1. 程式人生 > >Android中system server程序啟動流程原始碼解析 系統服務啟動

Android中system server程序啟動流程原始碼解析 系統服務啟動

system server

前言

在平時的開發中或多或少會了解過ActivityManagerService,WindowManagerService,PowerManagerService等服務,那你有想過這些服務如何產生的嗎,它們執行在哪呢?我們是如何獲取到這些服務的呢?要想了解這些就要看System Server程序了

本篇部落格原始碼基於API24

System Server

System Server程序和Zygote程序可以說是Android世界中的兩大最重要的程序,離開其中之一基本上系統就玩完了(這裡還有一個Media Server程序,是由init程序fork而來,負責啟動和管理整個C++ framework,包含AudioFlinger,Camera Service等服務);System Server負責啟動和管理整個framework,基本上在Framework中的大多數服務都是在system server程序中以一個執行緒的方式存在的;System Server程序的程序名是system_server,大家可以通過adb shell ps檢視當前手機存在的程序資訊,可以看到這幾條

USER     PID   PPID   VSIZE    RSS     WCHAN    PC         NAME
root      1     0     9048     1012    ffffffff 00000000 S /init

root      349   1     2118552  17464   ffffffff 00000000 S zygote64
root      350   1     1526172  16800   ffffffff 00000000 S zygote

system    793   349   2792784  109876  ffffffff 00000000 S system_server

fork SystemServer

System Server程序是由Zygote程序fork出來的,至於如何被Zygote程序fork出來的以及Zygote程序的資訊可以參考下面部落格
Android系統啟動流程概述 init程序啟動 zygote程序啟動 system server程序啟動

zygote程序fork成功後,會反射呼叫SystemServer.main()方法,至此進入system server程序的工作空間

SystemServer.main()

public static void main(String[] args) {
        new SystemServer().run();
}

private void run() {
        try {
           	//若當前時間小於1970年1月1日,那就設定為1970年1月1日
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }
            //設定系統的語言環境
			if (!SystemProperties.get("persist.sys.language").isEmpty()) {
                final String languageTag = Locale.getDefault().toLanguageTag();
                SystemProperties.set("persist.sys.locale", languageTag);
                SystemProperties.set("persist.sys.language", "");
                SystemProperties.set("persist.sys.country", "");
                SystemProperties.set("persist.sys.localevar", "");
            }
            
            //變更虛擬機器的庫檔案,對於Android 6.0預設採用的是libart.so
            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

            //清除vm記憶體增長上限,由於啟動過程需要較多的虛擬機器記憶體空間
            VMRuntime.getRuntime().clearGrowthLimit();

            //設定記憶體的可能有效使用率為0.8
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

            // 針對部分裝置依賴於執行時就產生指紋資訊,因此需要在開機完成前已經定義
            Build.ensureFingerprintProperty();

            //訪問環境變數前,需要明確地指定使用者
            Environment.setUserRequired(true);

            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);

            //確保當前系統程序的binder呼叫,總是執行在前臺優先順序(foreground priority)
            BinderInternal.disableBackgroundScheduling(true);

            // 增加system_server中的binder執行緒數
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            // 建立主執行緒looper 在當前執行緒執行
            android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper();

            //初始化android_servers庫
            System.loadLibrary("android_servers");

            //檢測上次關機過程是否失敗
            performPendingShutdown();

            //初始化系統上下文
            //初始化系統上下文物件mSystemContext,並設定預設的主題,mSystemContext實際上是一個ContextImpl物件。
            //呼叫ActivityThread.systemMain()的時候,會呼叫ActivityThread.attach(true),而在attach()裡面,則建立了Application物件,並呼叫了Application.onCreate()。
            createSystemContext();

            //建立系統服務管理
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        //啟動各種系統服務
        try {
	        //引導服務
            startBootstrapServices();
            //核心服務
            startCoreServices();
            //其它服務
            startOtherServices();
        } catch (Throwable ex) {
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        //開啟訊息迴圈
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

這個main方法做了很多事情:設定系統時間,設定語言環境,設定虛擬機器記憶體,設定binder執行緒數,初始化Loop,載入執行庫等

除了這些操作外,接下來繼續往下看main方法後半段


SystemServer.createSystemContext

private Context mSystemContext;

private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}

沒想到啊,原來System Server中也有Context物件,這個方法就是初始化system context;可能有人不太理解Context到底是個什麼玩意

Context英文原意是上下文的意思,在平時開發中涉及到的四大元件及資源操作基本上都離不開Context物件;你可以想象它是一團神祕的漂浮的物質,在一個生活場景中,不管你在哪,在幹什麼,你都可以通過這團神祕物質獲取到一些屬於這個場景的隱性資訊

比如你在吃一條魚這個場景,你能知道的就是這條魚多大,多好吃,但是假如你有Context這個上下文資訊,你就能獲取到更多資訊,比如魚的重量,魚的種類,魚的年齡等,用程式碼表示就是Context.getFishType(),你就知道這條魚的種類了

這就是上下文的意思,某一個場景下一些隱藏的資訊

其實Context家族很複雜,Context本身是一個抽象類,而ContextImpl,ContextWrapper,Activity,Service,Application等都是它的直接或間接子類

接下來我們看下方法後續呼叫

public static ActivityThread systemMain() {
        // 低記憶體裝置上的系統程序無法使用硬體加速繪圖,因為這會給程序增加太多開銷
        if (!ActivityManager.isHighEndGfx()) {
            ThreadedRenderer.disable(true);
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
}

public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                mSystemContext = ContextImpl.createSystemContext(this);
            }
            return mSystemContext;
        }
}

其中 thread.attach(true)這句話經過一系列呼叫後會建立很多物件,比如ActivityThread,Instrumentation, ContextImpl,LoadedApk,Application等

具體執行過程可檢視博主部落格

從Activity載入原始碼深入理解ActivityThrad的工作邏輯

執行完後System Server後續就能用到這些物件了


SystemServiceManager

繼續往下看

//建立系統服務管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

這裡是例項化SystemServiceManager物件,這個類主要是用來對System server中的一些系統服務的建立,啟動和其它的一些生命週期事件進行管理

SystemServiceManager維護了一個集合

private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();

SystemServer啟動的很多服務都儲存在這個集合裡


啟動服務三連

		//啟動各種系統服務
        try {
	        //引導服務
            startBootstrapServices();
            //核心服務
            startCoreServices();
            //其它服務
            startOtherServices();
        } catch (Throwable ex) {
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

main方法最後會執行這三個重要的啟動服務方法,先看第一個

SystemServer.startBootstrapServices

這個方法將會啟動一些引導服務

	private PowerManagerService mPowerManagerService;
    private ActivityManagerService mActivityManagerService;
    private WebViewUpdateService mWebViewUpdateService;
    private DisplayManagerService mDisplayManagerService;
    private PackageManagerService mPackageManagerService;
    private PackageManager mPackageManager;
		
	/**
     * 啟動一些系統執行必須的關鍵服務,這些服務具有複雜的相互依賴性,所以就在這裡全部初始化
     */
    private void startBootstrapServices() {
        // 阻塞等待installd完成啟動,與其建立socket通道
        // 以便它有機會使用適當的許可權建立關鍵目錄,例如/ data / user
        // 在初始化其他服務之前,我們需要完成此操作
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // 啟動ActivityManagerService
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

        // PowerManagerService需要儘早啟動,因為其他服務需要它。 本機守護程式可能正在監視它是否已註冊
        // 因為它要立即準備好處理傳入進來的binder呼叫(包括能夠驗證這些呼叫的許可權)
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // 現在電源管理器已經啟動,讓ActivityManagerService初始化電源管理功能
        mActivityManagerService.initPowerManagement();

        // 啟動服務LightsService 管理LED並顯示背光
        mSystemServiceManager.startService(LightsService.class);

        // 啟動服務DisplayManagerService
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        // 在初始化package manager之前,需要預設的顯示
        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        // 如果我們正在加密裝置,則只執行“核心”應用程式.
        String cryptState = SystemProperties.get("vold.decrypt");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            //加密程式正在執行
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            //已經被加密了
            mOnlyCore = true;
        }

        // 啟動PackageManagerService
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();

        // 沒有加密的話進行odex優化
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",false);
            if (!disableOtaDexopt) {
                traceBeginAndSlog("StartOtaDexOptService");
                try {
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {
                    reportWtf("starting OtaDexOptService", e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                }
            }
        }

        //啟動服務UserManagerService,新建目錄/data/user/
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);

        //初始化屬性快取用來快取包資源.
        AttributeCache.init(mSystemContext);

        // 為系統程序設定Application例項並開始使用
        mActivityManagerService.setSystemProcess();

        // 啟動感測器服務
        // 感測器服務需要訪問包管理器服務,app ops服務和許可權服務,因此我們在它們之後啟動它
        startSensorService();
    }
    
    //這是native方法
    private static native void startSensorService();

可以看到這裡啟動了很多系統關鍵性服務,而且都是通過SystemServiceManager例項去操作

SystemServiceManager.startService

/**
     * 建立並啟動 system service. 且這些服務必須是SystemService子類
     *
     * @param serviceClass A Java class that implements the SystemService interface.
     * @return The service instance, never null.
     * @throws RuntimeException if the service fails to start.
     */
    @SuppressWarnings("unchecked")
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();

            // 建立 service.
            if (!SystemService.class.isAssignableFrom(serviceClass)) {
                throw new RuntimeException("Failed to create " + name
                        + ": service must extend " + SystemService.class.getName());
            }
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } catch (InstantiationException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service could not be instantiated", ex);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (NoSuchMethodException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (InvocationTargetException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service constructor threw an exception", ex);
            }

            // 新增到list集合
            mServices.add(service);

            try {
            		//啟動
                service.onStart();
            } catch (RuntimeException ex) {
                throw new RuntimeException("Failed to start service " + name
                        + ": onStart threw an exception", ex);
            }
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

這裡都是通過反射構造出這些服務的例項,然後呼叫它們的onStart方法啟動,以Installer服務為例看一下

Installer.onStart

public final class Installer extends SystemService {

		private final InstallerConnection mInstaller;
		
		public Installer(Context context) {
	        super(context);
	        mInstaller = new InstallerConnection();
    	}
		
		@Override
    	public void onStart() {
        	//等待installd準備完畢
        	mInstaller.waitForConnection();
    	}
    
}
    
public class InstallerConnection {

    public void waitForConnection() {
        for (;;) {
            try {
                execute("ping");
                return;
            } catch (InstallerException ignored) {
            }
            //還沒準備好,休息一秒繼續嘗試
            SystemClock.sleep(1000);
        }
    }
    
}

其實就是不斷的通過ping命令連線Zygote程序(SystemServer和Zygote程序通過socket方式通訊,其他程序通過Binder方式通訊),成功連線之後才會開始啟動其他服務


SystemServer.startCoreServices

接下來看第二個啟動方法

	/**
     * 啟動一些與引導服務沒有複雜依賴的基本服務
     */
    private void startCoreServices() {
        // 啟動BatteryService 跟蹤電池電量
        mSystemServiceManager.startService(BatteryService.class);

        // 啟動UsageStatsService 跟蹤應用程式使用統計資訊
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));

        // 啟動WebViewUpdateService 跟蹤可更新的WebView是否處於就緒狀態並監視更新安裝。
        mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);   
    }

SystemServer.startOtherServices

這個方法著實有點長,將近一千行,不過做的事情不復雜,主要是啟動服務;這裡就不一一列舉了

private void startOtherServices() {
        final Context context = mSystemContext;
        //這裡會啟動一堆雜七雜八的服務
        VibratorService vibrator = null;
        IMountService mountService = null;
        NetworkManagementService networkManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        ConnectivityService connectivity = null;
        NetworkScoreService networkScore = null;
        NsdService serviceDiscovery= null;
        WindowManagerService wm = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        CommonTimeManagementService commonTimeMgmtService = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        MmsServiceBroker mmsService = null;
        HardwarePropertiesManagerService hardwarePropertiesService = null;

		//讀取配置資訊
        boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
        boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
        boolean disableLocation = SystemProperties.getBoolean("config.disable_location", false);
        boolean disableSystemUI = SystemProperties.getBoolean("config.disable_systemui", false);
        boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
        boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
        boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false);
        boolean disableRtt = SystemProperties.getBoolean("config.disable_rtt", false);
        boolean disableMediaProjection = SystemProperties.getBoolean("config.disable_mediaproj",
                false);
        boolean disableSerial = SystemProperties.getBoolean("config.disable_serial", false);
        boolean disableSearchManager = SystemProperties.getBoolean("config.disable_searchmanager",
                false);
        boolean disableTrustManager = SystemProperties.getBoolean("config.disable_trustmanager",
                false);
        boolean disableTextServices = SystemProperties.getBoolean("config.disable_textservices", false);
        boolean disableSamplingProfiler = SystemProperties.getBoolean("config.disable_samplingprof",
                false);
        boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");

        try {
            SystemConfig.getInstance();

            ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
            
            mSystemServiceManager.startService(TelecomLoaderService.class);

            telephonyRegistry = new TelephonyRegistry(context);
            ServiceManager.addService("telephony.registry", telephonyRegistry);

			......
						
        } catch (RuntimeException e) {
            Slog.e("System", "************ Failure starting core service", e);
        }

        StatusBarManagerService statusBar = null;
        INotificationManager notification = null;
        LocationManagerService location = null;
        CountryDetectorService countryDetector = null;
        ILockSettings lockSettings = null;
        AssetAtlasService atlas = null;
        MediaRouterService mediaRouter = null;
				
		......

		ActivityManagerNative.getDefault().showBootMessage(...); //顯示啟動介面

        
        try {
            vibrator.systemReady();
        } catch (Throwable e) {
            reportWtf("making Vibrator Service ready", e);
        }

        
        mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
        mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);

        try {
            wm.systemReady();
        } catch (Throwable e) {
            reportWtf("making Window Manager Service ready", e);
        }

		......

        
        mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {

                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_ACTIVITY_MANAGER_READY);
								
				......

                try {
                    startSystemUi(context);
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }


                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);

               ......
            }
        });
    }

這裡會啟動大量的服務,到這裡系統服務基本上啟動完成,system_server程序隨後進入Looper.loop()狀態,隨時等待訊息到來

總結

  • SystemServer程序啟動後會設定系統時間,設定語言環境,設定虛擬機器記憶體,設定binder執行緒數,初始化Loop,載入執行庫等
  • 接下來建立Context物件,SystemServiceManager物件
  • 最後啟動三類服務:引導服務,核心服務,其它服務;其中引導服務有7個,核心服務有三個,其他服務有70+
  • 進行訊息迴圈,隨時處理接收到的事件