Embedded Android


Embedded Android


Porting, Extending, and Customizing

by Karim Yaghmour.

Chapter 2 Internals Primer


App Developer’s View


https://developer.android.com/guide/

Android Concepts


Android apps are built as a combination of components that can be invoked individually.
  • Components
  • There are four main types of components:
    • Activities
    • An activity is the entry point for interacting with the user. It represents a single screen with a user interface. For example, an email app might have several activities: one activity that shows a list of new emails, another activity to compose an email, and another activity for reading emails. Although the activities work together to form a cohesive user experience in the email app, each one is independent of the others.
    • Services
    • A service is a general-purpose entry point for keeping an app running in the background to perform long-running operations or to perform work for remote processes.
    • Broadcast receivers
    • A broadcast receiver is a component that enables the system to deliver events to the app outside of a regular user flow, allowing the app to respond to system-wide broadcast announcements.
    • Content providers
    • A content provider manages a shared set of app data that you can store in the file system, in a SQLite database, on the web, or on any other persistent storage location that your app can access. Through the content provider, other apps can query or modify the data if the content provider allows it.
  • Intents
  • An Intent is a messaging object you can use to request an action from another app component. Three of the four component types — activities, services, and broadcast receivers—are activated by an asynchronous message called an intent. An intent is created with an Intent object, which defines a message to activate either a specific component (explicit intent) or a specific type of component (implicit intent).

Components can be declared as capable of dealing with given intent types using filters in the manifest file. Your app must declare all its components in this file, AndroidManifest.xml, which must be at the root of the app project directory.
The manifest does a number of things:
  • Declaring components
  • Declaring component capabilities
  • Declaring app requirements

You must declare all app components using the following elements in the manifest file:
  • <activity> elements for activities.
  • <service> elements for services.
  • <receiver> elements for broadcast receivers.
  • <provider> elements for content providers.
Except for the broadcast reciver, components included in your source but do not declare in the manifest are not visible to the system and, consequently, can never run.

An Android app requires resources that are separate from the source code, such as images, audio files, and anything relating to the visual presentation of the app.
For every resource that you include in your Android project, the SDK build tools define a unique integer ID, which you can use to reference the resource from your app code or from other resources defined in XML.
For example, the image file res/drawable/logo.png, the SDK tools generate a resource ID named R.drawable.logo. This ID maps to an app-specific integer, which you can use to reference the image and insert it in your user interface.

The Android SDK tools compile your code along with any data and resource files into an APK, an Android package, which is an archive file with an .apk suffix.
Each Android app lives in its own security sandbox, protected by the following Android security features:
  • The Android operating system is a multi-user Linux system in which each app is a different user.
  • By default, the system assigns each app a unique Linux user ID (the ID is used only by the system and is unknown to the app). The system sets permissions for all the files in an app so that only the user ID assigned to that app can access them.
  • Each process has its own virtual machine (VM), so an app's code runs in isolation from other apps.

Framework Intro


App Development Tools


Native Development



Overall Architecture





Linux Kernel

Wakelocks


Instead of letting the system be put to sleep at the user’s behest, an Androidized kernel is made to go to sleep as soon and as often as possible.
Wakelocks are provided to keep the system awake so that the important processing is being done.

Low-Memory Killer

Android’s low-memory killer applies the policies described in the app development documentation, weeding out processes hosting components that haven’t been used in a long time and are not high priority.
Android’s low-memory killer is based on the OOM adjustments mechanism available in Linux that enables the enforcement of different OOM kill priorities for different processes.
Android therefore attributes different OOM adjustment levels to different types of processes, the user-space policies are themselves applied by the init process at startup, and readjusted and partly enforced at runtime by the Activity Manager Service.

Binder


Android’s Binder mechanism is inspired by the OpenBinder code which is an RPC/IPC mechanism.
Binder attempts to provide remote object invocation capabilities without having to deal with a new OS.
The remote object can therefore be implemented in any desired language and may share the same process space as other remote services or have its own separate process.
Binder is a cornerstone of Android’s architecture. It’s what allows apps to talk the System Server, and it’s what apps use to talk to each others’ service components, app developers don’t actually talk to the Binder directly. Instead, they use the interfaces and stubs generated by the aidl tool.
The in-kernel driver part of the Binder mechanism is a character driver accessible through /dev/binder.

Anonymous Shared Memory (ashmem)

Ashmem is described as being similar to POSIX SHM “but with different behavior.”
  • It uses reference counting to destroy memory regions when all processes referring to them have exited
  • It will shrink mapped regions if the system is in need of memory.

Alarm


Android’s alarm driver is actually layered on top of the kernel’s existing Real-Time Clock (RTC) and High-Resolution Timers (HRT) functionalities.

In old versions of Linux, timers are only supported at a resolution of 1 jiffy. The length of a jiffy is dependent on the value of HZ in the Linux kernel, and is 1 millisecond on i386 and some other platforms, and 10 milliseconds on most embedded platforms.
Higher resolution timers are needed to allow the system to wake up and process data at more accurate intervals: timers with accuracy better than 1 jiffy.
In order to use high resolution timers, you need to enable the kernel support with "CONFIG_HIGH_RES_TIMERS=y".

Most computers have one or more hardware clocks which record the current "wall clock" time. These are called "Real Time Clocks" (RTCs).
RTCs should not be confused with the system clock, which is a software clock maintained by the kernel.
The system clock reports seconds and microseconds since a start point, defined to be the POSIX Epoch: 1970-01-01 00:00:00 +0000 (UTC). (One common implementation counts timer interrupts, once per "jiffy", at a frequency of 100, 250, or 1000 Hz.)
The system clock can only report time since system boot, the system clock will often be set to the current wall clock time using an RTC.

Linux application developers typically call the setitimer() system call to get a signal when a given time value expires, however, it doesn’t work when the system is suspended.
The kernel’s RTC driver is accessible through /dev/rtc and enables its users to use an ioctl() to, among other things, set an alarm that will be activated by the RTC hardware device in the system. That alarm will fire off whether the system is suspended or not

Android’s alarm driver uses the kernel’s HRT functionality to provide alarms to its users, if the system is about to suspend itself, it programs the RTC so that the system gets woken up at the appropriate time.

Logger


Most Linux distributions include two logging systems:
  • the kernel’s own log
  • typically accessed through the dmesg command,
  • the system logs
  • typically stored in files in the /var/log directory.
Android’s logging functionality manages a handful of separate kernel-hosted buffers for logging data coming from user-space, the driver maintains circular buffers in RAM where it logs every incoming event and returns immediately back to the caller.
Each buffer it manages is exposed as a separate entry within /dev/log/.
All user-space component rely on liblog, which provides a number of different logging functions.


The logcat utility is also relies on liblog.
It requires every event being logged to have a priority, a tag, and data.
When you type adb logcat on the host, the daemon actually launches the logcat command locally on the target to dump its “main” buffer and then transfers that back to the host to be shown on the terminal.

Hardware Support


The Linux Approach


The usual way to provide support for new hardware in Linux is to create device drivers and the corresponding hardware is thereafter generally accessible in user-space through entries in /dev.

Android’s General Approach

The Android stack typically relies on shared libraries provided by manufacturers to interact with hardware.
The hardware manufacture providing the shared library to implement the support for the HAL(Hardware Abstraction Layer).
Generally speaking, you can consider the HAL layer as being the hardware library loader .

Android does not in fact specify how the shared library and the driver or kernel subsystem should interact. Only the API provided by the shared library to the upper layers is specified by the HAL.
A system service corresponding to the type of hardware is typically responsible for loading and interfacing with the shared library.
To add the support for a given type of hardware, you need to understand the internals of the system service corresponding to your hardware.
The system service will be split in two parts: one part in Java and another part in C/C++.

Loading and Interfacing Methods


There are various ways in which system services and Android in general interact with the shared libraries implementing hardware support and hardware devices:
  • libhardware in HAL exposed a function hw_get_module() which relies on the classic dlopen() to load specific hardware- supporting shared library (a.k.a. a “module” in HAL terminology) libraries dynamically.
  • system services are simply linked against a given .so file at build time.
  • system services invoke dlopen() directly(the HAL is not used)
  • Sockets are sometimes used by system services or framework components to talk to a remote daemon or service that actually interacts with the hardware.
  • Some entries in sysfs (/sys) can be used to control the behavior of hardware and/or kernel subsystems
  • In some corner cases AOSP components directly access device nodes.
  • D-bus

Device Support Details


HardwareSystem ServiceInterface to User-Space HardwareInterface to Hardware
AudioAudio FlingerLinker-loadeda libaudio.soUp to hardware manufacturer, though ALSA is typical
BluetoothBluetooth ServiceSocket/D-Bus to BlueZBlueZ stack
CameraCamera ServiceLinker-loadedc libcamera.soUp to hardware manufacturer, sometimes Video4Linux
DisplaySurface FlingerHAL-loaded gralloc moduleUp to hardware manufacturer, /dev/fb0 or /dev/graphics/fb0
GPSLocation ManagerHAL-loaded gps moduleUp to hardware manufacturer
InputInput ManagerNative libui.so libraryEntries in /dev/input/
LightsLights ServiceHAL-loaded lights moduleUp to hardware manufacturer
MediaN/A, StageFright framework within Media Servicedlopen on libstagefrighthw.soUp to hardware manufacturer
Network interfacesNetwork Management ServiceSocket to netdioctl() on interfaces
Power managementPower Manager ServiceLinker-loaded libhardware_legacy.soEntries in /sys/power/ or, in older days, /sys/ android_power/
Radio (Phone)Phone ServiceSocket to rild, which itself does a dlopen()on manufacturer- provided .soUp to hardware manufacturer
StorageMount ServiceSocket to voldSystem calls and /sys entries
SensorsSensor ServiceHAL-loaded sensors moduleUp to hardware manufacturer
VibratorVibrator ServiceLinker-loaded libhardware_legacy.soUp to hardware manufacturer
WiFiWifi ServiceLinker-loaded libhardware_legacy.soClassic wpa_supplicant in most cases

Dalvik and Android’s Java


The code you write in Java gets compiled by a Java compiler into architecture-independent byte-code that is executed at runtime by a byte-code interpreter, also commonly referred to as a “virtual machine.”
Dalvik is Android’s Java virtual machine.
Android runtime (ART) is the managed runtime used by applications and some system services on Android.
ART and its predecessor Dalvik are compatible runtimes running Dex bytecode, so apps developed for Dalvik should work when running with ART.

The Java Development Kit (JDK) provides:
  • the Java compiler
  • the Java byte-code interpreter(JVM)
  • the Java libraries
Android actually relies on the JDK for the Java compiler at build time, it relies on Dalvik for JVM, and it relies on the Apache Harmony project for the JDK libraries.
For more information about the features and internals of Dalvik, you can also just go to YouTube and search for “Dan Bornstein Dalvik.”

JNI


It’s essentially a call bridge to other languages such as C and C++.
The AOSP relies massively on JNI to enable Java-coded services and components to interface with An‐ droid’s low-level functionality, which is mostly written in C and C++.

System Services


You cane use the service utility on an Android.

Chapter 3 AOSP Jump-Start


Inside the AOSP


A summary of the AOSP’s top-level directory:
  • art
  • bionic
  • Android’s custom C library
  • bootable
  • OTA, recovery mechanism and reference bootloader
  • build
  • Build system
  • cts
  • Comptability Test Suite
  • dalvik
  • Dalvik VM
  • developers
  • development
  • Development tools
  • device
  • Device-specific files and components
  • docs
  • Content of http://source.android.com
  • external
  • External projects imported into the AOSP
  • frameworks
  • Core components such as system services
  • hardware
  • HAL and hardware support libraries
  • libcore
  • Apache Harmony
  • libnativehelper
  • Helper functions for use with JNI
  • log
  • out
  • packages
  • Stock Android apps, providers, and IMEs
  • pdk
  • Platform Development Kit
  • platform_testing
  • prebuilts
  • Prebuilt binaries, including toolchains
  • sdk
  • Software Development Kit
  • system
  • “Embedded Linux” platform that houses Android
  • test
  • toolchain
  • tools
  • Various IDE tools
  • vendor

Directories prebuilt and external are mostly made up of content from other open source projects and include things like various GNU toolchain versions, kernel images, common libraries, and frameworks such as OpenSSL and WebKit, etc.
A lot of key components come from frameworks/base/, which is where the bulk of Android’s “brains” are located.



Using the Android Debug Bridge (ADB)


You can shell into the running emulator, or any real device connected through USB for that matter, using the adb tool:

$ adb shell
To exit an ADB shell session, all you need to do is type Ctrl-D.
When you start adb for the first time on the host, it starts a server in the background whose job is to manage the connections to all Android devices connected to the host.
You can actually ask that daemon what devices it sees:

$ adb devices
If there are multiple devices connected, you can tell it which device you want to talk to using the -s flag to identify the serial number of the device:

$ adb -s 0000021459584822 shell
adb can do a lot more than just give you a shell, you can run "adb" to get a list of commands.
For ex., use adb to dump the data contained in the main logger buffer:

$ adb logcat
You can also copy files to and from the device:

$ adb push data.txt /data/local 1 KB/s (87 bytes in 0.043s)
$ adb pull /proc/config.gz
95 KB/s (7087 bytes in 0.072s)
adb might just hang on because of the device connected, to kill the host-side daemon:

$ adb kill-server

Mastering the Emulator


Android Emulator is included with Android Studio.

The Android Emulator simulates various Android phone, tablet, Wear OS, and Android TV devices on your computer. It comes with predefined configurations for popular device types and can transfer data faster than a device connected over USB.

Each instance of the Android Emulator uses an Android Virtual Device (AVD) to configure its size, form factor, Android version, and various hardware characteristics. To effectively test your app, you should create an AVD that models each device type that your app is designed to support.

The AVD Manager is an interface you can launch from Android Studio that helps you create and manage AVDs.
To open the AVD Manager, click AVD Manager icon in the toolbar:
  • Click Create Virtual Device, at the bottom of the AVD Manager dialog.
  • The Select Hardware page appears.
  • Select a hardware profile, and then click Next.
  • If you don't see the hardware profile you want, you can create or import a hardware profile. The System Image page appears.
  • Select the system image for a particular API level
  • You need to Download the selected image, and then click Next. The API level of the target device is important, because your app won't be able to run on a system image with an API level that's less than that required by your app, as specified in the minSdkVersion attribute of the app manifest file. For more information about the relationship between system API level and minSdkVersion, see Versioning Your Apps. The Verify Configuration page appears.
  • Change AVD properties as needed, and then click Finish.
From the Your Virtual Devices page, you can perform the following operations on an emulator:
  • To run an emulator that uses an AVD
  • double-click the AVD. Or click the Launch button.
  • To stop a running emulator
  • right-click an AVD and select Stop. Or click Menu and select Stop.
  • To clear the data for an emulator and return it to the same state as when it was first defined
  • right-click an AVD and select Wipe Data. Or click Menu and select Wipe Data.

Chapter 4 The Build System


Within the context of Android’s build system, a “module” is any component of the AOSP that needs to be built. This might be a binary, an app package, a library, etc., and it might have to be built for the target or the host, but it’s still a “module” with regards to the build system.
The Android.mk files that specify how the local “module” is built.

The build system doesn’t generate object files(*.o) or any sort of intermediate output within the same location as the source files.
None of the existing AOSP directories are used in any of the output. Instead, the build system creates an out/ directory where it stores everything it generates.
Hence, a make clean is very much the same thing as an rm -rf out/.
Android uses a single global makefile for building the entire project based on module-provided .mk files.

Architecture


The entry point of the build system is the file build/core/main.mk.
Android’s build system pulls everything into a single makefile, each .mk file you see eventually becomes part of a single huge makefile that contains the rules for building all the pieces in the system.

Every time you type make, the aggregation of the .mk files happens.
What it’s doing is incorporating every Android.mk file it can find in the AOSP.
In build/core/main.mk:

subdir_makefiles := $(SOONG_ANDROID_MK) $(call first-makefiles-under,$(TOP)

Configuration


The build configuration is through the inclusion of build/make/core/config.mk.
This file sets up standard variables based on the current configuration and platform, it includes buildspec.mk at the top-level directory.
The build configuration can be configured either by the use of the envsetup.sh and lunch commands.

In addition to selecting which parts of the AOSP to build and which options to build them with, a BoardConfig.mk file describes the target to be built, such as the command line to be provided to the kernel, the base address at which the kernel should be loaded.
  • build/target/board/generic_$(ARCH)/BoardConfig.mk
  • device/VENDOR/*/TARGET_DEVICE/BoardConfig.mk
The device name (i.e., TARGET_DEVICE) is derived from the PRODUCT_DEVICE specified in the product.mk file provided for the TARGET_PRODUCT set in the configuration.

envsetup.sh


Mainly, it defines a series of shell commands that are useful.
You can use hmm to get the available commands.
  • lunch [product_name]-[build_variant]
  • croot
  • Changes directory to the top of the tree.
  • godir
  • Go to the directory containing a file.
  • m
  • Make (build) from the top level regardless of where you are
  • mm
  • Just make(build) the modules found in the current directory. Note that mm doesn’t rebuild the entire tree and, therefore, won’t regenerate AOSP images even if a dependent module has changed.
envsetup.sh also includes all the vendor-supplied scripts "vendorsetup.sh" which can be found under device/VENDOR.
This is how you end up with the "lunch" menu you saw. Note that the menu asks you to choose a combo. Essentially, this is a combination of a TARGET_PRODUCT and TARGET_BUILD_VARIANT
You can skip envsetup.sh and lunch if you copy the build/buildspec.mk.default into the top-level directory, rename it to buildspec.mk

Function Definitions


Because the build system is fairly large, he build system defines a large number of functions in the build/make/core/definitions.mk file.
Functions offer a variety of operations, including file lookup (e.g., all- makefiles-under and all-c-files-under), transformation (e.g., transform-c-to-o and transform-java-to-classes.jar), copying (e.g., copy-file-to-target), and utility (e.g., my-dir.)
Not only are these functions used throughout the rest of the build system’s components, acting as its core library, but they’re sometimes also directly used in modules’ Android.mk files.

Try grep define build/core/definitions.mk for an exhaustive list.

Call them via:

$(call FUNCTION, PARAM-1, PARAM-2)
or without parameters:

 $(call FUNCTION)
Here are some possibly interesting functions:
  • print-vars
  • print all Makefile variables, for debugging (not their values).
  • emit-line
  • output a line during building, to a file
  • dump-words-to-file
  • output a list of words to a file
  • copy-one-file
  • copy a file from one place to another (dest on target?)
  • all-subdir-makefiles
  • Recursively calls all Android.mk files, beginning in the current directory (Usage: include $(call all-subdir-makefiles)).

Build Variables

  • $(ANDROID_BUILD_TOP)
  • AOSP file system root folder
  • $(LOCAL_PATH)
  • Usually the current directory. Gets set by the developer/user in every Android.mk file. It get's overwritten in other Android.mk files down the file-tree (E.g. when you use include $(call all-subdir-makefiles)).
A workaround is:

 SAVED_LOCAL_PATH := $(call my-dir)
 include $(call all-subdir-makefiles)
 LOCAL_PATH:= $(SAVED_LOCAL_PATH)

Add a file directly to the output area

You can copy a file directly to the output area, without building anything, using the add-prebuilt-files function. The following line, extracted from prebuilt/android-arm/gdbserver/Android.mk copies a list of files to the EXECUTABLES directory in the output area:

$(call add-prebuilt-files, EXECUTABLES, $(prebuilt_files))

Steps for adding a new program to the Android source tree

  • make a directory under 'external'
  • e.g. ANDROID/external/myprogram
  • create your C/cpp files.
  • create Android.mk as clone of external/ping/Android.mk
  • Change the names ping.c and ping to match your C/cpp files and program name
  • add the directory name in ANDROID/build/core/main.mk after external/zlib as external/myprogram
  • make from the root of the source tree
  • your files will show up in the build output area, and in system images.
  • You can copy your file from the build output area, under out/target/product/..., if you want to copy it individually to the target (not do a whole install)

Grep macros and functions

  • cgrep PATTERN
  • Greps on all local C/C++ files.
  • ggrep PATTERN
  • Greps on all local Gradle files.
  • jgrep PATTERN
  • Greps on all local Java files.
  • resgrep PATTERN
  • Greps on all local res/*.xml files.
  • mangrep PATTERN
  • Greps on all local AndroidManifest.xml files.
  • mgrep PATTERN
  • Greps on all local Makefiles files.
  • sepgrep PATTERN
  • Greps on all local sepolicy files.
  • sgrep PATTERN
  • Greps on all local source files.
  • godir filename
  • Go to the directory containing a file

Main Make Recipes

build/core/Makefile:
  • boot image
  • 
    # #################################################################
    # Targets for boot/OS images
    # #################################################################
    ifneq ($(strip $(TARGET_NO_BOOTLOADER)),true)
      INSTALLED_BOOTLOADER_MODULE := $(PRODUCT_OUT)/bootloader
      ifeq ($(strip $(TARGET_BOOTLOADER_IS_2ND)),true)
        INSTALLED_2NDBOOTLOADER_TARGET := $(PRODUCT_OUT)/2ndbootloader
      else
        INSTALLED_2NDBOOTLOADER_TARGET :=
      endif
    else
      INSTALLED_BOOTLOADER_MODULE :=
      INSTALLED_2NDBOOTLOADER_TARGET :=
    endif # TARGET_NO_BOOTLOADER
    ifneq ($(strip $(TARGET_NO_KERNEL)),true)
      INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
    else
      INSTALLED_KERNEL_TARGET :=
    endif
    
  • system image
  • data image
Some things aren’t in this file:
  • Kernel images
  • There is no kernel part of the official AOSP releases, you need to find an Androidized kernel for your target, build it separately from the AOSP, and feed it to the AOSP. Some platforms put the kernel build script in the *.mk file under device/VENDOR.
  • NDK
  • The NDK’s build system is in ndk/build/
  • CTS
  • The rules for building the CTS are in build/core/tasks/cts.mk

Cleaning

The clean target itself is defined in build/core/main.mk. build/core/cleanbuild.mk defines the installcleantarget which is automatically invoked whenever you change TARGET_PRODUCT, TARGET_BUILD_VARIANT or PRODUCT_LOCALES.

Module Build Templates

Android is built from a top-down perspective, down to the level of AOSP modules’ Android.mk files. The Android build system looks for the first makefile in a hierarchy and doesn’t look in any subdirectories underneath the directory where one was found. Each template is tailored for a specific type of module, and module authors can use a set of documented variables, all prefixed by LOCAL_, to modulate the templates’ behavior and output. The build templates are provided in build/core/*.mk. Android.mk gets access to them through the include directive. For ex.,

    include $(BUILD_PACKAGE)
Android.mk files don’t actually include the .mk templates by name. Instead, they include a variable that is set to the corresponding .mk file.
VariableTemplate
BUILD_EXECUTABLEexecutable.mk
..
BUILD_PACKAGEpackage.mk
BUILD_KEY_CHAR_MAPkey_char_map.mk
By default, the build system has cleaning rules for each type of module. But you can specify your own rules in a CleanSpec.mk in case your module’s build does something the build system doesn’t generate by default and, therefore, wouldn’t typically know how to clean up.

Output

The build output operates in three stages and in two modes(host, target):

Build Recipes

The Default droid Build
When you run plain make, it’s as if you had typed:

    $ make droid
droid is in fact the default target as defined in build/make/core/main.mk. Here is a list of different make targets you can use to build different parts of the system:
  • make sdk
  • build the tools that are part of an SDK (adb, fastboot, etc.)
  • make snod
  • build the system image from the current software binaries
  • make services
  • make runtime
  • make droid
  • make droid is the normal build.
  • make all
  • make everything, whether it is included in the product definition or not
  • make clean
  • remove all built files (prepare for a new build). Same as rm -rf out//
  • make modules
  • shows a list of submodules that can be built (List of all LOCAL_MODULE definitions)
  • make [local_module]
  • make a specific module (note that this is not the same as directory name. It is the LOCAL_MODULE definition in the Android.mk file)
  • make clean-[local_module]
  • clean a specific module
  • make bootimage TARGET_PREBUILT_KERNEL=/path/to/bzImage
  • create a new boot image with custom bzImage
Seeing the Build Commands
If you want to see actual commands used to build the AOSP, like the gcc command lines for example, add the showcommands target to the build command line.

Building the SDK for Linux and Mac OS



Building the CTS

Building the NDK

Building a Single Module


Use the Launcher2 module (i.e., the Home screen) as an example:
  • build individual module
  • 
    $ make Launcher2
    
  • clean modules individually
  • 
    $ make clean-Launcher2
    
  • regenerate the system image to include your updated module
  • 
    $ make Launcher2 snod
    

If you’d ever like to build code against the AOSP and its Bionic library but don’t want to incorporate that into the AOSP, you can use a makefile such as the following to get the job done:

# Paths and settings
TARGET_PRODUCT = generic
ANDROID_ROOT = /home/karim/android/aosp-2.3.x
BIONIC_LIBC = $(ANDROID_ROOT)/bionic/libc
PRODUCT_OUT = $(ANDROID_ROOT)/out/target/product/$(TARGET_PRODUCT)
CROSS_COMPILE  = $(ANDROID_ROOT)/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
# Tool names
AS            = $(CROSS_COMPILE)as
AR            = $(CROSS_COMPILE)ar
CC            = $(CROSS_COMPILE)gcc
CPP           = $(CC) -E
LD            = $(CROSS_COMPILE)ld
NM            = $(CROSS_COMPILE)nm
OBJCOPY       = $(CROSS_COMPILE)objcopy
OBJDUMP       = $(CROSS_COMPILE)objdump
RANLIB        = $(CROSS_COMPILE)ranlib
READELF       = $(CROSS_COMPILE)readelf
SIZE          = $(CROSS_COMPILE)size
STRINGS       = $(CROSS_COMPILE)strings
STRIP         = $(CROSS_COMPILE)strip
export AS AR CC CPP LD NM OBJCOPY OBJDUMP RANLIB READELF SIZE STRINGS STRIP

# Build settings
CFLAGS = -O2 -Wall -fno-short-enums
HEADER_OPS = -I$(BIONIC_LIBC)/arch-arm/include \
  -I$(BIONIC_LIBC)/kernel/common \
  -I$(BIONIC_LIBC)/kernel/arch-arm
LDFLAGS = -nostdlib -Wl,-dynamic-linker,/system/bin/linker \
  $(PRODUCT_OUT)/obj/lib/crtbegin_dynamic.o \
  $(PRODUCT_OUT)/obj/lib/crtend_android.o \
  -L$(PRODUCT_OUT)/obj/lib -lc -ldl


# Installation variables
EXEC_NAME = example-app
INSTALL = install
INSTALL_DIR = $(PRODUCT_OUT)/system/bin

# Files needed for the build
OBJS          = example-app.o
# Make rules
all: example-app
.c.o:
        $(CC) $(CFLAGS) $(HEADER_OPS) -c $<
example-app: ${OBJS}
        $(CC) -o $(EXEC_NAME) ${OBJS} $(LDFLAGS)
install: example-app
        test -d $(INSTALL_DIR) || $(INSTALL) -d -m 755 $(INSTALL_DIR)
        $(INSTALL) -m 755 $(EXEC_NAME) $(INSTALL_DIR)
clean:
        rm -f *.o $(EXEC_NAME) core
distclean:
        rm -f *~
        rm -f *.o $(EXEC_NAME) core
You don’t need to care about either envsetup.sh or lunch, you can just go ahead:

make
This won’t add your binary to any of the images generated by the AOSP. Its value is only during debugging

Building Recursively, In-Tree


Signing Builds for Release


  • Release keys
  • The Android tree includes test-keys under build/target/product/security. Building an Android OS image using make will sign all .apk files using the test-keys. Since the test-keys are publicly known, anybody can sign their own .apk files with the same keys. For this reason it is critical to sign any publicly released or deployed Android OS image with a special set of release-keys that only you have access to.

    To generate your own unique set of release-keys, run these commands from the root of your Android tree:

    
    subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
    mkdir ~/.android-certs
    for x in releasekey platform shared media; do \
        ./development/tools/make_key ~/.android-certs/$x "$subject"; \
      done
    
    

    To generate a release image, use:

    
    make dist
    ./build/tools/releasetools/sign_target_files_apks \
        -o \    # explained in the next section
        -d ~/.android-certs out/dist/*-target_files-*.zip \
        signed-target_files.zip
    
    

Basic AOSP Hacks

To hack the AOSP to fit your needs.

Adding a Device to the build system

Assume you work for a company called VENDOR and try to add the support for the DEVICE.

Add the new device to the build system:
  • creating an entry for our new device in device
  • mkdir -p device/VENDOR/DEVICE
  • adding an device/VENDOR/DEVICE/AndroidProducts.mk file to describe this AOSP product
  • 
    PRODUC_MAKEFILES :=  $(LOCAL_DIR)/DEVICE.mk
    
    and it’s described in device/VENDOR/DEVICE/DEVICE.mk:
    
        $(call inherit-product, device/VENDOR/common/languages_full.mk)
        $(call inherit-product, build/make/target/product/product_launched_with_n.mk)
        DEVICE_PACKAGE_OVERLAYS :=
        PRODUCT_PACKAGES +=
        PRODUCT_COPY_FILES +=
        PRODUCT_NAME := DEVICE_name
        PRODUCT_DEVICE := DEVICE
        PRODUCT_MODEL := Full Android on the device
    
    • the inherit-product function tell the build system to pull in other product descriptions as the basis of ours.
    • languages_full.mk will pull in a vast number of locales, and product_launched_with_n.mk will make sure the API level. If you have several products sharing the same set of packages, you may want to create a device/VENDOR/common/ directory containing the shared packages.
    • DEVICE_PACKAGE_OVERLAYS
    • PRODUCT_PACKAGES
    • Allows us to specify packages we’d like to have this product include in addition to those specified in the products we’re already inheriting from.
    • PRODUCT_COPY_FILES
    • Allows us to list specific files we’d like to see copied to the target’s filesystem and the location where they need to be copied.
    • PRODUCT_NAME
    • TARGET_PRODUCT derives from this variable. It's part of the combo parameter to lunch.
    • PRODUCT_DEVICE
    • TARGET_DEVICE derives from this variable. PRODUCT_DEVICE has to match an entry in device/VENDOR/, since that’s where the build looks for the corresponding BoardConfig.mk.
    • PRODUCT_MODEL
    • The name of this product as provided in the “Model number”. This variable actually gets stored as the ro.prod uct.model global property accessible on the device.
  • information regarding the board the device is using
  • device/VENDOR/common/BoardConfig.mk device/VENDOR/DEVICE/BoardConfig.mk
  • a conventional Android.mk
  • device/VENDOR/common/Android.mk:
    
    ifneq ($(filter coyotepad,$(TARGET_DEVICE)),)
    
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    include $(call all-makefiles-under,$(LOCAL_PATH))
    
    endif
    
  • visible to envsetup.sh and lunch
  • Add a vendorsetup.sh in your device’s directory device/VENDOR/DEVICE/:
    
        add_lunch_combo PRODUCT_NAME-eng
    
    and make sure that it’s executable:
    
    $ chmod 755 vendorsetup.sh
    
After the building is don, you can check the file out/target/product/DEVICE/system/build.prop.
It contains various global properties that will be available at runtime on the target and that relate to our configuration and build.

Adding an App


Creating a HelloWorld! app :
  • device/VENDOR/DEVICE/HelloWorld
  • 
    
    
  • create an file device/VENDOR/DEVICE/HelloWorld/Android.mk
  • 
        LOCAL_PATH:= $(call my-dir)
        include $(CLEAR_VARS)
        LOCAL_MODULE_TAGS := optional
        LOCAL_SRC_FILES := $(call all-java-files-under, src)
        LOCAL_PACKAGE_NAME := HelloWorld
        include $(BUILD_PACKAGE)
    
    Given that we’re tagging this module as optional, it won’t be included by default in the AOSP build.

Adding an App Overlay


Overlays are a mech‐ anism included in the AOSP to allow device manufacturers to change the resources provided (such as for apps), without actually modifying the original resources included in the AOSP.

To use this capability, you must create an overlay tree and tell the build system about it.

EVICE_PACKAGE_OVERLAYS := device/VENDOR/DEVICE/overlay
So long as you put the files in the same hierarchy as they are found in the AOSP but within device/VENDOR/DEVICE/overlay/, they’ll be taken into account by the build system.


Adding a Native Tool or Daemon

You can add your custom native tools and daemons as subdirectories of device/VENDOR/DEVICE/. You’ll need to provide an Android.mk in the directory containing the code to build that module:

    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := hello-world
    LOCAL_MODULE_TAGS := optional
    LOCAL_SRC_FILES := hello-world.cpp
    LOCAL_SHARED_LIBRARIES := liblog
    include $(BUILD_EXECUTABLE)

Adding a Native Library

You’ll need an Android.mk in the directory containing the code to build your library:

    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := libmylib
    LOCAL_MODULE_TAGS := optional
    LOCAL_PRELINK_MODULE := false
    LOCAL_SRC_FILES := $(call all-c-files-under,.)
    include $(BUILD_SHARED_LIBRARY)
To use this library, you must add it to the libraries listed by the Android.mk file of whichever binaries depend on it:

    LOCAL_SHARED_LIBRARIES := libmylib

CHAPTER 5 Hardware Primer


An SoC comprises a CPU and a bunch of peripheral controllers all on the same integrated circuit (IC) die.
Android essentially runs on that SoC and therefore controls and/ or accesses everything on the board from that vantage point.

The Baseband Processor


You might wonder why there are two separate processors instead of just one: Application Processor (AP) and the Baseband Processor (BP).
  • In US, the software controlling the radio may not be modified without authorization.
  • there are hard real-time constraints on the operation of the radio functions
If your embedded system isn’t a handset, or doesn’t have radio functions, just assume that you don’t have a BP or any of the components attached to it.
Notice that the BP has its own flash and RAM. This guarantees that the certified software running on the BP is isolated from the software running on the AP, and that the real-time OS (RTOS) running on the BP is focused on running a single thing: the radio’s operation. The BP, for instance, runs software implementing the GSM stack. Notice also that the SIM card and an RF transceiver are connected to the BP. The transceiver takes care of the actual RF transmission and reception with the tower, while the SIM card is used to identify the handset user with the mobile network operator (MNO).

Core Components


SoC chips have the required modules to do basic reads and boot directly from a partition on the eMMC.
“Internal” storage typically designates the onboard eMMC, while “external” storage designates the user-removable SD card attached to the phone or tablet.

The PMIC(Power Management IC) is connected to the SoC through SPI, I2C, and/or GPIO. It can generate interrupts for such things as low battery or the charger being attached.

Real-World Interaction


As suggested by its Compatibility Definition Document (CDD), a system built with Android should allow rich user interaction

Memory Layout and Mapping

The mapping between applications and devices works because the CPU manages two entirely separate address spaces through its memory management unit (MMU). Using its MMU, the CPU can present a virtual address space to applications running on it and still use a physical address space to communicate with components connected to it through its address bus.

The flash storage is divided in two.
The first part contains the bootloader and starts at the lowest memory address available.
The rest of flash is occupied by the system.
Upon startup, the bootloader reads the kernel from the system part into RAM and jumps to the kernel's start routine. From there on, the startup is carried out by the kernel.
After the initialization task is completed by the kernel, the application processes are started
The OS collaborates with the MMU to implement a virtual address space wherein each process gets a similar view.
Virtual addresses eventually map to actual physical addresses, but the conversion is automatically handled by the MMU based on OS-maintained page tables.

The kernel is always seen as occupying an address range starting at 0xC000 0000 as its low address(kernel space). Android apps, on the other hand, occupy the entire address space below that address(user space).

Chapter 6 Native User-Space


“Native user-space” means all the user-space components that run outside the Dalvik virtual machine.
Such binaries usually have direct access to the root filesystem and the native libraries included in the system. Their capabilities are restricted only by the filesystem rights granted to them and their effective UID and GID. They aren’t subject to any of the restrictions imposed on a typical Android app by the Android Framework because they are running outside it.

Filesystem Layout


The kernel mounts the RAM disk image generated by the build system as its root filesystem and launches the init process found in that image. That init process’s configuration files will cause a number of additional images and virtual filesystems to be mounted onto existing directory entries in the root filesystem.

The RAM disk image is meant to be as small as possible, and its sole purpose is to provide the initial skeleton required to get the system going.

The two main directories in which Android operates are /system and /data. These directories are not used for standard Linux distributions that it might be possible to host Android side by side with a common Linux distribution on the same root filesystem.

Prepare the tools simg2img and make_ext4fs


    Download the https://android.googlesource.com/platform/system/extras repository:
    
    git clone https://android.googlesource.com/platform/system/extras
    
  • Check out a revision of your choice:
  • 
    cd extras
    git checkout android-4.1.1_r1
    
  • Compile simg2img:
  • 
    cd ext4_utils
    gcc -o simg2img -lz sparse_crc32.c simg2img.c
    
  • Compile make_ext4fs
  • 
    cd extras/ext4_utils
    gcc -o make_ext4fs -lz make_ext4fs_main.c make_ext4fs.c ext4fixup.c ext4_utils.c allocate.c backed_block.c output_file.c contents.c extent.c indirect.c uuid.c sha1.c sparse_crc32.c wipe.c
    

Modifying .img Files


You would need to go through the process: unzip -modify - rezip

ramdisk.img


  • Decompress the image
  • 
       mkdir root
       cd root
       gunzip -c ramdisk.img | cpio -i
      
  • Change the decompressed files
  • Make the new image
  • 
       /out/host/linux-x86/bin/mkbootfs root/ | ./out/host/linux-x86/bin/minigzip > ramdisk.img.new
      

system.img


  • Decompress the image
  • 
       out/host/linux-x86/bin/simg2img system.img system.img.raw
       # mount to directory "mnt-system"
       mkdir mnt-system
       sudo mount -t ext4 -o loop system.img.raw  mnt-system
      
  • Change the decompressed files
  • Modify any .so or apk in the mnt-system/ directory
  • Make the new image
  • The source code of these tools also in system/extra/ext4_utils/, you can follow the instructions in How to pack and unpack system.img and userdata.img from an Android factory image to compile the make_ext4fs.
    
       sudo out/host/linux-x86/bin/make_ext4fs -s -T -1 -S file_contexts -L system -l 512M -a system system.img.new mnt-system/
       sudo umount mnt-system/
      

Instead of having to reflash the whole big system.img, one can selective update any binary in /system folder on running target:


  adb remount
  adb push out/target/product/elfin/system/priv-app/TVLauncher/TVLauncher.apk /system/priv-app/TVLauncher/TVLauncher.apk
  adn sync
  
 

userdata.img


  • Decompress the image
  • 
       out/host/linux-x86/bin/simg2img userdata.img userdata.img.raw
       # mount to directory "mnt-userdata"
       mkdir mnt-userdata
       sudo mount -t ext4 -o loop userdata.img.raw  mnt-userdata
      
  • Change the decompressed files
  • Modify any .so or apk in the mnt-userdata/ directory
  • Make the new image
  • 
       sudo out/host/linux-x86/bin/make_ext4fs -s -l 512M -a userdata userdata.img.new mnt-userdata/
       sudo umount mnt-system/
      



cache.img


This is empty ext4 fs image.
Make the new image,

  mkdir mnt-point/
  sudo out/host/linux-x86/bin/make_ext4fs -s -l 256M -a cache cache.img mnt-cache/
 

boot.img


boot.img = zImage + ramdisk.img
zImage = kernel image
ramdisk.img = out/target/product/elfin/root/
The boot image is generated by:

 out/host/linux-x86/bin/mkbootimg --kernel zImage --ramdisk ramdisk.img --base adress --cmdline "kernel_arguments"  --board board -o boot.img.new
 
 

vendor.img




Libraries

Android relies on about 100 dynamically loaded libraries, all stored in the /system/lib directory.

Init


After the kernel finished initializing itself and the drivers it contains, the kernel starts just one user-space process, the init process.
This process is then responsible for spawning all other processes and services in the system.
In embedded Linux systems, the classic package that provides init is BusyBox.
Android introduces its own custom init.

Configuration language


Android’s init defines its own configuration semantics and relies on changes to global properties to trigger the execution of specific instructions.
  • The main configuration file for init is usually stored as /init.rc.
  • The device-specific configuration file stored as /init.(device_name).rc.
You can get a high degree of control over the system’s startup and its behavior by modifying those files.

Global properties


Some of the properties set at build time are stored in the /system/build.prop file and include the build date and build system details.
Use the getprop command to get the current list of properties and their values.

udev events


udev relies on runtime events generated by the kernel every time hardware is added or removed from the system.
In Android, these events are handled by the ueventd daemon built as part of Android’s init and accessed through a symbolic link from /sbin/ueventd to /init. To know which entries to create in /dev, ueventd relies on the /ueventd.rc and /ueventd.(device_name).rc files.

Toolbox

Busybox is a package which all commands are then made to be symbolic links to the busybox command.
Android doesn’t use BusyBox but includes its own tool, Toolbox, that basically functions in the very same way, using symbolic links to the toolbox command.

Daemons


Android’s init starts a few key daemons that continue to run throughout the lifetime of the system.
  • ueventd
  • servicemanager
  • vold
  • netd
  • debuggerd
  • rild
  • Zygote
  • mediaserver
  • dbus-daemon
  • bluetoothd
  • installd
  • keystore
  • system_server
  • adbd

Command-Line Utilities


/system/bin contains the majority of them, but some “extras” are in /system/xbin, and a handful are in /sbin.

adb

Its two most important components are:
  • the adb server running on the host
  • The adb server is started automatically whenever the adb command is invoked on the command line. The adb server opens socket 5037 on the host and listens for connections.
  • the adbd daemon running on the target

Basic Local Commands

  • adb start-server
  • adb kill-server
  • adb version
  • adb devices
  • adb connect host[:port]
  • adb disconnect host[:port]
  • adb wait-for-device
  • adb -d get-serialno
  • adb -s serial_no get-state
  • adb shell [command]
  • adb -d logcat [-b log_buffer_name]
  • adb -d bugreport
Dalvik implements the Java Debug Wire Protocol (JDWP), thereby allowing you to use the regular Java debugger jdb to debug your apps.

Filesystem Commands

  • adb push filename /data/local
  • adb pull filename /data/local
  • adb remount
  • remount filesystems in read-write mode
  • adb install app.apk
  • Install a new app, this will invoke the pm (short for “package manager”) command on the target.
  • adb uninstall full_app_package_name

State-Altering Commands


  • adb reboot
  • This actually invokes the re boot() system call on the target’s kernel
  • adb reboot bootloader
  • reboot in the bootloader
  • adb reboot recovery
  • reboot in the recovery mode
adbd’s privileges will depend on the TARGET_BUILD_VAR IANT chosen to build the AOSP:
  • user
  • adbd won’t run as root
  • userdebug
  • With this build, you can ask adb to restart as root by typing:
    
    $ adb root
    

To use TCP/IP instead of USB:

adb -s serial_no tcpip 7878
this will set the service.adb.tcp.port global property on the target to 7878 and restart the adbd daemon. You can then connect to it like above:

$ adb connect 192.168.202.79:7878
To switch it back to USB, you can type this:

$ adb -s 192.168.172.79:7878 usb

Toolbox:
  • cat
  • chmod
  • chown
  • cmp
  • cp
  • date
  • dd
  • df
  • dmesg
  • du
  • grep
  • hd
  • id
  • ifconfig
  • iftop
  • insmod
  • ionice
  • ln
  • md5
  • kill
  • ls
  • lsmod
  • lsof
  • mkdir
  • mount
  • mv
  • netstat
  • printenv
  • ps
  • ps -A is listing all processes in android-8.0-O release.
    
    # ps --help  
    usage: ps [-AadefLlnwZ] [-gG GROUP,] [-k FIELD,] [-o FIELD,] [-p PID,] [-t TTY,] [-uU USER,]  
      
    List processes.  
      
    Which processes to show (selections may be comma separated lists):  
      
    -A      All processes  
    -a      Processes with terminals that aren't session leaders  
    -d      All processes that aren't session leaders  
    -e      Same as -A  
    -g      Belonging to GROUPs  
    -G      Belonging to real GROUPs (before sgid)  
    -p      PIDs (--pid)  
    -P      Parent PIDs (--ppid)  
    -s      In session IDs  
    -t      Attached to selected TTYs  
    -T      Show threads  
    -u      Owned by USERs  
    -U      Owned by real USERs (before suid)  
      
    Output modifiers:  
      
    -k      Sort FIELDs in +increasing or -decreasting order (--sort)  
    -M      Measure field widths (expanding as necessary)  
    -n      Show numeric USER and GROUP  
    -w      Wide output (don't truncate fields)  
      
    Which FIELDs to show. (Default = -o PID,TTY,TIME,CMD)  
      
    -f      Full listing (-o USER:12=UID,PID,PPID,C,STIME,TTY,TIME,ARGS=CMD)  
    -l      Long listing (-o F,S,UID,PID,PPID,C,PRI,NI,ADDR,SZ,WCHAN,TTY,TIME,CMD)  
    -o      Output FIELDs instead of defaults, each with optional :size and =title  
    -O      Add FIELDS to defaults  
    -Z      Include LABEL  
      
    Command line -o fields:  
      
      ARGS     CMDLINE minus initial path     CMD  Command (thread) name (stat[2])  
      CMDLINE  Command line (argv[])          COMM Command filename (/proc/$PID/exe)  
      COMMAND  Command file (/proc/$PID/exe)  NAME Process name (argv[0] of $PID)  
      
    Process attribute -o FIELDs:  
      
      ADDR  Instruction pointer               BIT   Is this process 32 or 64 bits  
      CPU   Which processor running on        ETIME   Elapsed time since PID start  
      F     Flags (1=FORKNOEXEC 4=SUPERPRIV)  GID     Group id  
      GROUP Group name                        LABEL   Security label  
      MAJFL Major page faults                 MINFL   Minor page faults  
      NI    Niceness (lower is faster)  
      PCPU  Percentage of CPU time used       PCY     Android scheduling policy  
      PGID  Process Group ID  
      PID   Process ID                        PPID    Parent Process ID  
      PRI   Priority (higher is faster)       PSR     Processor last executed on  
      RGID  Real (before sgid) group ID       RGROUP  Real (before sgid) group name  
      RSS   Resident Set Size (pages in use)  RTPRIO  Realtime priority  
      RUID  Real (before suid) user ID        RUSER   Real (before suid) user name  
      S     Process state:  
            R (running) S (sleeping) D (device I/O) T (stopped)  t (traced)  
            Z (zombie)  X (deader)   x (dead)       K (wakekill) W (waking)  
      SCHED Scheduling policy (0=other, 1=fifo, 2=rr, 3=batch, 4=iso, 5=idle)  
      STAT  Process state (S) plus:  
            < high priority          N low priority L locked memory  
            s session leader         + foreground   l multithreaded  
      STIME Start time of process in hh:mm (size :19 shows yyyy-mm-dd hh:mm:ss)  
      SZ    Memory Size (4k pages needed to completely swap out process)  
      TCNT  Thread count                      TID     Thread ID  
      TIME  CPU time consumed                 TTY     Controlling terminal  
      UID   User id                           USER    User name  
      VSZ   Virtual memory size (1k units)    %VSZ    VSZ as % of physical memory  
      WCHAN What are we waiting in kernel for  
    
  • reboot
  • renice
  • rm
  • rmdir
  • rmmod
  • route
  • sleep
  • sync
  • top
  • touch
  • umount
  • uptime
  • vmstat

Boot timing


init records some boot timing information in system properties:
  • ro.boottime.init
  • Time after boot in ns (via the CLOCK_BOOTTIME clock) at which the first stage of init started.
  • ro.boottime.init.selinux
  • How long it took the first stage to initialize SELinux.
  • ro.boottime.init.cold_boot_wait
  • How long init waited for ueventd's coldboot phase to end.
  • ro.boottime.service-name
  • Time after boot in ns (via the CLOCK_BOOTTIME clock) that the service was first started. For ex.,
    
     getprop ro.boottime.bootanim  
                                         
    14573890508
    
    
    This is the sorted list for starting time of services:
    
    
    [ro.boottime.init.cold_boot_wait]:      [343]
    [ro.boottime.init.mount_all.default]:   [999]
    
    [ro.boottime.init.selinux]:            [1811]
    [ro.boottime.init]:                    [2690]
    
    [ro.boottime.ueventd]:           [4985370514]
    
    [ro.boottime.vndservicemanager]: [6413975291]
    [ro.boottime.hwservicemanager]:  [6409472513]
    [ro.boottime.servicemanager]:    [6407880031]
    [ro.boottime.logd]:              [6406522920]
    
    [ro.boottime.nxserver]:          [6982565846]
    [ro.boottime.nxssd]:             [6985401735]
    
    
    [ro.boottime.vendor.boot-hal-1-0]:            [10064207363]
    [ro.boottime.vendor.keymaster-3-0]:           [10072800251]
    [ro.boottime.vold]:                           [10086374881]
    [ro.boottime.update_verifier_nonencrypted]:   [10472909807]
    [ro.boottime.hwcbinder]:                      [10463487325]
    [ro.boottime.netd]:                           [10546403548]
    [ro.boottime.zygote]:                         [10548066251]
    [ro.boottime.logd-reinit]:                    [10739392621]
    [ro.boottime.vendor.drm-hal-1-0]:             [10842572658]
    [ro.boottime.vendor.configstore-hal]:         [10833104066]
    [ro.boottime.vendor.drm-clearkey-hal-1-1]:    [10877488844]
    [ro.boottime.vendor.camera-provider-2-4-ext]: [10813270547]
    [ro.boottime.vendor.cas-hal-1-0]:             [10827322214]
    [ro.boottime.vendor.audio-hal-2-0]:           [10806470621]
    [ro.boottime.vendor.bluetooth-1-0]:           [10809773103]
    [ro.boottime.healthd]:                        [10802831621]
    [ro.boottime.hidl_memory]:                    [10800248214]
    
    
    [ro.boottime.vendor.drm-playready-hal-1-1]:   [11057987510]
    
    [ro.boottime.vendor.drm-widevine-hal-1-1]:    [11312583806]
    [ro.boottime.vendor.hwcomposer-2-1]:          [11413200028]
    [ro.boottime.vendor.health-hal-2-0]:          [11418875954]
    [ro.boottime.vendor.gralloc-2-0]:             [11408103436]
    [ro.boottime.vendor.gatekeeper-1-0]:          [11405293806]
    [ro.boottime.vendor.light-hal-2-0]:           [11420836103]
    [ro.boottime.vendor.memtrack-hal-1-0]:        [11425082732]
    [ro.boottime.vendor.power-hal-1-0]:           [11436459547]
    [ro.boottime.vendor.thermal-hal-1-0]:         [11450939473]
    [ro.boottime.vendor.tv-input-1-0]:            [11596201436]
    [ro.boottime.vendor.cec-hal-1-0]:             [11515599917]
    [ro.boottime.dpthak-hal-1-0]:                 [11610388139]
    [ro.boottime.dspscvext-hal-1-0]:              [11624504547]
    [ro.boottime.prdysc-hal-1-0]:                 [11640132214]
    [ro.boottime.sdbhak-hal-1-0]:                 [11650355399]
    [ro.boottime.vendor.wifi_hal_legacy]:         [11605604806]
    [ro.boottime.vendor.sfhak-hal-1-0]:           [11704580288]
    [ro.boottime.audioserver]:                    [11715227695]
    [ro.boottime.surfaceflinger]:                 [11781523843]
    [ro.boottime.thermalservice]:                 [11795234213]
    [ro.boottime.lmkd]:                           [11716943065]
    
    [ro.boottime.console]:                        [12235263398]
    
    [ro.boottime.media]:                  [13371257361]
    [ro.boottime.mediadrm]:               [13365624583]
    [ro.boottime.mediaextractor]:         [13367349212]
    [ro.boottime.mediametrics]:           [13369200138]
    [ro.boottime.adbd]:                   [13344453620]
    [ro.boottime.wificond]:               [13376630472]
    [ro.boottime.cameraserver]:           [13355411027]
    [ro.boottime.traced_probes]:          [13353444324]
    [ro.boottime.drm]:                    [13357061101]
    [ro.boottime.incidentd]:              [13358782768]
    [ro.boottime.installd]:               [13360544398]
    [ro.boottime.keystore]:               [13362261250]
    [ro.boottime.traced]:                 [13347719213]
    [ro.boottime.statsd]:                 [13372931879]
    [ro.boottime.storaged]:               [13374700027]
    [ro.boottime.vendor.media.omx]:       [13506928101]
    [ro.boottime.usbd]:                   [13526911694]
    [ro.boottime.update_engine]:          [13525073953]
    [ro.boottime.gatekeeperd]:            [13509408620]
    [ro.boottime.tombstoned]:             [13518850286]
    [ro.boottime.perfprofd]:              [13510986768]
    
    [ro.boottime.bootanim]: [14573890508]
    
    
Boot events can be found via:

adb logcat -b events | grep boot

01-01 00:00:14.862  2959  2959 I boot_progress_start: 12711
01-01 00:00:18.217  2959  2959 I sysui_histogram: [boot_zygote_init,16066]
01-01 00:00:18.218  2959  2959 I sysui_multi_action: [757,804,799,boot_zygote_init,801,16066,802,1]
01-01 00:00:18.236  2959  2959 I boot_progress_preload_start: 16086
01-01 00:00:21.093  2959  2959 I boot_progress_preload_end: 18942
01-01 00:00:21.856  3206  3206 I boot_progress_system_run: 19705
01-01 00:00:21.858  3206  3206 I sysui_histogram: [boot_system_server_init,19705]
01-01 00:00:21.858  3206  3206 I sysui_multi_action: [757,804,799,boot_system_server_init,801,19705,802,1]
01-01 00:00:22.725  3206  3206 I sysui_histogram: [boot_package_manager_init_start,20575]
01-01 00:00:22.725  3206  3206 I sysui_multi_action: [757,804,799,boot_package_manager_init_start,801,20575,802,1]
01-01 00:00:22.760  3206  3206 I boot_progress_pms_start: 20610
01-01 00:00:22.897  3206  3206 I boot_progress_pms_system_scan_start: 20747
01-01 00:00:23.052  3206  3206 I boot_progress_pms_data_scan_start: 20902
01-01 00:00:23.060  3206  3206 I boot_progress_pms_scan_end: 20910
01-01 00:00:23.251  3206  3206 I boot_progress_pms_ready: 21101
01-01 00:00:23.334  3206  3206 I sysui_histogram: [boot_package_manager_init_ready,21183]
01-01 00:00:23.334  3206  3206 I sysui_multi_action: [757,804,799,boot_package_manager_init_ready,801,21183,802,1]
03-12 08:07:15.118  3206  3206 I boot_progress_ams_ready: 34268
03-12 08:07:17.017  3206  3206 I sysui_histogram: [boot_system_server_ready,36167]
03-12 08:07:17.017  3206  3206 I sysui_multi_action: [757,804,799,boot_system_server_ready,801,36167,802,1]
03-12 08:07:18.790  3206  3223 I boot_progress_enable_screen: 37940
03-12 08:07:19.185  3029  3544 I sf_stop_bootanim: 38335
03-12 08:07:19.187  3206  3231 I wm_boot_animation_done: 38338
03-12 08:07:19.209  3206  3231 I sysui_histogram: [framework_locked_boot_completed,38]
03-12 08:07:19.209  3206  3231 I sysui_multi_action: [757,804,799,framework_locked_boot_completed,801,38,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,ro.boottime.init,801,2690,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,boot_reason,801,1,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,ro.boottime.init.selinux,801,1811,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,boottime.bootloader.total,801,0,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,factory_reset_boot_complete,801,58,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,system_boot_reason,801,67,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,boot_complete,801,38,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,last_boot_time_utc,801,1552378039,802,1]
03-12 08:07:19.397  3571  3571 I sysui_multi_action: [757,804,799,time_since_last_boot,801,-883,802,1]
03-12 08:07:19.398  3571  3571 I sysui_multi_action: [757,804,799,boot_complete_no_encryption,801,38,802,1]
03-12 08:07:19.398  3571  3571 I sysui_multi_action: [757,804,799,ro.boottime.init.cold_boot_wait,801,343,802,1]
03-12 08:07:19.398  3571  3571 I sysui_multi_action: [757,804,799,absolute_boot_time,801,38,802,1]
03-12 08:07:19.398  3571  3571 I sysui_multi_action: [757,804,799,factory_reset_boot_complete_no_encryption,801,58,802,1]
03-12 08:07:19.607  3206  3223 I sysui_histogram: [framework_boot_completed,38]
03-12 08:07:19.607  3206  3223 I sysui_multi_action: [757,804,799,framework_boot_completed,801,38,802,1]
03-12 08:07:23.338  3206  3772 I sysui_histogram: [boot_mount_all_duration_default,999]
03-12 08:07:23.338  3206  3772 I sysui_multi_action: [757,804,799,boot_mount_all_duration_default,801,999,802,1]
03-12 08:07:23.341  3206  3772 I sysui_histogram: [boot_fs_stat_userdata,11]
03-12 08:07:23.341  3206  3772 I sysui_multi_action: [757,804,799,boot_fs_stat_userdata,801,11,802,1]
03-12 08:07:23.342  3206  3772 I sysui_histogram: [boot_fs_stat_cache,1035]
03-12 08:07:23.342  3206  3772 I sysui_multi_action: [757,804,799,boot_fs_stat_c

Bootcharting


This version of init contains code to perform “bootcharting”: generating log files that can be later processed by the tools provided by http://www.bootchart.org/.
Bootchart is a tool for performance analysis and visualization of the GNU/Linux boot process. Resource utilization and process information are collected during the boot process and are later rendered in a PNG, SVG or EPS encoded chart.

To activate bootchart on a device:

adb shell 'touch /data/bootchart/enabled'

Don‘t forget to delete this file when you’re done collecting data!
The log files are written to /data/bootchart/. A script is provided to retrieve them and create a bootchart.tgz file that can be used with the bootchart command-line utility:

$ sudo apt-get install pybootchartgui

$ # grab-bootchart.sh uses $ANDROID_SERIAL.
$ adb devices
serialNo  device

$ export ANDROID_SERIAL=serialNo

$ $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh

The bootchart will show init as if it started running at 0s.


A handy script named compare-bootcharts.py can be used to compare the start/end time of selected processes.
For ex.,
system/core/init/compare-bootcharts.py base-bootchart-dir exp-bootchart-dir

process: baseline experiment (delta) - Unit is ms (a jiffy is 10 ms on the system)
------------------------------------
/init: 50 40 (-10)
/system/bin/surfaceflinger: 4320 4470 (+150)
/system/bin/bootanimation: 6980 6990 (+10)
zygote64: 10410 10640 (+230)
zygote: 10410 10640 (+230)
system_server: 15350 15150 (-200)
bootanimation ends at: 33790 31230 (-2560)

Optimizing Boot Times




  • Optimizing I/O efficiency
  • When a process reads sequentially a file the kernel starts reading some data in advance to reduce the amount of time that a process have to wait for data to be available, so this parameter "Readahead" sets the maximum amount of data that the kernel reads ahead for a single file. In order to avoid processes waiting for data to be available, this parameter sets the maximum amount of data that the kernel reads ahead for a single file. Default: 128KB
    
      echo 640 > /sys/block/mmcblk0/queue/read_ahead_kb
    
    Try set it on Android via /init.rc:
    
    on late-fs
      # boot time fs tune
        # boot time fs tune
        write /sys/block/sda/queue/iostats 0
        write /sys/block/sda/queue/scheduler cfq
        write /sys/block/sda/queue/iosched/slice_idle 0
        write /sys/block/sda/queue/read_ahead_kb 2048
        write /sys/block/sda/queue/nr_requests 256
        write /sys/block/dm-0/queue/read_ahead_kb 2048
        write /sys/block/dm-1/queue/read_ahead_kb 2048
    
    on property:sys.boot_completed=1
        # end boot time fs tune
        write /sys/block/sda/queue/read_ahead_kb 512
        ...
    

    Improving I/O efficiency is critical to making boot time faster, and reading anything not necessary should be deferred until after boot. fsck check is typically forced during reboot on your Linux installation.

    • Skip fsck check once
    • To skip it once, you simply need to add fastboot to kernel boot options. "fastboot" was added in 2.6.29 and removed again in 2.6.30.
    • To permanently disable fsck check on a hard disk partition
    • You need to edit the /etc/fstab file to change dump and pass. Setting both to 0 will tell fsck to skip checking the partitions. The format used in /etc/fstab:
      
      <file system> <dir> <type> <options> <dump> <pass>
      
      <dump> - Is used by the dump utility to decide when to make a backup. fsck reads the <pass> number and determines in which order/priority (0,1,2) the file systems should be checked. The root file system should have the highest priority, 1, all other file systems you want to have checked should get a 2. File systems with a value 0 will not be checked by the fsck utility.
  • Optimizing boot animation
  • fsck is triggered periodically due to safety reasons, causing a delay in starting the bootanimation service. To make bootanimation start early, split the fstab mount into two phases:
    • In the early phase, mount only the partitions (such as system/ and vendor/) that don't require run checks, then start boot animation services and its dependencies (such as servicemanager and surfaceflinger).
    • In the second phase, mount partitions (such as data/) that do require run checks.
    Boot animation will be started much faster (and in constant time) regardless of fsck.

Debugging init


If it is required to debug a service from its very start, the sigstop service option is added. This option will send SIGSTOP to a service immediately before calling exec.


stop logd
setprop ctl.sigstop_on logd
start logd
ps -e | grep logd
> logd          4343     1   18156   1684 do_signal_stop 538280 T init

To resume the service,


kill -SIGCONT 4343

Global properties


A set of global properties that can be accessed from anywhere in the system.
  • getprop
  • list all the properties with their current values
  • setprop prop val
  • getprop prop
  • watchprops
  • monitor properties being changed in real-time
The property will, however, disappear at the next reboot unless its name starts with persist.
For ex.,



In that case, a file with the property’s full name will be created in /data/property containing the property’s value.

Input events


Android relies heavily on Linux’s input layer to get the user’s input events.
  • getevent
  • getevent continuously displays events as they come in until you type Ctrl-C. The output format is event type, event code, and event value.
  • sendevent
  • Note, getevent’s output is hexadecimal, sendevent’s input is decimal.

Controlling services


You can start and stop services using the following:

    start (servicename)
    stop (servicename)

Logging


You can add your own events to Android’s logger:

    log [-p (prioritychar)] [-t (tag)] (message)
    prioritychar should be one of:
    v,d,i,w,e

ioctl


Toolbox provides a utility to enable developers to invoke drivers’ ioctl() functions.

ioctl [-l ] [-a ] [-rdh]  
      -l    Length of io buffer
      -a   Size of each argument (1-8)
      -r            Open device in read only mode
      -d            Direct argument (no iobuffer)
      -h            Print help
this will be highly driver-specific.

Wiping the device


Toolbox’s wipe command:

    wipe 
    system means '/system'
    data means '/data'

Android-specific commands


  • nandread
  • This utility is for reading the contents of a NAND flash device to a file:
    
    nandread [-d ] [-f ] [-s ] [-vh]
          -d    Read from 
          -f   Write to 
          -s   Number of spare bytes in file (default 64)
          -R         Raw mode
          -S  Start offset (default 0)
    -L  -v
    -h
    Length (default 0)
    Print info
    Print help
    
  • newfs_msdos
  • This command allows you to format a device as a VFAT filesystem:
    
    newfs_msdos [ -options ] device [disktype]
        where the options are:
        -@ create file system at specified offset
        -B get bootstrap from file
        -C create image file with specified size
        -F FAT type (12, 16, or 32)
        -I volume ID
        -L volume label
        -N don't create file system: just print out parameters
        -O OEM string
        -S bytes/sector
        -a sectors/FAT
        -b block size
        -c sectors/cluster
        -e root directory entries
        -f standard format
        -h drive heads
        -i file system info sector
        -k backup boot sector
        -m media descriptor
        -n number of FATs
        -o hidden sectors
        -r reserved sectors
        -s file system size (sectors)
        -u sectors/track
    
  • schedtop
  • real-time monitoring of the kernel’s scheduler
    
    schedtop [-d delay] [-bitamun]
                -d refresh every  seconds
                -b batch - continuous prints instead of refresh
                -i hide idle tasks
                -t show threads
                -a use alternate screen
                -m use millisecond precision
                -u use microsecond precision
                -n use nanosecond precision
    
  • logcat
  • Logcat is a command-line tool that dumps a log of system messages, including stack traces when the device throws an error and messages that you have written from your app with the Log class.
    
    # logcat --help
    Usage: logcat [options] [filterspecs]
    
    
    You can run logcat as an adb command or directly in a shell prompt of your connected device.
    
    adb logcat
    
    Options:
    • -b buffer
    • The default used log buffers are: main, system, crash. The Android logging system keeps multiple circular buffers for log messages, and not all of the log messages are sent to the default circular buffer. To see additional log messages, you can run the logcat command with the -b option, to request viewing of an alternate circular buffer.
      • radio: View the buffer that contains radio/telephony related messages.
      • events: View the interpreted binary system event buffer messages.
      • main: View the main log buffer (default) does not contain system and crash log messages.
      • system: View the system log buffer (default).
      • crash: View the crash log buffer (default).
      • all: View all buffers.
      • default: Reports main, system, and crash buffers.
    • -c, --clear
    • Clear (flush) the selected buffers and exit. The default buffer set is main, system and crash. To clear all of the buffers, use -b all -c.
    • -d
    • Dump the log to the screen and exits.
    • -e expr, --regex=expr
    • Only print lines where the log message matches expr where expr is a regular expression.
    • -n count
    • Set the maximum number of rotated logs to count.
    • -t count
    • Print only the most recent number of lines. This option includes -d functionality.
    • -t 'time'
    • Print the most recent lines since the specified time.
      
      adb logcat -t '01-26 20:52:41.820'
      
    • Filtering log output
    • Filter expressions let you indicate to the system the tags-priority combinations that you are interested in.
      
      priority/tag
      
      The priority is one of the following character values, ordered from lowest to highest priority:
      • V: Verbose (lowest priority)
      • D: Debug
      • I: Info
      • W: Warning
      • E: Error
      • F: Fatal
      • S: Silent (highest priority, on which nothing is ever printed)
      The tag of a log message is a short string indicating the system component from which the message originates . A filter expression follows this format
      
      tag:priority ...
      
      Messages for that tag at or above the specified priority are written to the log. You can supply any number of tag:priority specifications in a single filter expression. The following example suppresses all log messages except those with the tag "ActivityManager", at priority "Info" or above, and all log messages with tag "MyApp", with priority "Debug" or above:
      
      adb logcat ActivityManager:I MyApp:D *:S
      
      
    • Control log output format
    • When starting logcat, you can specify the output format you want by using the -v option:
      
      logcat [-v format]
      
      You can specify one of the supported output formats listed below:
      • brief: Display priority, tag, and PID of the process issuing the message.
      • long: Display all metadata fields and separate messages with blank lines.
      • process: Display PID only.
      • raw: Display the raw log message with no other metadata fields.
      • tag: Display the priority and tag only.
      • thread: A legacy format that shows priority, PID, and TID of the thread issuing the message.
      • threadtime (default): Display the date, invocation time, priority, tag, PID, and TID of the thread issuing the message.
      • time: Display the date, invocation time, priority, tag, and PID of the process issuing the message.
    • Logging from code
    • The Log class allows you to create log entries in your code that display in the logcat tool. Common logging methods include:
      • verbose
      • Log.v(tag, String)
      • debug
      • Log.d(tag, String)
      • information
      • Log.i(tag, String)
      • warning
      • Log.w(tag, String)
      • error
      • Log.e(tag, String)
      Java code:
      
      Log.i("MyActivity", "MyClass.getView() — get item number " + position);
      
      
  • netcfg
  • 
    netcfg [interface {dhcp|up|down}]
    
  • debuggerd
  • This daemon is actually started by init early during startup. It remains dormant until a user-space process crashes. When the crash happens, it creates a tombstone file in /data/tombstones
  • check_prereq
  • This allows you to check whether the currently running build is older than a given timestamp:
    
    # check_prereq 1336847591
    current build time: [1336162137] new build time: [1336847591]
    

Init


After init is started by the kernel, it essentially reads its configuration files, prints out a boot logo or text to the screen, opens a socket for its property service, and starts all the daemons and services that bring up the entire Android user-space.


init includes an implementation of the udev hotplug events handler.
One of the first things init does is check whether it was invoked as ueventd.
init checks the command-line that was used to invoke it, and if it was invoked through the /sbin/ueventd symbolic link to /init, then init immediately runs as ueventd.

The next thing init does is create and mount /dev, /proc, and /sys.
then reads the /init.rc and /init.device_name.rc files, parses their content into its internal structures, and proceeds to initialize the system based on a mix of its configuration files and built-in rules.

Once all initialization is done, init then enters an infinite loop:
  • restarts any services that might have exited and that need restarting
  • polls file descriptors it needs to handle
  • Such as the property service’s socket (this is how setprop property setting requests are serviced), input events.

Configuration Files


The main way to control init’s behavior is through its configuration files.
The root directory (/) includes the actual init binary itself and its two configurations files: init.rc and init.device_name.rc. The device_name is extracted from /proc/cpuinfo.
init reads both files before it executes any of the instructions.
init’s .rc files contain a series of declarations that fall in one of two types: actions and services. Each declarative section starts with a keyword identifying the type of declaration: on for an action and service for a service.
Only an action, however, results in the execution of commands. Service declarations serve only to describe services; they don’t actually start anything. The services are typically started or stopped when an action is triggered.

Android Init Language


The init language is used in plain text files that take the .rc file extension.
The Android Init Language consists of 5 classes of statements: Actions, Commands, Services, Options, and Imports.
  • All of these are line-oriented, consisting of tokens separated by whitespace.
  • 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}.
  • 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.

/init.rc is the primary .rc file and is loaded by the init executable at the beginning of its execution.
All of the files contained within the /{system,vendor,odm}/etc/init/ directories are loaded immediately after loading the primary /init.rc .
The intention of these directories is:
  • /system/etc/init/
  • is for core system items such as SurfaceFlinger, MediaService, and logcatd.
  • /vendor/etc/init/
  • is for SoC vendor items such as actions or daemons needed for core SoC functionality.
  • /odm/etc/init/
  • is for device manufacturer items such as actions or daemons needed for motion sensor or other peripheral functionality.

Imports


import path
Parse an init config file, extending the current configuration. If path is a directory, each file in the directory is parsed as a config file. It is not recursive, nested directories will not be parsed.

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.

on trigger [&& trigger]*
       command
       command
       ...
Actions are added to the queue and executed based on the order that the file that contains them was parsed.
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
The commands are defined in system/core/init/builtins.cpp:


// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits::max();
    // clang-format off
    static const Map builtin_functions = {
        {"bootchart",               {1,     1,    {false,  do_bootchart}}},
        ...
        {"setprop",                 {2,     2,    {true,   do_setprop}}},
        ...
        {"write",                   {2,     2,    {true,   do_write}}},
    };
    // clang-format on
    return builtin_functions;

}
static Result do_setprop(const BuiltinArguments& args) {
    property_set(args[1], args[2]);
    return Success();
}


Triggers


Triggers are strings which can be used to match certain kinds of events and used to cause an action(a sequence of commands) to occur.
Triggers are subdivided into:
  • event triggers
  • Event triggers are strings triggered by the ‘trigger’ command or pre-defined by the QueueEventTrigger() function within the init executable(init.cpp):(built-in actions defined)
    • early-init
    • Built-in actions are executed:
      • coldboot: Check that ueventd has populated /dev.
      • Initialize property service’s internal data structures.
      • Set up handler for keychords.
      • Initialize the console and display startup text or image.
    • init
    • charger
    • late-init
  • property triggers
  • After all pre-defined trigger commnds are executed, init runs all property-triggered commands based on current property values. Property triggers are strings triggered when a named property changes value to a given new value(‘property:=value’) or when a named property changes value to any new value(‘property:=*’). Actions can also be taken based on property value changes:
    
     on property:name=value
    
    
    A very good example of this is the default init.rc’s starting or stopping the adbd daemon based on the toggling of the “USB debugging” checkbox in Settings:
    
        on property:persist.service.adb.enable=1
            start adbd
        on property:persist.service.adb.enable=0
            stop adbd
    
Here’s the list of predefined and property triggers that is executed in order by the init configuration file:
  • early-init
  • init
  • charger
  • late-init
  • early-fs
  • fs
  • post-fs
  • early-boot
  • boot

Commands used for actions:

  • chmod octal-mode path
  • Change file access permissions.
  • chown owner group path
  • Change file owner and group.
  • class_start serviceclass
  • Start all services of the specified class if they are not already running. See the start entry for more information on starting services.
  • class_stop serviceclass
  • Stop and disable all services of the specified class if they are currently running.
  • class_reset serviceclass
  • Stop all services of the specified class if they are currently running, without disabling them. They can be restarted later using class_start.
  • class_restart serviceclass
  • Restarts all services of the specified class.
  • copy src dst
  • Copies a file. Similar to write, but useful for binary/large amounts of data. Regarding to the src file, copying from symbolic link file and world-writable or group-writable files are not allowed. Regarding to the dst file, the default mode created is 0600 if it does not exist. And it will be truncated if dst file is a normal regular file and already exists.
  • domainname name
  • Set the domain name.
  • enable servicename
  • Turns a disabled service into an enabled one as if the service did not specify disabled. If the service is supposed to be running, it will be started now. Typically used when the bootloader sets a variable that indicates a specific service should be started when needed. E.g.
    
    on property:ro.boot.myfancyhardware=1
        enable my_fancy_service_for_my_fancy_hardware
    
  • exec [ seclabel [ user [ group\* ] ] ] -- command [ argument\* ]
  • Fork and execute command with the given arguments. The command starts after “--” so that an optional security context, user, and supplementary groups can be provided. No other commands will be run until this one finishes. seclabel can be a - to denote default. Properties are expanded within argument. Init halts executing commands until the forked process exits.
  • exec_background [ seclabel [ user [ group\* ] ] ] -- command [ argument\* ]
  • Fork and execute command with the given arguments. This is handled similarly to the exec command. The difference is that init does not halt executing commands until the process exits for exec_background.
  • exec_start service
  • Start a given service and halt the processing of additional init commands until it returns. The command functions similarly to the exec command, but uses an existing service definition in place of the exec argument vector.
  • export name value
  • Set the environment variable name equal to value in the global environment (which will be inherited by all processes started after this command is executed)
  • hostname name
  • Set the host name.
  • ifup interface
  • Bring the network interface interface online.
  • insmod [-f] path [options]
  • Install the module at path with the specified options. -f: force installation of the module even if the version of the running kernel and the version of the kernel for which the module was compiled do not match.
  • load_all_props
  • Loads properties from /system, /vendor, et cetera. This is included in the default init.rc.
  • load_persist_props
  • Loads persistent properties when /data has been decrypted. This is included in the default init.rc.
  • loglevel level
  • Sets the kernel log level to level. Properties are expanded within level.
  • mkdir path [mode] [owner] [group]
  • Create a directory at path, optionally with the given mode, owner, and group. If not provided, the directory is created with permissions 755 and owned by the root user and root group. If provided, the mode, owner and group will be updated if the directory exists already.
  • mount_all fstab [ path ]\* [--option]
  • Calls fs_mgr_mount_all on the given fs_mgr-format fstab and imports .rc files at the specified paths (e.g., on the partitions just mounted) with optional options “early” and “late”. Refer to the section of “Init .rc Files” for detail.
  • mount type device dir [ flag\* ] [options]
  • Attempt to mount the named device at the directory dir _flag_s include “ro”, “rw”, “remount”, “noatime”, ... options include “barrier=1”, “noauto_da_alloc”, “discard”, ... as a comma separated string, eg: barrier=1,noauto_da_alloc
  • restart iservice
  • Stops and restarts a running service, does nothing if the service is currently restarting, otherwise, it just starts the service.
  • restorecon path [ path\* ]
  • Restore the file named by path to the security context specified in the file_contexts configuration. Not required for directories created by the init.rc as these are automatically labeled correctly by init.
  • restorecon_recursive path [ path\* ]
  • Recursively restore the directory tree named by path to the security contexts specified in the file_contexts configuration.
  • rm path
  • Calls unlink(2) on the given path. You might want to use “exec -- rm ...” instead (provided the system partition is already mounted).
  • rmdir path
  • Calls rmdir(2) on the given path.
  • readahead file|dir [--fully]
  • Calls readahead(2) on the file or files within given directory. Use option --fully to read the full file content.
  • setprop name value
  • Set system property name to value. Properties are expanded within value.
  • setrlimit resource cur max
  • Set the rlimit for a resource. This applies to all processes launched after the limit is set. It is intended to be set early in init and applied globally. resource is best specified using its text representation (‘cpu’, ‘rtio’, etc or ‘RLIM_CPU’, ‘RLIM_RTIO’, etc). It also may be specified as the int value that the resource enum corresponds to.
  • start service
  • Start a service running if it is not already running. Note that this is not synchronous, and even if it were, there is no guarantee that the operating system‘s scheduler will execute the service sufficiently to guarantee anything about the service’s status. This creates an important consequence that if the service offers functionality to other services, such as providing a communication channel, simply starting this service before those services is not sufficient to guarantee that the channel has been set up before those services ask for it. There must be a separate mechanism to make any such guarantees.
  • stop service
  • Stop a service from running if it is currently running.
  • swapon_all fstab
  • Calls fs_mgr_swapon_all on the given fstab file.
  • symlink target path
  • Create a symbolic link at path with the value target
  • sysclktz mins_west_of_gmt
  • Set the system clock base (0 if system clock ticks in GMT)
  • trigger event
  • Trigger an event. Used to queue an action from another action.
  • umount path
  • Unmount the filesystem mounted at that path.
  • verity_load_state
  • Internal implementation detail used to load dm-verity state.
  • verity_update_state mount-point
  • Internal implementation detail used to update dm-verity state and set the partition.mount-point.verified properties used by adb remount because fs_mgr can't set them directly itself.
  • wait path [ timeout ]
  • Poll for the existence of the given file and return when found, or the timeout has been reached. If timeout is not specified it currently defaults to five seconds.
  • wait_for_prop name value
  • Wait for system property name to be value. Properties are expanded within value. If property name is already set to value, continue immediately.
  • write path content
  • Open the file at path and write a string to it with write(2). If the file does not exist, it will be created. If it does exist, it will be truncated. Properties are expanded within content.

Services

Services are programs which init launches and (optionally) restarts when they exit.

service name pathname [ argument ]*
       option
       option
       option 
       ...

Service options are modifiers to services. They affect how and when init runs the service.
  • class name [ name\* ]
  • Specify class names for the service. All services in a named class may be started or stopped together.
  • console [console]
  • This service needs a console.
  • critical
  • This is a device-critical service. If it exits more than four times in four minutes, the device will reboot into recovery mode.
  • disabled
  • This service will not automatically start with its class. It must be explicitly started by name or by interface name.
  • group groupname [ groupname\* ]
  • Run this service under the given group(s).
  • ioprio class priority
  • Sets the IO priority and IO priority class for this service via the SYS_ioprio_set syscall. class must be one of “rt”, “be”, or “idle”. priority must be an integer in the range 0 - 7.
  • keycodes keycode [ keycode\* ]
  • Start the service whenever the given keycodes are activated.
  • oneshot
  • Do not restart the service when it exits.
  • onrestart
  • Execute a Command when service restarts.
  • seclabel seclabel
  • Change to ‘seclabel’ before exec'ing this service.
  • setenv name value
  • Set the environment variable name to value in the launched process.
  • socket name type perm [ user [ group [ seclabel ] ] ]
  • Create a unix domain socket named /dev/socket/name and pass its fd to the launched process. type must be “dgram”, “stream” or “seqpacket”.
  • user username
  • Change to ‘username’ before exec'ing this service.

Global Properties


Android’s global properties serve as a trivial way of sharing important values globally among all parts of the stack.
Property service is part of init process, there are two ways that this property service is exposed to the rest of the system:
  • /dev/socket/property_service
  • This is a Unix domain socket that processes can open to talk to the property service and have it set and/or change the value of global properties.
  • /dev/__properties__
  • This is an “invisible” file that is created within the tmpfs-mounted /dev and that is memory-mapped into the address space. It’s through this mapped region that descendants of init (i.e., all user-space processes in the system) can read global properties via the memory-mapped file.
The property service essentially maintains a RAM-based workspace where it stores all global properties. Because of the way it’s set up, only the property service can write to this workspace, though any process can read from it. Hence we have a single-writer/multiple-readers configuration.
The specific permissions required to set certain global properties(through the /dev/socket/property_service) are hardcoded in system/core/init/property_service.c:

/* White list of permissions for setting property services. */
struct {
    const char *prefix;
    unsigned int uid;
    unsigned int gid;
} property_perms[] = {
    { "net.rmnet0.", AID_RADIO, 0 },
    ...
    { "ril.", AID_RADIO, 0 },
    { "gsm.", AID_RADIO, 0 },
    ...
    { "hw.", AID_SYSTEM, 0 },
    { "sys.", AID_SYSTEM, 0 },
    ...
    { "persist.security.", AID_SYSTEM, 0 },
    { NULL, 0, 0 }
}
For instance, the above says that :
  • only processes running as the system user can change properties that start with sys. or hw.
  • only processes running as the radio user can change properties that start with ril. or gsm.
The system/core/include/private/android_filesystem_config.h file provides the list of pre‐defined system users, as well as the rights and ownership assigned to everything in the system.

#define AID_ROOT    0  /* traditional unix root user *
...
static const struct android_id_info android_ids[] = {
        { "root",AID_ROOT, }
        ...
}
Note that:
  • processes running as root can change any property they wish.
  • properties whose names starts with ro. can be set only once. (these three characters "ro." are stripped from the name before permissions are checked)

To interact with the property service:
  • the command line
  • You can use getprop, setprop, and watchprops. You should use getprop after the initial boot of your system to get your device’s base list of properties.
  • in Java
  • Look at the frameworks/base/core/java/android/os/SystemProperties.java class and use this class,
    
     import android.os.SystemProper
    
  • in C
  • Look at system/core/include/cutils/properties.h and use the functions in this header
    
     #include <cutils/properties.h>
    

Properties follow a certain naming convention and are processed differently based on their prefixes:
  • ro.*
  • Properties that start with this prefix are meant to be read-only. Hence, they can be set only once in the system’s lifetime. The only way to change their value is to change the source of the information to which they are set and reboot the system. For ex., hardware and ro.build.id
  • persist.*
  • Properties marked with this prefix are committed to persistent storage each time they are set. For ex., persist.service.adb.enable
  • ctl.*
  • There’s a ctl.start and a ctl.stop, and setting them doesn’t actually result in any property being saved. When the property service receives a request to set a ctl.* property, it starts/stops the service whose name is provided as the value for the property. The Surface Flinger, for instance, does this as part of its startup:
    
           property_set("ctl.start", "bootanim");
    
    This effectively results in the bootanim service being started by init. The bootanim service and its options are described in the init.rc file.
  • net.change
  • Whenever a net.* property is changed, net.change is set to the name of that property. Hence, net.change always contains the name of the last net.* property that was modified.

Several parts are involved in creating the final set of global properties found in any single Android device:
  • The build system
  • You can find them in the root/ and system/ subdirectories of out/target/product/PRODUCT_DEVICE/:
    • /system/build.prop
    • This one contains information about the build itself. Most of the content of these files is generated by the core AOSP build code(makefile) in build/core/. For ex.,
      
      PRODUCT_PROPERTY_OVERRIDES += \
                 wifi.interface=eth0 \
                 wifi.supplicant_scan_interval=15 \
                 dalvik.vm.heapsize=32m
      
    • /default.prop
    • This one contains default values for certain key properties
    The files contain one-liner name-value pairs. Most of the content of these files is gen‐ erated by the core AOSP build code in build/core/ .
  • Additional property files
  • you can add your own target-specific /system/default.prop and device-specific /data/local.prop, both of which will be read by the property service.
  • .rc files
  • the init.rc file and init.device_name.rc
  • code
  • Some parts of the code also set properties. The Connectivity Service, for instance, does this:
    
                   SystemProperties.set("net.hostname", name);
    
  • entries in the /data/property directory
  • This is used to store the value of properties at run-time. Properties found in /data/property are read by the property service at startup and restored. Any property that starts with persist. is stored as an individual file in that directory and each of the files there contains the value assigned to the property.
There is, therefore, no definitive dictionary or official list of global properties that are to be expected across Android devices.


ueventd


ueventd is one of the very first services started by the default init.rc.


Based on the events ueventd receives and its configuration files, it automatically creates device node entries in /dev.
These entries under /dev are re-created based on ueventd’s configuration files,

/dev/node mode use group
When a uevent corresponding to node occurs, ueventd creates /dev/node with access permissions set to mode and assigns the entry to user/group.

Boot Logo


Android devices’ screens typically go through 4 stages during boot:
  • Kernel boot screen
  • The kernel might either maintain the screen black until init starts, or it might display a static logo, built as part of the kernel image, to the framebuffer.
  • Init boot logo
  • This is a text string or an image displayed very early by init while it initializes the console.
  • Boot animation
  • This is a series of animated images, possibly a loop, that displays during the Surface Flinger’s start up.
    • frameworks/native/include/ui/ISurfaceComposer.h
    • 
      class BnSurfaceComposer : public BnInterface<ISurfaceComposer>
      {
      public:
          enum {
              // Note: BOOT_FINISHED must remain this value, it is called from
              // Java by ActivityManagerService.
              BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
      ...
      }
      
    • frameworks/native/libs/gui/ISurfaceComposer.cpp
    • 
          virtual void bootFinished()
          {
              Parcel data, reply;
              data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
              remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
          }
      
      status_t BnSurfaceComposer::onTransact(
          uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
      {
          switch(code) {
              ...
              case BOOT_FINISHED: {
                  CHECK_INTERFACE(ISurfaceComposer, data, reply);
                  bootFinished();
              } break;
              ...
      }
      
      
    • frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    • 
      
      status_t SurfaceFlinger::readyToRun()
      {
          ALOGI(  "SurfaceFlinger's main thread ready to run. "
                  "Initializing graphics H/W...");
      ...
          // start boot animation
          startBootAnim();
          return NO_ERROR;
      }
      
      void SurfaceFlinger::startBootAnim() {
          // start boot animation
          property_set("service.bootanim.exit", "0");
          property_set("ctl.start", "bootanim");
      }
      
      void SurfaceFlinger::bootFinished()
      {
          const nsecs_t now = systemTime();
          const nsecs_t duration = now - mBootTime;
          ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
          mBootFinished = true;
          // wait patiently for the window manager death
          const String16 name("window");
          sp window(defaultServiceManager()->getService(name));
          if (window != 0) {
              window->linkToDeath(static_cast(this));
          }
          // stop boot animation
          // formerly we would just kill the process, but we now ask it to exit so it
          // can choose where to stop the animation.
          property_set("service.bootanim.exit", "1");
      }
      
      
    • frameworks/base/cmds/bootanimation/Android.mk
    • 
      ...
      LOCAL_MODULE:= bootanimation
      LOCAL_INIT_RC := bootanim.rc
      ...
      
    • frameworks/base/cmds/bootanimation/bootanim.rc
    • 
      service bootanim /system/bin/bootanimation
          class core animation
          user graphics
          group graphics audio
          disabled
          oneshot
          writepid /dev/stune/top-app/tasks
      
    • frameworks/base/cmds/bootanimation/BootAnimation.cpp
    • 
      
      static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
      
      void BootAnimation::checkExit() {
          // Allow surface flinger to gracefully request shutdown
          char value[PROPERTY_VALUE_MAX];
          property_get(EXIT_PROP_NAME, value, "0");
          int exitnow = atoi(value);
          if (exitnow) {
              requestExit();
              mCallbacks->shutdown();
          }
      }
      
      bool BootAnimation::playAnimation(const Animation& animation)
      {
      ...
                      nsecs_t now = systemTime();
                      nsecs_t delay = frameDuration - (now - lastFrame);
      ...
                      if (delay > 0) {
                          struct timespec spec;
                          spec.tv_sec  = (now + delay) / 1000000000;
                          spec.tv_nsec = (now + delay) % 1000000000;
                          int err;
                          do {
                              err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
                          } while (err<0 && errno == EINTR);
                      }
                      checkExit();
                  }
                  usleep(part.pause * ns2us(frameDuration));
      
      }
      
      
  • Home screen
  • This is the starting screen of the Launcher, which is activated at the complete end of the boot sequence. You’ll need to dig into the Launcher’s sources if you’d like to customize what it displays.




CHAPTER 7 Android Framework


The Android Framework includes:
  • the android.* packages
  • the System Services
  • the Android Runtime
  • some of the native daemons
Sourcewise, the Android Framework is typically composed of all the code located in the frameworks/ directory of the AOSP.
Practically, it can be thought as everything that runs on top of native user-space.

Kick-Starting the Framework


We can make the AOSP to generate Tiny Android, go to the AOSP’s source directory and type this:

$ BUILD_TINY_ANDROID=true make -j16
you’ll get Tool‐ box, Bionic, init, adbd, logcat, sh, and a few other key binaries and libraries.


Core Building Blocks


One of the first services started by init is the servicemanager.
If the servicemanager isn’t running, none of the system services will be able to advertise themselves, and the Framework simply will not work.

The next core component to get started is the Zygote declared in root/init.zygote32.rc:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
init runs the C++ program /system/bin/app_process, and gives the resulting process the name "zygote".
source for 'app_process is in frameworks/base/cmds/app_process/app_main.cpp.
app_process start a new Dalvik VM for running Android code straight from the command line.

Usage: app_process [java-options] cmd-dir start-class-name [options]
app_process has two main responsibilities:
  • initialize the Android runtime
  • app_process does a runtime.start("com.android.internal.os.ZygoteInit", startSystemServer), the startSystemServer flag is passed as a parameter on to app_process, to indicate whether to start the system server.
    runtime is an instance of class AppRuntime, which is sub-classed from AndroidRuntime, AndroidRuntime is the main class for starting the Dalvik runtime environment. source is in frameworks/base/core/jni/AndroidRuntime.cpp, the start() method starts the Dalvik virtual machine via startVM().
  • use the runtime to start zygote via its main method
  • com.android.internal.os.ZygoteInit:main() starts executing, source is at frameworks/base/core/java/com/android/internal/os/ZygoteInit.java .
    • If startSystemServer is set, then the system server is started via Zygote.forkSystemServer()
    • Source for the SystemServer is in frameworks/base/services/java/com/android/server/SystemServer.java. The libandroid_servers.so library is loaded, which contains the JNI parts required by some of the system services and then invokes native code in frameworks/base/cmds/system_server/library/system_init.cpp, which starts C-coded system services that run in the system_server process. In the "ServerThread::run()" method, lots of critical services are started.
    • zygote runs in "select loop mode", where a single process spins waiting for communication to start subsequent apps
This process is a “Warmed-up” process, which means it’s a process that’s been initialized and has all the core libraries linked in.
When you start an Android application, the Zygote is forked with another VM. Every android application runs in a separate process and has its own Dalvik VM.
You can disable Zygoye's startup entirely by adding the disabled option to its section in init.rc.

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
   ...
   disabled
This will effectively prevent init from starting the Zygote at boot time, so none of the Android Framework’s parts will start, including the System Server.

System Services


Android has quite a few daemons running in the background.
The Android init is different than that of Linux, with the most important differences being in its support of System Properties and using a particular set of rc files.
The System Server is started as part of the Zygote’s startup.


Apps Startup


Utilities and Commands


General-Purpose Utilities:
  • service
    • service list
  • dumpsys service_name
  • Call the dump() method implemented by a service. For ex., to get the CPU usage:
    
    adb shell dumpsys cpuinfo
    
  • dumpstate
  • get a snapshot of the entire system
  • rawbu
  • back up and restore the contents

Service-Specific Utilities:
  • am
  • The Activity Manager. am is in fact a shell script, as you can see in frameworks/base/cmds/am/am/:
    
        # Script to start "am" on the device, which has a very rudimentary
        # shell.
        #
        base=/system
        export CLASSPATH=$base/framework/am.jar
        exec app_process $base/bin com.android.commands.am.Am "$@"
    
    The script uses app_process to start Java code that implements am’s functionality. All parameters passed on the command line are actually passed on to the Java code as is.
  • pm
  • The Package Manager. pm is also a shell script that starts Java code:
    
        # Script to start "pm" on the device, which has a very rudimentary
        # shell.
        #
        base=/system
        export CLASSPATH=$base/framework/pm.jar
        exec app_process $base/bin com.android.commands.pm.Pm "$@"
    
    • Listing the installed packages
    • 
      pm list packages
      
    • Installing an app (the command used by the adb install command)
    • 
      pm install appName.apk
      
    • removing the app requires knowing its package name
    • 
      pm uninstall full.package.name
      
  • svc
  • svc is also a script that uses app_process to start Java code. It is a utility to provide you with the ability to control several system services:
    • power
    • Control the power manager
      
      usage: svc power stayon [true|false|usb|ac|wireless]
               Set the 'keep awake while plugged in' setting.
             svc power reboot [reason]
               Perform a runtime shutdown and reboot device with specified reason.
             svc power shutdown
               Perform a runtime shutdown and power off the device.
      
    • data
    • Control mobile data connectivity
      
      usage: svc data [enable|disable]
               Turn mobile data on or off.
      
    • wifi
    • Control the Wi-Fi manager
      
      usage: svc wifi [enable|disable]
               Turn Wi-Fi on or off.
      
  • ime
  • The ime command lets you communicate with the Input Method system service to control the system’s use of available input methods
    
    usage: ime list [-a] [-s]
               ime enable ID
               ime disable ID
               ime set ID
        The list command prints all enabled input methods.  Use
        the -a option to see all input methods.  Use
        the -s option to see only a single summary line of each.
        The enable command allows the given input method ID to be used.
        The disable command disallows the given input method ID from use.
        The set command switches to the given input method ID.
    
  • input
  • input connects to the Window Manager system service and injects text or key events into the system.
    
    Usage: input [source] command [arg...]
    
    The sources are:
          dpad
          keyboard
          mouse
          touchpad
          gamepad
          touchnavigation
          joystick
          touchscreen
          stylus
          trackball
    
    The commands and default sources are:
          text string (Default: touchscreen)
          keyevent [--longpress] key code number or name ... (Default: keyboard)
          tap x y (Default: touchscreen)
          swipe x1 y1 x2 y2 [duration(ms)] (Default: touchscreen)
          draganddrop x1 y1 x2 y2 [duration(ms)] (Default: touchscreen)
          press (Default: trackball)
          roll dx dy (Default: trackball)
    
  • monkey
  • there’s an entire section about it in the app developer documentation entitled UI/Application Exerciser Monkey. It sends a pseudo-random(yet repeatable) stream of user events into the system, which acts as a stress test on the application software you are developing. To do its magic, monkey communicates with the Activity Manager, the Window Man‐ ager, and the Package Manager.
    
    usage: monkey [-p ALLOWED_PACKAGE [-p ALLOWED_PACKAGE] ...]
                  [-c MAIN_CATEGORY [-c MAIN_CATEGORY] ...]
                  [--ignore-crashes] [--ignore-timeouts]
                  [--ignore-security-exceptions]
                  [--monitor-native-crashes] [--ignore-native-crashes]
                  [--kill-process-after-error] [--hprof]
                  [--match-description TEXT]
                  [--pct-touch PERCENT] [--pct-motion PERCENT]
                  [--pct-trackball PERCENT] [--pct-syskeys PERCENT]
                  [--pct-nav PERCENT] [--pct-majornav PERCENT]
                  [--pct-appswitch PERCENT] [--pct-flip PERCENT]
                  [--pct-anyevent PERCENT] [--pct-pinchzoom PERCENT]
                  [--pct-permission PERCENT]
                  [--pkg-blacklist-file PACKAGE_BLACKLIST_FILE]
                  [--pkg-whitelist-file PACKAGE_WHITELIST_FILE]
                  [--wait-dbg] [--dbg-no-events]
                  [--setup scriptfile] [-f scriptfile [-f scriptfile] ...]
                  [--port port]
                  [-s SEED] [-v [-v] ...]
                  [--throttle MILLISEC] [--randomize-throttle]
                  [--profile-wait MILLISEC]
                  [--device-sleep-time MILLISEC]
                  [--randomize-script]
                  [--script-log]
                  [--bugreport]
                  [--periodic-bugreport]
                  [--permission-target-system]
                  COUNT
    
    Here is a more typical command line, which will launch your application and send 500 pseudo-random events to it:
    
    $ adb shell monkey -p your.package.name -v 500
    
    Most interestingly, you can provide a script to monkey for running a predefined set of input instead of providing random input. For a detailed understanding of the scripting language understood by monkey, take a look at monkey’s script interpreting code in development/cmds/monkey/src/com/android/commands/ monkey/MonkeySourceScript.java and look for EVENT_KEYWORD_.
  • bmgr
  • the Backup Manager system service.
    
    usage: bmgr [backup|restore|list|transport|run]
           bmgr backup PACKAGE
           bmgr enable BOOL
           bmgr enabled
           bmgr list transports [-c]
           bmgr list sets
           bmgr transport WHICH|-c WHICH_COMPONENT
           bmgr restore TOKEN
           bmgr restore TOKEN PACKAGE...
           bmgr restore PACKAGE
           bmgr run
           bmgr wipe TRANSPORT PACKAGE
           bmgr fullbackup PACKAGE...
           bmgr backupnow --all|PACKAGE...
           bmgr cancel backups
    
    The 'backup' command schedules a backup pass for the named package.
    Note that the backup pass will effectively be a no-op if the package
    does not actually have changed data to store.
    
    The 'enable' command enables or disables the entire backup mechanism.
    If the argument is 'true' it will be enabled, otherwise it will be
    disabled.  When disabled, neither backup or restore operations will
    be performed.
    
    The 'enabled' command reports the current enabled/disabled state of
    the backup mechanism.
    
    The 'list transports' command reports the names of the backup transports
    BackupManager is currently bound to. These names can be passed as arguments
    to the 'transport' and 'wipe' commands.  The currently active transport
    is indicated with a '*' character. If -c flag is used, all available
    transport components on the device are listed. These can be used with
    the component variant of 'transport' command.
    
    The 'list sets' command reports the token and name of each restore set
    available to the device via the currently active transport.
    
    The 'transport' command designates the named transport as the currently
    active one.  This setting is persistent across reboots. If -c flag is
    specified, the following string is treated as a component name.
    
    The 'restore' command when given just a restore token initiates a full-system
    restore operation from the currently active transport.  It will deliver
    the restore set designated by the TOKEN argument to each application
    that had contributed data to that restore set.
    
    The 'restore' command when given a token and one or more package names
    initiates a restore operation of just those given packages from the restore
    set designated by the TOKEN argument.  It is effectively the same as the
    'restore' operation supplying only a token, but applies a filter to the
    set of applications to be restored.
    
    The 'restore' command when given just a package name intiates a restore of
    just that one package according to the restore set selection algorithm
    used by the RestoreSession.restorePackage() method.
    
    The 'run' command causes any scheduled backup operation to be initiated
    immediately, without the usual waiting period for batching together
    data changes.
    
    The 'wipe' command causes all backed-up data for the given package to be
    erased from the given transport's storage.  The next backup operation
    that the given application performs will rewrite its entire data set.
    Transport names to use here are those reported by 'list transports'.
    
    The 'fullbackup' command induces a full-data stream backup for one or more
    packages.  The data is sent via the currently active transport.
    
    The 'backupnow' command runs an immediate backup for one or more packages.
        --all flag runs backup for all eligible packages.
    For each package it will run key/value or full data backup
    depending on the package's manifest declarations.
    The data is sent via the currently active transport.
    The 'cancel backups' command cancels all running backups.
    
  • media
  • The Media APIs are used to play and, in some cases, record media files. This includes audio (e.g., play MP3s or other music files, ringtones, game sound effects, or DTMF tones) and video (e.g., play a video streamed over the web or from local storage).
    
    usage: media [subcommand] [options]
           media dispatch KEY
           media list-sessions
           media monitor tag
           media volume [options]
    
    media dispatch: dispatch a media key to the system.
                    KEY may be: play, pause, play-pause, mute, headsethook,
                    stop, next, previous, rewind, record, fast-forword.
    media list-sessions: print a list of the current sessions.
    media monitor: monitor updates to the specified session.
                           Use the tag from list-sessions.
    media volume:  the options are as follows:
                    --stream STREAM selects the stream to control, see AudioManager.STREAM_*
                                    controls AudioManager.STREAM_MUSIC if no stream is specified
                    --set INDEX     sets the volume index value
                    --adj DIRECTION adjusts the volume, use raise|same|lower for the direction
                    --get           outputs the current volume
                    --show          shows the UI during the volume change
            examples:
                    adb shell media volume --show --stream 3 --set 11
                    adb shell media volume --stream 0 --adj lower
                    adb shell media volume --stream 3 --get
    

Dalvik Utilities
  • dalvikvm
  • dalvikvm is actually a raw Dalvik VM without any connection to “Android”, it start just a Dalvik VM without any Android-specific functionality
  • dexdump
  • To reverse-engineer Android apps or JAR files.

Support Daemons


Apps run as unprivileged users that can’t, for instance, invoke any system call that requires root privileges or access most of the key devices in /dev. Apps must ask system services to act on their behalf.
System services don’t, however, themselves run as root. Instead, many key operations require system services to communicate through Unix domain sockets in /dev/socket/ with native daemons running as either root or as a specific user to conduct privileged operations.

vold

External storage is managed by a combination of the vold init service and StorageManagerService system service.
vold takes care of many of the key operations required by the Mount Service, such as mounting and formatting volumes.
Mounting of physical external storage volumes is handled by vold.
vold is started by init.rc, while the Mount Service is part of the System Server.
vold actually has a configuration file,
  • /etc/vold.fstab for Android 4.2.2 and earlier
  • /etc/fstab.device for Android releases 4.3 and later
For external storage volumes that are managed by vold, the entries should have the following format:

src mnt_point type mnt_flags fs_mgr_flags

where:
  • src
  • A path under sysfs (usually mounted at /sys) to the device that can provide the mount point. The path must start with /.
  • mount_point
  • Filesystem path where the volume should be mounted.
  • type
  • The type of the filesystem on the volume. For external cards, this is usually vfat.
  • mnt_flags
  • Vold ignores this field and it should be set to defaults
  • fs_mgr_flags
  • : Vold ignores any lines in the unified fstab that do not include the voldmanaged= flag in this field. This flag must be followed by a label describing the card, and a partition number or the word auto. Here is an example: voldmanaged=sdcard:auto. Other possible flags are nonremovable, encryptable=sdcard, noemulatedsd, and encryptable=userdata.

healthd

The "health daemon" is meant to service general "device health" tasks periodically, currently, the only tasks are battery related.
Like most daemons, healthd sets up an initial configuration, and then enters a run loop.

Android 9 includes android.hardware.health HAL 2.0, a major version upgrade from health@1.0 HAL.
Devices launching with Android 9 must provide the 2.0 HAL (and must not provide the 1.0 HAL).
Terminology:
  • health@1.0
  • abbreviation of android.hardware.health@1.0. Refers to health HIDL HAL version 1.0 released in Android 8.0.
  • health@2.0
  • abbreviation of android.hardware.health@2.0. Refers to health HIDL HAL version 2.0 released in Android 9.
  • charger
  • executable running in off-mode charging that displays the phone-charging animation.
  • recovery
  • executable running in recovery mode that must retrieve battery information.
  • healthd
  • legacy daemon running in Android that retrieves health-related information and provides it to framework.
  • storaged
  • daemon running in Android that retrieves storage information and provides it to framework.
In Android 9, the health component works as detailed in the following diagram:


The framework attempts to retrieve health@2.0 service from hwservicemanager. If it fails, it calls into health@1.0 (in Android 8.x). The legacy code path is kept so the Android 9 system image is compatible with the Android 8.x vendor image. The framework does not retrieve information from both HALs because only one service version (1.0 or 2.0) can exist on the device.

health@2.0 has the following clients:
  • charger
  • The usage of libbatterymonitor and healthd_common code is wrapped in health@2.0-impl.
  • recovery
  • BatteryManager
  • BatteryService
  • Storaged
Removing healthd: For devices launching with Android 9 and devices upgrading to Android 9 that provide the Health 2.0 HAL in the new vendor image, we recommend removing healthd from the system image to save disk space and speed boot time.

Upgrading from health@1.0 HAL


Hardware Abstraction Layer


Android relies on a Hardware Abstraction Layer (HAL) to interface with hardware.
System services almost never interact with devices through /dev entries directly. Instead, they go through HAL modules, typically shared libraries, to talk to hardware.

The definitions of the interfaces between the Framework and the HAL modules are in header files under:
  • hardware/libhardware/include/hardware/
  • hardware/libhardware_legacy/include/hardware_legacy/

留言

熱門文章