Android起動のSystemServer起動


SystemServerはAndroidシステムの核心であり、APKアプリケーションで直接対話できるシステムサービスの大部分はこのプロセスで実行されている.よく見られるのはWindowManagerServer(Wms)、Activity ManagerSystemService(AmS)、PackageManagerServer(PmS)などである.
トランザクションは、1つのスレッドでSystemServerプロセスに存在します.
startSystemServer
SystemServerはzygoteで起動したときにforkが起動したので、まずZygoteInitに戻ります.JAvaクラスでSystemServerの起動を見てみましょう.zygote起動中、startSystemServerを呼び出してsystemServerを起動します.
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,1018,3001,3002,3003,3006,3007",
            "--capabilities=130104352,130104352",
            "--runtime-init",
            "--nice-name=system_server",//      
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);


            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }
まずZygoteを通過する.forkSystemServer forkはサブプロセスを出し、uid、gidなどの新しいプロセスの情報を設定するためにいくつかのパラメータを入力します.関数が戻った後、サブプロセスpid=0の場合、handleSystemServer Process関数に入ります.以下のようにします.
private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();

        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Libcore.os.umask(S_IRWXG | S_IRWXO);

        //ps    system    261   98    391508 49008 ffffffff 4005c880 S system_server,  system_server    parsedArgs.niceName
        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }

        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    null, parsedArgs.remainingArgs);
        } else {
            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
        }

        /* should never reach here           */
    }
この関数では、親プロセスzygoteからコピーされたsocketサービスを閉じるためにcloseServerSocket()を最初に呼び出します.zygoteがsocketリクエストの処理を傍受すれば十分です.そして実行を続けますzygoteInit()はJNIでapp_を呼び出しますmain.cppのonZygoteInitは、スレッドプールを起動してBinderイベントを処理します.最後にinvokeStaticMain()関数により異常MethodAndArgsCallerを放出した.
public static class MethodAndArgsCaller extends Exception implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

このクラスはExceptionから継承され,Runnableが実現された.この異常はZygoteInit.JAvaクラスのmain関数catchを実行しrun()関数を実行し、反射によりSystemServerのmain関数を起動します.
次はZygoteInitです.JAvaクラスのmain関数は、例外のコードを取得します.
} catch (MethodAndArgsCaller caller) {
            caller.run();
}

システムサーバを起動しましたJAvaのmain関数です.ソースコードは(baseservicesjavacomandroidserver).
SystemServer.java
このクラスのコードの一部を見てみましょう.
 /**
     * 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) {
        //           SamplingProfiler
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            // If a device's clock is before 1970 (before 0), a lot of
            // APIs crash dealing with negative numbers, notably
            // java.io.File#setLastModified, so instead we fake it and
            // hope that time from cell towers or NTP fixes it
            // shortly.
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        if (SamplingProfilerIntegration.isEnabled()) {
            SamplingProfilerIntegration.start();
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }

        // Mmmmmm... more memory!
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

        // 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);

        //     libandroid_servers.so
        System.loadLibrary("android_servers");
        //init1()     native  ,  JNI    system_init.cpp  system_init()  ,        Dalvik           。        ,      Java  init2()  ,      Java       init2()   .
        init1(args);
    }

    //           init2()      。
    public static final void init2() {
        Slog.i(TAG, "Entered the Android system server!");
        //          ServerThread  ,        ,         , ServerThread run()                。
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
    }
main()関数はまずinit 1()関数を実行し、init 1()関数はnative関数であり、JNIを介してsystem_を最終的に呼び出すinit.cppのsystem_Init()関数:
extern "C" status_t system_init()
{
    ALOGI("Entered system_init()");
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    ALOGI("ServiceManager: %p
", sm.get()); sp<GrimReaper> 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) { // SurfaceFlinger SurfaceFlinger::instantiate(); } property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // sensor service SensorService::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. ALOGI("System server: starting Android runtime.
"); AndroidRuntime* runtime = AndroidRuntime::getRuntime(); ALOGI("System server: starting Android services.
"); JNIEnv* env = runtime->getJNIEnv(); if (env == NULL) { return UNKNOWN_ERROR; } // “com/android/server/SystemServer” SystemServer.java jclass clazz = env->FindClass("com/android/server/SystemServer"); if (clazz == NULL) { return UNKNOWN_ERROR; } // SystemServer.java init2 jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V"); if (methodId == NULL) { return UNKNOWN_ERROR; } // init2() env->CallStaticVoidMethod(clazz, methodId); ALOGI("System server: entering thread pool.
"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); ALOGI("System server: exiting thread pool.
"); return NO_ERROR; }
system_Init()関数コールバックinit 2()関数、init 2()関数はサーバThreadスレッドを起動して各種サービスとその他のいくつかの初期化作業を追加し、サーバThreadは内部クラスであり、大体コードは以下の通りである.
class ServerThread extends Thread {

    ...

    @Override
    public void run() {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
            SystemClock.uptimeMillis());
        Looper.prepareMainLooper();

        ...

        String factoryTestStr = SystemProperties.get("ro.factorytest");
        int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
                : Integer.parseInt(factoryTestStr);
        final boolean headless = "1".equals(SystemProperties.get("ro.config.headless", "0"));

	//    ,     ,        , :  、  、Wifi、  ,USB 
       ...
        Context context = null;
       ...

        // Create a shared handler thread for UI within the system server.
        // This thread is used by at least the following components:
        // - WindowManagerPolicy
        // - KeyguardViewManager
        // - DisplayManagerService
        HandlerThread uiHandlerThread = new HandlerThread("UI");
        uiHandlerThread.start();
        Handler uiHandler = new Handler(uiHandlerThread.getLooper());
        uiHandler.post(new Runnable() {
            @Override
            public void run() {
                //Looper.myLooper().setMessageLogging(new LogPrinter(
                //        Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
                android.os.Process.setThreadPriority(
                        android.os.Process.THREAD_PRIORITY_FOREGROUND);
                android.os.Process.setCanSelfBackground(false);


                // For debug builds, log event loop stalls to dropbox for analysis.
                if (StrictMode.conditionallyEnableDebugLogging()) {
                    Slog.i(TAG, "Enabled StrictMode logging for UI Looper");
                }
            }
        });

        // Create a handler thread just for the window manager to enjoy.
        HandlerThread wmHandlerThread = new HandlerThread("WindowManager");
        wmHandlerThread.start();
        Handler wmHandler = new Handler(wmHandlerThread.getLooper());
        wmHandler.post(new Runnable() {
            @Override
            public void run() {
                //Looper.myLooper().setMessageLogging(new LogPrinter(
                //        android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM));
                android.os.Process.setThreadPriority(
                        android.os.Process.THREAD_PRIORITY_DISPLAY);
                android.os.Process.setCanSelfBackground(false);

                // For debug builds, log event loop stalls to dropbox for analysis.
                if (StrictMode.conditionallyEnableDebugLogging()) {
                    Slog.i(TAG, "Enabled StrictMode logging for WM Looper");
                }
            }
        });

        // Critical services...
        boolean onlyCore = false;
        try {
            // Wait for installd to finished starting up so that it has a chance to
            // create critical directories such as /data/user with the appropriate
            // permissions.  We need this to complete before we initialize other services.
            Slog.i(TAG, "Waiting for installd to be ready.");
            installer = new Installer();
            installer.ping();
     
	    //   EntropyService,   ,           
            Slog.i(TAG, "Entropy Mixer");
            ServiceManager.addService("entropy", new EntropyMixer());// Context.getSystemService (String name)          

	    // ServiceManager        
            Slog.i(TAG, "Power Manager");
            power = new PowerManagerService();
            ServiceManager.addService(Context.POWER_SERVICE, power);

	    //  ActivityManagerService,       context
            Slog.i(TAG, "Activity Manager");
            context = ActivityManagerService.main(factoryTest);

    	    //  uiHandler、wmHandler
	    Slog.i(TAG, "Display Manager");
            display = new DisplayManagerService(context, wmHandler, uiHandler);
            ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);

        ...
	    //  wmHandler
	    Slog.i(TAG, "Input Manager");
            inputManager = new InputManagerService(context, wmHandler);

	    //  uiHandler、wmHandler
 	    Slog.i(TAG, "Window Manager");
            wm = WindowManagerService.main(context, power, display, inputManager,
                    uiHandler, wmHandler,
                    factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
                    !firstBoot, onlyCore);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

            ActivityManagerService.setSystemProcess();

 	...

            Slog.i(TAG, "System Content Providers");
            ActivityManagerService.installSystemProviders();
	...

            // only initialize the power service after we have started the lights service, content providers and the battery service.
            power.init(context, lights, ActivityManagerService.self(), battery,
                    BatteryStatsService.getService(), display);

 	...

            Slog.i(TAG, "Init Watchdog");
            Watchdog.getInstance().init(context, battery, power, alarm,
                    ActivityManagerService.self());

 	...

            ActivityManagerService.self().setWindowManager(wm);

	...

	    //  wmHandler
    	    if (context.getResources().getBoolean(
                    com.android.internal.R.bool.config_dreamsSupported)) {
                try {
                    Slog.i(TAG, "Dreams Service");
                    // Dreams (interactive idle-time views, a/k/a screen savers)
                    dreamy = new DreamManagerService(context, wmHandler);
                    ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy);
                } catch (Throwable e) {
                    reportWtf("starting DreamManagerService", e);
                }
            }
        } catch (RuntimeException e) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting core service", e);
        }

	...

            try {
                Slog.i(TAG, "NetworkPolicy Service");
                networkPolicy = new NetworkPolicyManagerService(
                        context, ActivityManagerService.self(), power,
                        networkStats, networkManagement);
                ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
            } catch (Throwable e) {
                reportWtf("starting NetworkPolicy Service", e);
            }

 	...
        } 

 	...

        if (safeMode) {
            ActivityManagerService.self().showSafeModeOverlay();
        }

        ...

	//           ,      
        ActivityManagerService.self().systemReady(new Runnable() {
            public void run() {
                Slog.i(TAG, "Making services ready");

                if (!headless) startSystemUi(contextF);
                try {
                    if (mountServiceF != null) mountServiceF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Mount Service ready", e);
                }

                ...

                try {
                    if (telephonyRegistryF != null) telephonyRegistryF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making TelephonyRegistry ready", e);
                }
            }
        });

        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {
            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }

	//         
        Looper.loop();
        Slog.d(TAG, "System ServerThread is exiting!");
    }

    static final void startSystemUi(Context context) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.OWNER);
    }
}

システムアプリケーションフレームワーク層のXxxServiceManagerの準備完了