Sunday, February 06, 2011

Zygote Initialization Flow

The code flow of zygote initialization is rather complicated, especially when the JNIs are extensively involved. My IDE often fails to cross reference between them. So I log the code flow here and the location they are defined as well.

In the very beginning, the init.rc initiated a Zygote process, which forks the SystemServer as we will see later.
system/core/rootdir/init.rc

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system- server socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media
The Android.mk for app_process is list below
frameworks/base/cmds/app_process/Android.mk

LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ app_main.cpp LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ libbinder \ libandroid_runtime LOCAL_MODULE:= app_process include $(BUILD_EXECUTABLE)
The main program looks pretty short(exception handling is removed for readability), but the execution flow underneath is rather complicated.
frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, const char* const argv[]) { AppRuntime runtime; int i = runtime.addVmArguments(argc, argv); setArgv0(argv0, "zygote"); set_process_name("zygote"); runtime.start("com.android.internal.os.ZygoteInit", startSystemServer); ...
The AppRuntime is a subclass of AndroidRuntime, which actually takes care of the initialization.
frameworks/base/cmds/app_process/app_main.cpp

class AppRuntime : public AndroidRuntime { public: AppRuntime() : mParentDir(NULL) , mClassName(NULL) , mArgC(0) , mArgV(NULL) { } virtual void onStarted() { sp proc = ProcessState::self(); if (proc->supportsProcesses()) { LOGV("App process: starting thread pool.\n"); proc->startThreadPool(); } app_init(mClassName, mArgC, mArgV); if (ProcessState::self()->supportsProcesses()) IPCThreadState::self()->stopProcess(); } virtual void onZygoteInit() { sp proc = ProcessState::self(); if (proc->supportsProcesses()) { LOGV("App process: starting thread pool.\n"); proc->startThreadPool(); } } ...
The start() method does the following work:
  • Initilize the Java Virtual Machine
  • Register JNIs
  • Prepare the JNI arguments for the main() method
  • Invoke the ZygoteInit.main() with the JNI arguments
And as the comments stated, the main() method will not return until the VM exits.
frameworks/base/core/jni/AndroidRuntime.cpp

/* * Start the Android runtime. This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". */ void AndroidRuntime::start(const char* className, const bool startSystemServer) { char* slashClassName = NULL; char* cp; JNIEnv* env; blockSigpipe(); const char* rootDir = getenv("ANDROID_ROOT"); if (rootDir == NULL) { rootDir = "/system"; setenv("ANDROID_ROOT", rootDir, 1); } /* start the virtual machine */ startVm(&mJavaVM, &env); /* Register android functions. */ startReg(env); /* * We want to call main() with a String array with arguments in it. * At present we only have one argument, the class name. Create an * array to hold it. */ jclass stringClass; jobjectArray strArray; jstring classNameStr; jstring startSystemServerStr; stringClass = env->FindClass("java/lang/String"); strArray = env->NewObjectArray(2, stringClass, NULL); classNameStr = env->NewStringUTF(className); env->SetObjectArrayElement(strArray, 0, classNameStr); startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false"); env->SetObjectArrayElement(strArray, 1, startSystemServerStr); /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ jclass startClass; jmethodID startMeth; slashClassName = strdup(className); for (cp = slashClassName; *cp != '\0'; cp++) if (*cp == '.') *cp = '/'; startClass = env->FindClass(slashClassName); startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); env->CallStaticVoidMethod(startClass, startMeth, strArray); /* If everything goes well, the following are not reached */ ... }
The main() first register a socket, pre-load bunches of classes and resources. Then the execution flow diverges from the startSystemServer().

The startSystemServer() forks and specialized a child process as the SystemServer, which in turn spawns threads for different Android subsystems.

The parent process, on the other hand, returns to the main() function and continues to enter into a closed loop in the runSelectLoopMode(), which accepts new requests received via the zygote socket created earlier, and spawns new processes for them.
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) { try { registerZygoteSocket(); preloadClasses(); preloadResources(); // Do an initial gc to clean up after startup gc(); // If requested, start system server directly from Zygote if (argv.length != 2) { throw new RuntimeException(argv[0] + USAGE_STRING); } if (argv[1].equals("true")) { startSystemServer(); } else if (!argv[1].equals("false")) { throw new RuntimeException(argv[0] + USAGE_STRING); } Log.i(TAG, "Accepting command socket connections"); runSelectLoopMode(); closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }
Before we jump into the startSystemServer(), let's first finish our code tracing of the parent process.
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

/** * Runs the zygote process's select loop. Accepts new connections as * they happen, and reads commands from connections one spawn-request's * worth at a time. * * @throws MethodAndArgsCaller in a child process when a main() should * be executed. */ private static void runSelectLoopMode() throws MethodAndArgsCaller { ArrayList fds = new ArrayList(); ArrayList peers = new ArrayList(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; /* * Call gc() before we block in select(). * It's work that has to be done anyway, and it's better * to avoid making every child do it. It will also * madvise() any free memory as a side-effect. * * Don't call it every time, because walking the entire * heap is a lot of overhead to free a few hundred bytes. */ if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; } fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { boolean done; done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } }
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003,3006", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; parsedArgs = new ZygoteConnection.Arguments(args); /* * Enable debugging of the system process if *either* the command line flags * indicate it should be debuggable or the ro.debuggable system property * is set to "1" */ int debugFlags = parsedArgs.debugFlags; if ("1".equals(SystemProperties.get("ro.debuggable"))) debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; /* Request to fork the system server process */ int pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, debugFlags, null); /* For child process */ if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }
dalvik/vm/native/dalvik_system_Zygote.c

const DalvikNativeMethod dvm_dalvik_system_Zygote[] = { { "fork", "()I", Dalvik_dalvik_system_Zygote_fork }, { "forkAndSpecialize", "(II[II[[I)I", Dalvik_dalvik_system_Zygote_forkAndSpecialize }, { "forkSystemServer", "(II[II[[I)I", Dalvik_dalvik_system_Zygote_forkSystemServer }, { NULL, NULL, NULL }, };
dalvik/vm/native/dalvik_system_Zygote.c

/* * native public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags); */ static void Dalvik_dalvik_system_Zygote_forkSystemServer(const u4* args, JValue* pResult) { pid_t pid = forkAndSpecializeCommon(args); /* The zygote process checks whether the child process has died or not. */ if (pid > 0) { int status; LOGI("System server process %d has been created", pid); gDvm.systemServerPid = pid; } RETURN_INT(pid); } /* * Utility routine to fork zygote and specialize the child process. */ static pid_t forkAndSpecializeCommon(const u4* args) { ... }
After being forked the child process branches to the handleSystemServerProcess() method, which in turn invokes RuntimeInit.zygoteInit().
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

/** * Finish remaining work for the newly forked system server process. */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { /* * First, set the capabilities if necessary */ if (parsedArgs.uid != 0) { /* * If the Process belong to AID_RADIO(1001) or AID_SYSTEM(1000) * then add CAP_SYS_TIME (1<<25) Capability. */ if(parsedArgs.uid == 1000 || parsedArgs.uid == 1001 ) { parsedArgs.permittedCapabilities |= (1<<25); parsedArgs.effectiveCapabilities |= (1<<25); } setCapabilities(parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } closeServerSocket(); /* * Pass the remaining arguments to SystemServer. * "--nice-name=system_server com.android.server.SystemServer" */ RuntimeInit.zygoteInit(parsedArgs.remainingArgs); /* should never reach here */ }
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

/** * The main function called when started through the zygote process. This * could be unified with main(), if the native code in finishInit() * were rationalized with Zygote startup. * * Current recognized args: * * --nice-name=nice name to appear in ps * <code> [--] <start class name> <args> * * @param argv arg strings */ public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller { commonInit(); zygoteInitNative(); int curArg = 0; for ( /* curArg */ ; curArg < argv.length; curArg++) { String arg = argv[curArg]; if (arg.equals("--")) { curArg++; break; } else if (!arg.startsWith("--")) { break; } else if (arg.startsWith("--nice-name=")) { String niceName = arg.substring(arg.indexOf('=') + 1); Process.setArgV0(niceName); } } if (curArg == argv.length) { Slog.e(TAG, "Missing classname argument to RuntimeInit!"); // let the process exit return; } // Remaining arguments are passed to the start class's static main String startClass = argv[curArg++]; String[] startArgs = new String[argv.length - curArg]; System.arraycopy(argv, curArg, startArgs, 0, startArgs.length); invokeStaticMain(startClass, startArgs); }
The JNI zygoteInitNative() is listed below, and the gCurRuntime->onZygoteInit() refers to the AppRuntime->onZygoteInit(), which has been listed in the begin of this post.
framework/base/core/jni/AndroidRuntime.cpp

static JNINativeMethod gMethods[] = { { "finishInit", "()V", (void*) com_android_internal_os_RuntimeInit_finishInit }, { "zygoteInitNative", "()V", (void*) com_android_internal_os_RuntimeInit_zygoteInit }, { "isComputerOn", "()I", (void*) com_android_internal_os_RuntimeInit_isComputerOn }, { "turnComputerOn", "()V", (void*) com_android_internal_os_RuntimeInit_turnComputerOn }, { "getQwertyKeyboard", "()I", (void*) com_android_internal_os_RuntimeInit_getQwertyKeyboard }, }; ... static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); }
The invokeStaticMain() staffs SystemServer.main() into ZygoteInit.MethodAndArgsCaller() and throws it. The exception will be caught in ZygoteInit.main(), which we've seen earlier. And the exception handler there only does one thing; invoke the staffed SystemServer.main().
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

/** * Invokes a static "main(argv[]) method on class "className". * Converts various failing exceptions into RuntimeExceptions, with * the assumption that they will then cause the VM instance to exit. * * @param className Fully-qualified class name * @param argv Argument vector for main() */ private static void invokeStaticMain(String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { // We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); Class cl = Class.forName(className); Method m = cl.getMethod("main", new Class[] { String[].class }); /* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */ throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
frameworks/base/services/java/com/android/server/SystemServer.java

public class SystemServer { ... /** * This method is called from Zygote to initialize the system. This will cause the native * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back * up into init2() to start the Android services. */ native public static void init1(String[] args); public static void main(String[] args) { // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); System.loadLibrary("android_servers"); init1(args); } }
The native init1() in turn calls into the system_init()
frameworks/base/services/jni/com_android_server_SystemServer.cpp

namespace android { extern "C" int system_init(); static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz) { system_init(); } /* * JNI registration. */ static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 }, }; int register_android_server_SystemServer(JNIEnv* env) { return jniRegisterNativeMethods(env, "com/android/server/SystemServer", gMethods, NELEM(gMethods)); } }; // namespace android
After instantiating some services, system_init() invokes SystemServer.init2() to spawn the SystemServer thread, which further initializes more subsystems of android framework.
framework/base/cmds/system_server/library/system_init.cpp

extern "C" status_t system_init() { LOGI("Entered system_init()"); sp proc(ProcessState::self()); sp sm = defaultServiceManager(); LOGI("ServiceManager: %p\n", sm.get()); sp grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsurfaceflinger", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } // On the simulator, audioflinger et al don't get started the // same way as on the device, and we need to start them here if (!proc->supportsProcesses()) { // Start the AudioFlinger AudioFlinger::instantiate(); // Start the media playback service MediaPlayerService::instantiate(); // Start the camera service CameraService::instantiate(); // Start the audio policy service AudioPolicyService::instantiate(); } // And now start the Android runtime. We have to do this bit // of nastiness because the Android runtime initialization requires // some of the core system services to already be started. // All other servers should just start the Android runtime at // the beginning of their processes's main(), before calling // the init function. LOGI("System server: starting Android runtime.\n"); AndroidRuntime* runtime = AndroidRuntime::getRuntime(); LOGI("System server: starting Android services.\n"); runtime->callStatic("com/android/server/SystemServer", "init2"); // If running in our own process, just go into the thread // pool. Otherwise, call the initialization finished // func to let this process continue its initilization. if (proc->supportsProcesses()) { LOGI("System server: entering thread pool.\n"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); LOGI("System server: exiting thread pool.\n"); } return NO_ERROR; }
frameworks/base/services/java/com/android/server/SystemServer.java

public class SystemServer { public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } }
frameworks/base/services/java/com/android/server/SystemServer.java

class ServerThread extends Thread { private static final String TAG = "SystemServer"; private static final int LOG_BOOT_PROGRESS_SYSTEM_RUN = 3010; private ContentResolver mContentResolver; private class AdbSettingsObserver extends ContentObserver { public AdbSettingsObserver() { super(null); } @Override public void onChange(boolean selfChange) { boolean enableAdb = (Settings.Secure.getInt(mContentResolver, Settings.Secure.ADB_ENABLED, 0) > 0); // setting this secure property will start or stop adbd SystemProperties.set("persist.service.adb.enable", enableAdb ? "1" : "0"); } } @Override public void run() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); Looper.prepare(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); BinderInternal.disableBackgroundScheduling(true); String factoryTestStr = SystemProperties.get("ro.factorytest"); int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF : Integer.parseInt(factoryTestStr); LightsService lights = null; PowerManagerService power = null; BatteryService battery = null; ConnectivityService connectivity = null; IPackageManager pm = null; Context context = null; WindowManagerService wm = null; BluetoothService bluetooth = null; BluetoothA2dpService bluetoothA2dp = null; HeadsetObserver headset = null; DockObserver dock = null; UiModeManagerService uiMode = null; RecognitionManagerService recognition = null; ThrottleService throttle = null; // Critical services... try { Slog.i(TAG, "Entropy Service"); ServiceManager.addService("entropy", new EntropyService()); Slog.i(TAG, "Power Manager"); power = new PowerManagerService(); ServiceManager.addService(Context.POWER_SERVICE, power); Slog.i(TAG, "Activity Manager"); context = ActivityManagerService.main(factoryTest); Slog.i(TAG, "Telephony Registry"); ServiceManager.addService("telephony.registry", new TelephonyRegistry(context)); AttributeCache.init(context); Slog.i(TAG, "Package Manager"); pm = PackageManagerService.main(context, factoryTest != SystemServer.FACTORY_TEST_OFF); ActivityManagerService.setSystemProcess(); mContentResolver = context.getContentResolver(); // The AccountManager must come before the ContentService Slog.i(TAG, "Account Manager"); ServiceManager.addService(Context.ACCOUNT_SERVICE, new AccountManagerService(context)); Slog.i(TAG, "Content Manager"); ContentService.main(context, factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL); Slog.i(TAG, "System Content Providers"); ActivityManagerService.installSystemProviders(); Slog.i(TAG, "Battery Service"); battery = new BatteryService(context); ServiceManager.addService("battery", battery); Slog.i(TAG, "Lights Service"); lights = new LightsService(context); Slog.i(TAG, "Vibrator Service"); ServiceManager.addService("vibrator", new VibratorService(context)); // only initialize the power service after we have started the // lights service, content providers and the battery service. power.init(context, lights, ActivityManagerService.getDefault(), battery); Slog.i(TAG, "Alarm Manager"); AlarmManagerService alarm = new AlarmManagerService(context); ServiceManager.addService(Context.ALARM_SERVICE, alarm); Slog.i(TAG, "Init Watchdog"); Watchdog.getInstance().init(context, battery, power, alarm, ActivityManagerService.self()); // Sensor Service is needed by Window Manager, so this goes first Slog.i(TAG, "Sensor Service"); ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context)); Slog.i(TAG, "Window Manager"); wm = WindowManagerService.main(context, power, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL); ServiceManager.addService(Context.WINDOW_SERVICE, wm); ((ActivityManagerService)ServiceManager.getService("activity")) .setWindowManager(wm); // Skip Bluetooth if we have an emulator kernel // TODO: Use a more reliable check to see if this product should // support Bluetooth - see bug 988521 if (SystemProperties.get("ro.kernel.qemu").equals("1")) { Slog.i(TAG, "Registering null Bluetooth Service (emulator)"); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null); } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) { Slog.i(TAG, "Registering null Bluetooth Service (factory test)"); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null); } else { Slog.i(TAG, "Bluetooth Service"); bluetooth = new BluetoothService(context); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth); bluetooth.initAfterRegistration(); bluetoothA2dp = new BluetoothA2dpService(context, bluetooth); ServiceManager.addService( BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE, bluetoothA2dp); int bluetoothOn = Settings.Secure.getInt(mContentResolver, Settings.Secure.BLUETOOTH_ON, 0); if (bluetoothOn > 0) { bluetooth.enable(); } } } catch (RuntimeException e) { Slog.e("System", "Failure starting core service", e); } DevicePolicyManagerService devicePolicy = null; StatusBarService statusBar = null; InputMethodManagerService imm = null; AppWidgetService appWidget = null; NotificationManagerService notification = null; WallpaperManagerService wallpaper = null; LocationManagerService location = null; if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { Slog.i(TAG, "Device Policy"); devicePolicy = new DevicePolicyManagerService(context); ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy); Slog.i(TAG, "Status Bar"); statusBar = new StatusBarService(context); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); Slog.i(TAG, "Clipboard Service"); ServiceManager.addService(Context.CLIPBOARD_SERVICE, new ClipboardService(context)); Slog.i(TAG, "Input Method Service"); imm = new InputMethodManagerService(context, statusBar); ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm); Slog.i(TAG, "NetStat Service"); ServiceManager.addService("netstat", new NetStatService(context)); Slog.i(TAG, "NetworkManagement Service"); ServiceManager.addService( Context.NETWORKMANAGEMENT_SERVICE, new NetworkManagementService(context)); Slog.i(TAG, "Connectivity Service"); connectivity = ConnectivityService.getInstance(context); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); Slog.i(TAG, "Throttle Service"); throttle = new ThrottleService(context); ServiceManager.addService(Context.THROTTLE_SERVICE, throttle); Slog.i(TAG, "Accessibility Manager"); ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, new AccessibilityManagerService(context)); /* * NotificationManagerService is dependant on MountService, * (for media / usb notifications) so we must start MountService first. */ Slog.i(TAG, "Mount Service"); ServiceManager.addService("mount", new MountService(context)); Slog.i(TAG, "Notification Manager"); notification = new NotificationManagerService(context, statusBar, lights); ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification); Slog.i(TAG, "Device Storage Monitor"); ServiceManager.addService(DeviceStorageMonitorService.SERVICE, new DeviceStorageMonitorService(context)); Slog.i(TAG, "Location Manager"); location = new LocationManagerService(context); ServiceManager.addService(Context.LOCATION_SERVICE, location); Slog.i(TAG, "Search Service"); ServiceManager.addService(Context.SEARCH_SERVICE, new SearchManagerService(context)); Slog.i(TAG, "DropBox Service"); ServiceManager.addService(Context.DROPBOX_SERVICE, new DropBoxManagerService(context, new File("/data/system/dropbox"))); Slog.i(TAG, "Wallpaper Service"); wallpaper = new WallpaperManagerService(context); ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper); Slog.i(TAG, "Audio Service"); ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context)); Slog.i(TAG, "Headset Observer"); headset = new HeadsetObserver(context); Slog.i(TAG, "Dock Observer"); dock = new DockObserver(context, power); Slog.i(TAG, "UI Mode Manager Service"); uiMode = new UiModeManagerService(context); Slog.i(TAG, "Backup Service"); ServiceManager.addService(Context.BACKUP_SERVICE, new BackupManagerService(context)); Slog.i(TAG, "AppWidget Service"); appWidget = new AppWidgetService(context); ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget); Slog.i(TAG, "Recognition Service"); recognition = new RecognitionManagerService(context); com.android.server.status.StatusBarPolicy.installIcons(context, statusBar); Slog.i(TAG, "DiskStats Service"); ServiceManager.addService("diskstats", new DiskStatsService(context)); } // make sure the ADB_ENABLED setting value matches the secure property value Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED, "1".equals(SystemProperties.get("persist.service.adb.enable")) ? 1 : 0); // register observer to listen for settings changes mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED), false, new AdbSettingsObserver()); // Before things start rolling, be sure we have decided whether // we are in safe mode. final boolean safeMode = wm.detectSafeMode(); if (safeMode) { ActivityManagerNative.getDefault().enterSafeMode(); // Post the safe mode state in the Zygote class Zygote.systemInSafeMode = true; // Disable the JIT for the system_server process VMRuntime.getRuntime().disableJitCompilation(); } else { // Enable the JIT for the system_server process VMRuntime.getRuntime().startJitCompilation(); } // It is now time to start up the app processes... if (devicePolicy != null) { devicePolicy.systemReady(); } if (notification != null) { notification.systemReady(); } if (statusBar != null) { statusBar.systemReady(); } wm.systemReady(); power.systemReady(); pm.systemReady(); // These are needed to propagate to the runnable below. final BatteryService batteryF = battery; final ConnectivityService connectivityF = connectivity; final DockObserver dockF = dock; final ThrottleService throttleF = throttle; final UiModeManagerService uiModeF = uiMode; final AppWidgetService appWidgetF = appWidget; final WallpaperManagerService wallpaperF = wallpaper; final InputMethodManagerService immF = imm; final RecognitionManagerService recognitionF = recognition; final LocationManagerService locationF = location; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. ((ActivityManagerService)ActivityManagerNative.getDefault()) .systemReady(new Runnable() { public void run() { Slog.i(TAG, "Making services ready"); if (batteryF != null) batteryF.systemReady(); if (connectivityF != null) connectivityF.systemReady(); if (dockF != null) dockF.systemReady(); if (uiModeF != null) uiModeF.systemReady(); if (recognitionF != null) recognitionF.systemReady(); Watchdog.getInstance().start(); // It is now okay to let the various system services start their // third party code... if (appWidgetF != null) appWidgetF.systemReady(safeMode); if (wallpaperF != null) wallpaperF.systemReady(); if (immF != null) immF.systemReady(); if (locationF != null) locationF.systemReady(); if (throttleF != null) throttleF.systemReady(); } }); Looper.loop(); Slog.d(TAG, "System ServerThread is exiting!"); } }

3 comments:

lucky said...

Superb article thank u very very much

Anonymous said...

Thanks a ton! Great article and insight.

Anonymous said...

Very great job!
Understanding Android internals is very difficult.

I'm trying to understand how the androidFramework is linked to the libs of the OS. For example how an App use libgui and libui.

Do you know that?

Thans.