Android Init Language --------------------- The Android Init Language consists of five broad classes of statements: Actions, Commands, Services, Options, and Imports. All of these are line-oriented, consisting of tokens separated by whitespace. The c-style backslash escapes may be used to insert whitespace into a token. Double quotes may also be used to prevent whitespace from breaking text into multiple tokens. The backslash, when it is the last character on a line, may be used for line-folding. Lines which start with a `#` (leading whitespace allowed) are comments. System properties can be expanded using the syntax `${property.name}`. This also works in contexts where concatenation is required, such as `import /init.recovery.${ro.hardware}.rc`. Actions and Services implicitly declare a new section. All commands or options belong to the section most recently declared. Commands or options before the first section are ignored. Services have unique names. If a second Service is defined with the same name as an existing one, it is ignored and an error message is logged. Init .rc Files -------------- The init language is used in plain text files that take the .rc file extension. There are typically multiple of these in multiple locations on the system, described below. `/system/etc/init/hw/init.rc` is the primary .rc file and is loaded by the init executable at the beginning of its execution. It is responsible for the initial set up of the system. Init loads all of the files contained within the `/{system,system_ext,vendor,odm,product}/etc/init/` directories immediately after loading the primary `/system/etc/init/hw/init.rc`. This is explained in more details in the [Imports](#imports) section of this file. Legacy devices without the first stage mount mechanism previously were able to import init scripts during mount_all, however that is deprecated and not allowed for devices launching after Q. The intention of these directories is: 1. /system/etc/init/ is for core system items such as SurfaceFlinger, MediaService, and logd. 2. /vendor/etc/init/ is for SoC vendor items such as actions or daemons needed for core SoC functionality. 3. /odm/etc/init/ is for device manufacturer items such as actions or daemons needed for motion sensor or other peripheral functionality. All services whose binaries reside on the system, vendor, or odm partitions should have their service entries placed into a corresponding init .rc file, located in the /etc/init/ directory of the partition where they reside. There is a build system macro, LOCAL\_INIT\_RC, that handles this for developers. Each init .rc file should additionally contain any actions associated with its service. An example is the userdebug logcatd.rc and Android.mk files located in the system/core/logcat directory. The LOCAL\_INIT\_RC macro in the Android.mk file places logcatd.rc in /system/etc/init/ during the build process. Init loads logcatd.rc during the mount\_all command and allows the service to be run and the action to be queued when appropriate. This break up of init .rc files according to their daemon is preferred to the previously used monolithic init .rc files. This approach ensures that the only service entries that init reads and the only actions that init performs correspond to services whose binaries are in fact present on the file system, which was not the case with the monolithic init .rc files. This additionally will aid in merge conflict resolution when multiple services are added to the system, as each one will go into a separate file. Versioned RC files within APEXs ------------------------------- With the arrival of mainline on Android Q, the individual mainline modules carry their own init.rc files within their boundaries. Init processes these files according to the naming pattern `/apex/*/etc/*rc`. Because APEX modules must run on more than one release of Android, they may require different parameters as part of the services they define. This is achieved, starting in Android T, by incorporating the SDK version information in the name of the init file. The suffix is changed from `.rc` to `.#rc` where # is the first SDK where that RC file is accepted. An init file specific to SDK=31 might be named `init.31rc`. With this scheme, an APEX may include multiple init files. An example is appropriate. For an APEX module with the following files in /apex/sample-module/apex/etc/: 1. init.rc 2. init.32rc 4. init.35rc The selection rule chooses the highest `.#rc` value that does not exceed the SDK of the currently running system. The unadorned `.rc` is interpreted as sdk=0. When this APEX is installed on a device with SDK <=31, the system will process init.rc. When installed on a device running SDK 32, 33, or 34, it will use init.32rc. When installed on a device running SDKs >= 35, it will choose init.35rc This versioning scheme is used only for the init files within APEX modules; it does not apply to the init files stored in /system/etc/init, /vendor/etc/init, or other directories. This naming scheme is available after Android S. Actions ------- Actions are named sequences of commands. Actions have a trigger which is used to determine when the action is executed. When an event occurs which matches an action's trigger, that action is added to the tail of a to-be-executed queue (unless it is already on the queue). Each action in the queue is dequeued in sequence and each command in that action is executed in sequence. Init handles other activities (device creation/destruction, property setting, process restarting) "between" the execution of the commands in activities. Actions take the form of: on [&& ]* Actions are added to the queue and executed based on the order that the file that contains them was parsed (see the Imports section), then sequentially within an individual file. For example if a file contains: on boot setprop a 1 setprop b 2 on boot && property:true=true setprop c 1 setprop d 2 on boot setprop e 1 setprop f 2 Then when the `boot` trigger occurs and assuming the property `true` equals `true`, then the order of the commands executed will be: setprop a 1 setprop b 2 setprop c 1 setprop d 2 setprop e 1 setprop f 2 If the property `true` wasn't `true` when the `boot` was triggered, then the order of the commands executed will be: setprop a 1 setprop b 2 setprop e 1 setprop f 2 If the property `true` becomes `true` *AFTER* `boot` was triggered, nothing will be executed. The condition `boot && property:true=true` will be evaluated to false because the `boot` trigger is a past event. Note that when `ro.property_service.async_persist_writes` is `true`, there is no defined ordering between persistent setprops and non-persistent setprops. For example: on boot setprop a 1 setprop persist.b 2 When `ro.property_service.async_persist_writes` is `true`, triggers for these two properties may execute in any order. Services -------- Services are programs which init launches and (optionally) restarts when they exit. Services take the form of: service [ ]*