AMS啟動流程

zerozx發表於2019-01-27

在SystemServer中簡單分析了AMS的流程,這篇就詳細地講解AMS的啟動流程

注意一點:AMS所在的程式是屬於SystemServer中的

時序圖

AMS啟動流程

AMS流程

  • 建立AMS物件
  • 呼叫ams.setSystemProcess
  • 呼叫ams.installSystemProviders
  • 呼叫ams.systemReady

ActivityThread建立

在startBootstrapServices之前有一個流程是 createSystemContext,該過程會建立物件有ActivityThread,Instrumentation, ContextImpl,LoadedApk,Application,這些都是後面AMS要用到的物件,請注意它們是在這裡建立的

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

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }
複製程式碼

建立AMS物件

startBootstrapServices

private void startBootstrapServices() {
    ...
    //啟動AMS服務
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();

    //設定AMS的系統服務管理器
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    //設定AMS的APP安裝器
    mActivityManagerService.setInstaller(installer);
    //初始化AMS相關的PMS
    mActivityManagerService.initPowerManagement();
    ...

    //設定SystemServer
    mActivityManagerService.setSystemProcess();
}
複製程式碼

startService

    public SystemService startService(String className) {
        final Class<SystemService> serviceClass;
        try {
            serviceClass = (Class<SystemService>)Class.forName(className);
        } catch (ClassNotFoundException ex) {
            ......
        }
        return startService(serviceClass);
    }

    public void startService(@NonNull final SystemService service) {
        // Register it.
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            .....
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }
複製程式碼

這部分比較簡單,主要是新增服務,並呼叫服務的 onStart 函式

ActivityManagerService.Lifecycle.class

    public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }

        @Override
        public void onStart() {
            mService.start();
        }

        @Override
        public void onCleanupUser(int userId) {
            mService.mBatteryStatsService.onCleanupUser(userId);
        }

        public ActivityManagerService getService() {
            return mService;
        }
    }
複製程式碼

繼承SystemService,代表是一個系統服務,裡面主要是建立 ActivityManagerService

ActivityManagerService物件建立

public ActivityManagerService(Context systemContext) {
    mContext = systemContext;
    mFactoryTest = FactoryTest.getMode();
    mSystemThread = ActivityThread.currentActivityThread();

    //建立名為"ActivityManager"的前臺執行緒,並獲取mHandler
    mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, false);
    mHandlerThread.start();

    mHandler = new MainHandler(mHandlerThread.getLooper());

    //通過UiThread類,建立名為"android.ui"的執行緒
    mUiHandler = new UiHandler();

    ......

    //建立目錄/data/system
    File dataDir = Environment.getDataDirectory();
    File systemDir = new File(dataDir, "system");
    systemDir.mkdirs();

    //建立服務BatteryStatsService
    mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
    mBatteryStatsService.getActiveStatistics().readLocked();
    ......

    //建立程式統計服務,資訊儲存在目錄/data/system/procstats,
    mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
    ......
    //CPU使用情況的追蹤器執行初始化
    mProcessCpuTracker.init();
    ......
    mRecentTasks = new RecentTasks(this);
    // 建立ActivityStackSupervisor物件
    mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);
    mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);

    //建立名為"CpuTracker"的執行緒
    mProcessCpuThread = new Thread("CpuTracker") {
        public void run() {
         ......
        }
    };
    ......
}
複製程式碼

該過程共建立了3個執行緒

  • ActivityManager
  • android.ui
  • CpuTracker

start

mSystemServiceManager.startService 會呼叫服務的onStart,在AMS裡onStart會呼叫他的start

private void start() {
    Process.removeAllProcessGroups(); //移除所有的程式組
    mProcessCpuThread.start(); //開啟CpuTracker執行緒

    mBatteryStatsService.publish(mContext); //啟動電池統計服務
    mAppOpsService.publish(mContext);
    //建立LocalService,並新增到LocalServices
    LocalServices.addService(ActivityManagerInternal.class, new LocalService());
}
複製程式碼

呼叫ams.setSystemProcess

這個步驟還是在 startBootstrapServices 中執行的

    public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));

            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            ......
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
    }
複製程式碼

如果之前看過筆者寫的binder系列,應該知道 ServiceManager.addService 主要就是新增服務

該函式的主要作用是註冊服務,以及為系統程式設定Application單例並啟動,是由 installSystemApplicationInfo 函式完成的

該函式最終會執行到 LoadedApk 的 installSystemApplicationInfo 函式,來設定包名為 'android' 的 package 資訊

    /**
     * Sets application info about the system package.
     */
    void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        assert info.packageName.equals("android");
        mApplicationInfo = info;
        mClassLoader = classLoader;
    }
複製程式碼

呼叫ams.installSystemProviders

在執行完startBootstrapServices後,最後會執行 startOtherServices 函式

private void startOtherServices() {
  ......
  //安裝系統Provider 
  mActivityManagerService.installSystemProviders();
  ......

  mActivityManagerService.systemReady(new Runnable() {
     public void run() {
         ......
      }
  }
}
複製程式碼

安裝服務,就是在某某連結串列中新增

installSystemProviders 中會呼叫 mSystemThread.installSystemProviders(providers)

 try {
        ActivityManager.getService().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
複製程式碼

那最終呼叫到 AMS的 publishContentProviders 函式,這個函式就是把providers放到map裡等等操作

呼叫ams.systemReady

關於 systemReady 在SystemServer的啟動流程中介紹過了

AMS是最後一個啟動的服務,會呼叫 mActivityManagerService.systemReady

mActivityManagerService.systemReady(new Runnable() {
    public void run() {
        //啟動WebView
      WebViewFactory.prepareWebViewInSystemServer();
      //啟動系統UI
      startSystemUi(context);

      // 執行一系列服務的systemReady方法
      networkScoreF.systemReady();
      networkManagementF.systemReady();
      networkStatsF.systemReady();

      ......

      //執行一系列服務的systemRunning方法
      wallpaper.systemRunning();
      inputMethodManager.systemRunning(statusBarF);
      location.systemRunning();

    }
});
複製程式碼

systemReady大致流程

public final class ActivityManagerService{

    public void systemReady(final Runnable goingCallback) {
        ...//更新操作
        mSystemReady = true; //系統處於ready狀態
        removeProcessLocked(proc, true, false, "system update done");//殺掉所有非persistent程式
        mProcessesReady = true;  //程式處於ready狀態

        goingCallback.run(); //這裡有可能啟動程式

        addAppLocked(info, false, null); //啟動所有的persistent程式
        mBooting = true;  //正在啟動中
        startHomeActivityLocked(mCurrentUserId, "systemReady"); //啟動桌面
        mStackSupervisor.resumeTopActivitiesLocked(); //恢復棧頂的Activity
    }
}
複製程式碼

相關文章