ActivityManagerService (ActivityManagerService, ActivityManagerService, ActivityManagerService)

Today we will look at the startup of ActivityManageerService, which will be referred to as AMS for short.

Start the AMS

The startup of AMS occurs during the BootPhase 0 phase of the SystemServer startup process.

In the start service of the three classification services, the startBootstrapServices method

private void startBootstrapServices() { ... ActivityTaskManagerService atm = mSystemServiceManager.startService( ActivityTaskManagerService.Lifecycle.class).getService(); mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mWindowManagerGlobalLock = atm.getGlobalLock(); . }Copy the code

AMS’s is created through AMS’s internal class Lifecycle, with a call to Lifecycle.onstart () to start AMS.

public static final class Lifecycle extends SystemService { private final ActivityManagerService mService; private static ActivityTaskManagerService sAtm; public Lifecycle(Context context) { super(context); mService = new ActivityManagerService(context, sAtm); } public static ActivityManagerService startService( SystemServiceManager ssm, ActivityTaskManagerService atm) { sAtm = atm; return ssm.startService(ActivityManagerService.Lifecycle.class).getService(); } @Override public void onStart() { mService.start(); }... }Copy the code

Lifecycle inherits from SystemService and starts the Service through the SSM (SystemServiceManager).

Internally Lifecycle instances are created through reflection and AMS is created during Lifecycle instances.

So what do we do when we instantiate AMS

public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) { ... // Create a thread named ActivityManager, Create MainHandler // thread to handle various state information (GC, Service_TIMEOUT, update_TIME_zone, kill_application, kill_zygote) mHandlerThread = new ServiceThread(TAG, THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); mHandlerThread.start(); mHandler = new MainHandler(mHandlerThread.getLooper()); // getUiHandler mUiHandler = minector. GetUiHandler (this); MProcStartHandlerThread = new ServiceThread(TAG + ":procStart", THREAD_PRIORITY_FOREGROUND, false /* allowIo */); mProcStartHandlerThread.start(); mProcStartHandler = new Handler(mProcStartHandlerThread.getLooper()); MConstants = new ActivityManagerConstants(mContext, this, mHandler); ActiveUids ActiveUids = new ActiveUids(this, true /* postChangesToAtm */); mProcessList.init(this, activeUids); // mLowMemDetector = new LowMemDetector(this); mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids); / / the foreground radio receiver final BroadcastConstants foreConstants = new BroadcastConstants (Settings. Global. BROADCAST_FG_CONSTANTS); foreConstants.TIMEOUT = BROADCAST_FG_TIMEOUT; / / the background radio receiver final BroadcastConstants backConstants = new BroadcastConstants (Settings. Global. BROADCAST_BG_CONSTANTS); backConstants.TIMEOUT = BROADCAST_BG_TIMEOUT; Final BroadcastConstants offloadConstants = new BroadcastConstants( Settings.Global.BROADCAST_OFFLOAD_CONSTANTS); offloadConstants.TIMEOUT = BROADCAST_BG_TIMEOUT; offloadConstants.SLOW_TIME = Integer.MAX_VALUE; mEnableOffloadQueue = SystemProperties.getBoolean( "persist.device_config.activity_manager_native_boot.offload_queue_enabled", false); mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", foreConstants, false); mBgBroadcastQueue = new BroadcastQueue(this, mHandler, "background", backConstants, true); mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, "offload", offloadConstants, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; mBroadcastQueues[2] = mOffloadBroadcastQueue; mServices = new ActiveServices(this); mProviderMap = new ProviderMap(this); mPackageWatchdog = PackageWatchdog.getInstance(mUiContext); mAppErrors = new AppErrors(mUiContext, this, mPackageWatchdog); final File systemDir = SystemServiceManager.ensureSystemDir(); MBatteryStatsService = new BatteryStatsService(systemContext, systemDir, backgroundThread.get ().gethandler ())); mBatteryStatsService.getActiveStatistics().readLocked(); mBatteryStatsService.scheduleWriteToDisk(); mOnBattery = DEBUG_POWER ? true : mBatteryStatsService.getActiveStatistics().getIsOnBattery(); mBatteryStatsService.getActiveStatistics().setCallback(this); mOomAdjProfiler.batteryPowerChanged(mOnBattery); MProcessStats = new ProcessStatsService(this, new File(systemDir, "procStats ")); mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler); . mActivityTaskManager = atm; mActivityTaskManager.initialize(mIntentFirewall, mPendingIntentController, DisplayThread.get().getLooper()); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); MProcessCpuThread = new Thread("CpuTracker") {@override public void run() {synchronized (mProcessCpuTracker) { mProcessCpuInitLatch.countDown(); mProcessCpuTracker.init(); } while (true) { try { try { synchronized(this) { final long now = SystemClock.uptimeMillis(); long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now; long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now; //Slog.i(TAG, "Cpu delay=" + nextCpuDelay // + ", write delay=" + nextWriteDelay); if (nextWriteDelay < nextCpuDelay) { nextCpuDelay = nextWriteDelay; } if (nextCpuDelay > 0) { mProcessCpuMutexFree.set(true); this.wait(nextCpuDelay); }} catch (InterruptedException e) {} // Update CPU information updateCpuStatsNow(); } catch (Exception e) { Slog.e(TAG, "Unexpected exception collecting process stats", e); }}}}; . }Copy the code

So the main thing to do here is to create ActivityManager, Proc, and CpuTracker threads; Create the corresponding broadcast receiver at the same time.

After an AMS instance is created, the start() method is called to start AMS

Private void start() {removeAllProcessGroups(); Mprocesscputhread.start (); / / start battery statistics service mBatteryStatsService. The publish (); mAppOpsService.publish(mContext); / / added to the local LocalServices LocalServices. The addService (ActivityManagerInternal. Class, new LocalService ()); mActivityTaskManager.onActivityManagerInternalAdded(); mUgmInternal.onActivityManagerInternalAdded(); mPendingIntentController.onActivityManagerInternalAdded(); Try {/ / wait for the process CPU statistics thread running mProcessCpuInitLatch. Await (); } catch (InterruptedException e) { Slog.wtf(TAG, "Interrupted wait during start", e); Thread.currentThread().interrupt(); throw new IllegalStateException("Interrupted wait during start"); }}Copy the code

At this point, AMS is already up and running.

What AMS does in SystemServer

startBootstrapServices

private void startBootstrapServices() { ... mActivityManagerService.initPowerManagement(); . mActivityManagerService.setSystemProcess(); . }Copy the code

initPowerManagement

PowerManagement is initialized first

public void initPowerManagement() {
    mActivityTaskManager.onInitPowerManagement();
    mBatteryStatsService.initPowerManagement();
    mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class);
}
Copy the code

PowerManagement will eventually be initialized via BatterStateService.

setSystemProcess

Next comes setSystemProcess, which registers the related services.

Public void setSystemProcess () {try {/ / registered ActivityManagerService ServiceManager. The addService (Context) ACTIVITY_SERVICE, this, /* allowIsolated= */ true, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO); / / registered ProcessStatsService ServiceManager. The addService (ProcessStats SERVICE_NAME, mProcessStats); / / registered MemBinder ServiceManager. The addService (" meminfo, "new MemBinder (this), allowIsolated = / * * / false, DUMP_FLAG_PRIORITY_HIGH); / / registered GraphicsBinder ServiceManager. The addService (" gfxinfo ", new GraphicsBinder (this)); / / registered DbBinder ServiceManager. The addService (" dbinfo ", new DbBinder (this)); If (MONITOR_CPU_USAGE) {/ / registered CpuBinder ServiceManager. The addService (" cpuinfo, "new CpuBinder (this), /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); } / / registered PermissionController ServiceManager. The addService (" permission ", new PermissionController (this)); / / registered ProcessInfoService ServiceManager. The addService (" processinfo ", new ProcessInfoService (this)); // Load the package named Android, Finally to load by LoadedApk ApplicationInfo info = mContext. GetPackageManager (). GetApplicationInfo (" android ", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY); mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader()); . }Copy the code

Note that the AMS is registered with the ServiceManager, and then the registered AMS is retrieved through the ActivityManager.

Next, you enter startCoreServices to start the core service

startCoreServices

private void startCoreServices() { ... mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); . }Copy the code

The thing to do here is very simple, set up the UsageStateManager

startOtherServices

Proceed to start the other service modules

private void startOtherServices() { ... mActivityManagerService.installSystemProviders(); mActivityManagerService.setWindowManager(wm); mActivityManagerService.systemReady(...) . }Copy the code

The main work here is to install the system Provider and set up WindowManagerService and systemReady.

installSystemProviders

public final void installSystemProviders() { List<ProviderInfo> providers; synchronized (this) { ProcessRecord app = mProcessList.mProcessNames.get("system", SYSTEM_UID); / / get will will = generateApplicationProvidersLocked (app); if (providers ! = null) { for (int i=providers.size()-1; i>=0; i--) { ProviderInfo pi = (ProviderInfo)providers.get(i); If ((pi.applicationInfo. flags&applicationInfo. FLAG_SYSTEM) == 0) {Providers. Remove (I); }}}} // Install the system's Providers via ActivityThread. = null) { mSystemThread.installSystemProviders(providers); } synchronized (this) { mSystemProvidersInstalled = true; } mConstants.start(mContext.getContentResolver()); mCoreSettingsObserver = new CoreSettingsObserver(this); mActivityTaskManager.installSystemProviders(); mDevelopmentSettingsObserver = new DevelopmentSettingsObserver(); SettingsToPropertiesMapper.start(mContext.getContentResolver()); mOomAdjuster.initSettings(); }Copy the code

The main task here is to install the system Providers

WindowManagerService

public void setWindowManager(WindowManagerService wm) { synchronized (this) { mWindowManager = wm; mActivityTaskManager.setWindowManager(wm); }}Copy the code

Set up the WindowManagerService service

systemReady

SystemReady has a lot of logic, so let’s break it down

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { goingCallback before if (goingCallback ! = null) goingCallback.run(); goingCallback after }Copy the code

Before calling goingcallback.run

Public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {synchronized(this) { Skip if (mSystemReady) {if (goingCallback! = null) { goingCallback.run(); } return; }... mSystemReady = true; }... ArrayList<ProcessRecord> procsToKill = null; synchronized(mPidsSelfLocked) { for (int i=mPidsSelfLocked.size()-1; i>=0; i--) { ProcessRecord proc = mPidsSelfLocked.valueAt(i); // non-president process if (! isAllowedWhileBooting(proc.info)){ if (procsToKill == null) { procsToKill = new ArrayList<ProcessRecord>(); } // Add procstokill.add (proc); } } } synchronized(this) { if (procsToKill ! = null) {// kill procsToKill process for (int I = procstokill.size ()-1; i>=0; i--) { ProcessRecord proc = procsToKill.get(i); mProcessList.removeProcessLocked(proc, true, false, "system update done"); } } mProcessesReady = true; }... if (goingCallback ! = null) goingCallback.run(); . }Copy the code

The main thing to do is kill the process in procsToKill, at which point the system and process are ready

Goingcallback.run is then called

mActivityManagerService.systemReady(() -> { // BootPhase 550 mSystemServiceManager.startBootPhase( SystemService.PHASE_ACTIVITY_MANAGER_READY); try { mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } traceBeginAndSlog("MakeConnectivityServiceReady"); try { if (connectivityF ! = null) { connectivityF.systemReady(); } } catch (Throwable e) { reportWtf("making Connectivity Service ready", e); }... // BootPhase 600 mSystemServiceManager.startBootPhase( SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); try { if (locationF ! = null) { locationF.systemRunning(); } } catch (Throwable e) { reportWtf("Notifying Location Service running", e); } try { if (countryDetectorF ! = null) { countryDetectorF.systemRunning(); } } catch (Throwable e) { reportWtf("Notifying CountryDetectorService running", e); }... }, BOOT_TIMINGS_TRACE_LOG);Copy the code

This has already been analyzed in the Android SystemServer startup (2), which is not covered here.

It is mainly used for systemReady and systemRuning of some services.

Finally, we come to the last step of systemReady

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { ... if (goingCallback ! = null) goingCallback.run(); final int currentUserId = mUserController.getCurrentUserId(); if (currentUserId ! = UserHandle.USER_SYSTEM && ! mUserController.isSystemUserStarted()) { throw new RuntimeException("System user not started while current user is:" + currentUserId); } mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START, Integer.toString(currentUserId), currentUserId); mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(currentUserId), currentUserId); / / call all SystemService onStartUser method mSystemServiceManager. StartUser (currentUserId); Synchronized (this) {// Enable Persistent app startPersistentApps(packagemanager.match_direct_boot_aware); mBooting = true; if (UserManager.isSplitSystemUser() && Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0) ! = 0) { ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class); try { AppGlobals.getPackageManager().setComponentEnabledSetting(cName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, UserHandle.USER_SYSTEM); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); }} / / start system desktop Activity mAtmInternal. StartHomeOnAllDisplays (currentUserId "systemReady"); mAtmInternal.showSystemReadyErrorDialogsIfNeeded(); final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); long ident = Binder.clearCallingIdentity(); Intent = new Intent(intent.action_user_started); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, currentUserId); Intent.action_user_starting = new intent.action_user_starting; intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId); broadcastIntentLocked(null, null, intent, null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { } }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); } catch (Throwable t) { Slog.wtf(TAG, "Failed sending first user broadcasts", t); } finally { Binder.restoreCallingIdentity(ident); } mAtmInternal.resumeTopActivities(false /* scheduleIdle */); mUserController.sendUserSwitchBroadcasts(-1, currentUserId); BinderInternal.nSetBinderProxyCountWatermarks(BINDER_PROXY_HIGH_WATERMARK, BINDER_PROXY_LOW_WATERMARK); BinderInternal.nSetBinderProxyCountEnabled(true); BinderInternal.setBinderProxyCountCallback( new BinderInternal.BinderProxyLimitListener() { @Override public void onLimitReached(int uid) { Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid " + Process.myUid()); BinderProxy.dumpProxyDebugInfo(); if (uid == Process.SYSTEM_UID) { Slog.i(TAG, "Skipping kill (uid is SYSTEM)"); } else { killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid), "Too many Binders sent to SYSTEM"); } } }, mHandler); . / / the Activity recovery stack mAtmInternal resumeTopActivities (false scheduleIdle / * * /); / / send User_SWITCH radio mUserController. SendUserSwitchBroadcasts (1, currentUserId); . }}Copy the code

StartUser calls back to the previous SystemService onStartUser method

public void startUser(final int userHandle) { final int serviceLen = mServices.size(); MServices for (int I = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStartUser " + service.getClass().getName()); long time = SystemClock.elapsedRealtime(); Try {// Callback onStartUser service.onStartUser(userHandle); } catch (Exception ex) { Slog.wtf(TAG, "Failure reporting start of user " + userHandle + " to service " + service.getClass().getName(), ex); }}}Copy the code

Starthome all displays will eventually come to the startHomeOnDisplay method of RootActivityContainer

boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) { if (displayId == INVALID_DISPLAY) { displayId = getTopDisplayFocusedStack().mDisplayId; } Intent homeIntent = null; ActivityInfo aInfo = null; if (displayId == DEFAULT_DISPLAY) { homeIntent = mService.getHomeIntent(); aInfo = resolveHomeActivity(userId, homeIntent); } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) { Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId); aInfo = info.first; homeIntent = info.second; } if (aInfo == null || homeIntent == null) { return false; } if (! canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) { return false; } / / set the home homeIntent. The Intent of Component information setComponent (new the ComponentName (aInfo. ApplicationInfo. PackageName, aInfo.name)); homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); / / set up extra if (fromHomeKey) {homeIntent. PutExtra (WindowManagerPolicy EXTRA_FROM_HOME_KEY, true); } final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( aInfo.applicationInfo.uid) + ":" + displayId; / / start the desktop Activity mService. GetActivityStartController () startHomeActivity (homeIntent aInfo, myReason, displayId); return true; }Copy the code

To summarize, after goingcallback. run, this phase mainly does the following:

  1. Call all the previously added onesSystemServicetheonStartUsermethods
  2. Start thePersistentprocess
  3. Start the system desktop Activity
  4. Send USER_STARTED broadcast
  5. Send a USER_STARTING broadcast
  6. Resume top of stack Activity
  7. Sends a User_SWITCH broadcast

This is the whole process of AMS in SystemServer, and also the startup process of AMS.

The main things that the whole process does are:

  1. throughLifecyclecreateAMSInstance at the same timeonStart()Methods to start theAMS
  2. throughsetSystemProcessregisteredAMS,meminfo,gfxinfo,dbinfo,cpuinfoAnd other services toServiceManagerIn the
  3. throughinstallSystemProvidersTo load the systemproviders
  4. throughsystemReadytoreadywithrunningVarious services simultaneously launch desktop applications, send related broadcasts with restore stack topActivity

Wechat public number: Android supply station, focusing on Android advanced, algorithm and interview analysis, as well as irregular benefits

recommended

Android_startup: Provides a simpler and more efficient way to initialize components at application startup. Developers can use Android-startup to simplify the startup sequence and explicitly set the dependency between the initialization order and the components. Meanwhile, Android-startup supports synchronous and asynchronous wait, and ensures the initialization sequence of internal dependent components by means of directed acyclic topology sorting.

AwesomeGithub: Based on Github client, pure exercise project, support componentized development, support account password and authentication login. Kotlin language for development, the project architecture is based on Jetpack&DataBinding MVVM; Popular open source technologies such as Arouter, Retrofit, Coroutine, Glide, Dagger and Hilt are used in the project.

Flutter_github: a cross-platform Github client based on Flutter, corresponding to AwesomeGithub.

Android-api-analysis: A comprehensive analysis of Knowledge points related to Android with detailed Demo to help readers quickly grasp and understand the main points explained.

Daily_algorithm: advanced algorithm, from shallow to deep, welcome to join us.