Overall timing
// DisplayContent.java boolean updateDisplayOverrideConfigurationLocked(Configuration values, ActivityRecord starting, boolean deferResume, ActivityTaskManagerService.UpdateConfigurationResult result) {<!-- --> int changes = 0; boolean kept = true; mAtmService.deferWindowLayout(); try {<!-- --> if (values != null) {<!-- --> if (mDisplayId == DEFAULT_DISPLAY) {<!-- --> // First trigger process-related Configuration changes changes = mAtmService.updateGlobalConfigurationLocked(values, false /* initLocale */, false /* persistent */, UserHandle.USER_NULL /* userId */); } else {<!-- --> changes = performDisplayOverrideConfigUpdate(values); } } if (!deferResume) {<!-- --> // Then trigger changes in Activity-related Configuration kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes); } } finally {<!-- --> mAtmService.continueWindowLayout(); } ..... }
Process level ConfigurationChangeItem
The main purpose is to update the Configuration in the Resource of the app process and trigger the onConfigurationChanged callback of Application/Service/Provider, etc.
System server
// ATMS.java int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale, boolean persistent, int userId) {<!-- --> ... Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig); ... SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap(); for (int i = pidMap.size() - 1; i >= 0; i--) {<!-- --> final int pid = pidMap.keyAt(i); final WindowProcessController app = pidMap.get(pid); ProtoLog.v(WM_DEBUG_CONFIGURATION, "Update process config of %s to new " + "config %s", app.mName, mTempConfig); app.onConfigurationChanged(mTempConfig); } ... }
// WindowProcessController.java private void scheduleConfigurationChange(IApplicationThread thread, Configuration config) {<!-- --> ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName, config); ... mHasCachedConfiguration = false; try {<!-- --> mAtm.getLifecycleManager().scheduleTransaction(thread, ConfigurationChangeItem.obtain(config, mLastTopActivityDeviceId)); } catch (Exception e) {<!-- --> Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change: " + mOwner, e); } }
App
// ConfigurationController.java void handleConfigurationChanged(@Nullable Configuration config, @Nullable CompatibilityInfo compat) {<!-- --> ... synchronized (mResourcesManager) {<!-- --> ... //First update the value of Configuration in Resource mResourcesManager.applyConfigurationToResources(config, compat); ... } final ArrayList<ComponentCallbacks2> callbacks = mActivityThread.collectComponentCallbacks(false /* includeUiContexts */); freeTextLayoutCachesIfNeeded(configDiff); if (callbacks != null) {<!-- --> final int size = callbacks.size(); for (int i = 0; i < size; i + + ) {<!-- --> ComponentCallbacks2 cb = callbacks.get(i); if (!equivalent) {<!-- --> // Then trigger the callback of Application/Service/Provider, etc. performConfigurationChanged(cb, config); } } } }
Activity level
Two ways of processing
For activity-level processing, only one of relaunching the current Activity or triggering the current Actiivty callback onConfigurationChanged method will occur.
- When the app configures the corresponding configChanges in AndroidManifest.xml, it triggers the Activity callback onConfigurationChanged method.
- Otherwise, perform the relaunch operation directly
ActivityRelaunchItem
If the app does not configure the corresponding configChanges in AndroidManifest.xml, the relaunch of the current top page will be triggered when the configuration changes. The corresponding event log is as follows:
10-10 16:12:05.951 3972 8346 I configuration_changed: 512 10-10 16:12:06.021 3972 8346 I wm_relaunch_resume_activity: [0,237413577,21,com.miui.gallery/.activity.MapActivity,200] 10-10 16:12:06.022 3972 8346 I wm_relaunch_activity: [0,218943334,21,com.miui.gallery/.activity.HomePageActivity,200] // The page of top resume still stays in the onResume state after reconstruction. 10-10 16:12:06.244 20930 20930 I wm_on_top_resumed_lost_called: [237413577,com.miui.gallery.activity.MapActivity,pausing] 10-10 16:12:06.284 20930 20930 I wm_on_paused_called: [0,237413577,com.miui.gallery.activity.MapActivity,performPause,39] 10-10 16:12:06.294 20930 20930 I wm_on_stop_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleRelaunchActivity,2] 10-10 16:12:06.328 20930 20930 I wm_on_destroy_called: [0,237413577,com.miui.gallery.activity.MapActivity,performDestroy,32] 10-10 16:12:06.461 20930 20930 I wm_on_create_called: [0,237413577,com.miui.gallery.activity.MapActivity,performCreate,29] 10-10 16:12:06.599 20930 20930 I wm_on_start_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleStartActivity,135] 10-10 16:12:06.603 20930 20930 I wm_on_resume_called: [0,237413577,com.miui.gallery.activity.MapActivity,RESUME_ACTIVITY,2] 10-10 16:12:06.603 20930 20930 I wm_on_top_resumed_gained_called: [237413577,com.miui.gallery.activity.MapActivity,topWhenResuming] // Visible but the final state of the pause page is still onPause after reconstruction 10-10 16:12:06.625 20930 20930 I wm_on_stop_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleRelaunchActivity,6] 10-10 16:12:06.649 20930 20930 I wm_on_destroy_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performDestroy,13] 10-10 16:12:06.701 20930 20930 I wm_on_create_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performCreate,34] 10-10 16:12:06.903 20930 20930 I wm_on_start_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleStartActivity,199] 10-10 16:12:06.910 20930 20930 I wm_on_resume_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,LIFECYCLER_RESUME_ACTIVITY,5] 10-10 16:12:06.926 20930 20930 I wm_on_paused_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performPause,1]
Send a ClientTransaction to the app process:
- If it should resume: ActivityRelaunchItem (handles Activity reconstruction) & ResumeActivityItem (handles final life cycle)
- Otherwise: ActivityRelaunchItem & PauseActivityItem
void relaunchActivityLocked(boolean preserveWindow) {<!-- --> ... if (andResume) {<!-- --> EventLogTags.writeWmRelaunchResumeActivity(mUserId, System.identityHashCode(this), task.mTaskId, shortComponentName, Integer.toHexString(configChangeFlags)); } else {<!-- --> EventLogTags.writeWmRelaunchActivity(mUserId, System.identityHashCode(this), task.mTaskId, shortComponentName, Integer.toHexString(configChangeFlags)); } startFreezingScreenLocked(0); try {<!-- --> ... final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults, pendingNewIntents, configChangeFlags, new MergedConfiguration(getProcessGlobalConfiguration(), getMergedOverrideConfiguration()), preserveWindow); final ActivityLifecycleItem lifecycleItem; if (andResume) {<!-- --> lifecycleItem = ResumeActivityItem.obtain(isTransitionForward(), shouldSendCompatFakeFocus()); } else {<!-- --> lifecycleItem = PauseActivityItem.obtain(); } final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), token); transaction.addCallback(callbackItem); transaction.setLifecycleStateRequest(lifecycleItem); mAtmService.getLifecycleManager().scheduleTransaction(transaction); } catch (RemoteException e) {<!-- --> ProtoLog.i(WM_DEBUG_STATES, "Relaunch failed %s", e); } ... }
Then execute the corresponding life cycle according to ResumeActivityItem and PauseActivityItem. Generally, the top Activity executes onResume, and the bottom one executes onPause.
ActivityConfigurationChangeItem
If the corresponding configChanges is not configured in the function manifest file, the current Activity of the app will be triggered to execute the onConfigurationChanged method, which mainly posts an ActivityConfigurationChangeItem to the app process (different from the process-level ConfigurationChangeItem).
Update top Activity’s Configuration
10-10 16:12:05.951 3972 8346 I configuration_changed: 512 10-10 16:12:06.021 3972 8346 I wm_relaunch_resume_activity: [0,237413577,21,com.miui.gallery/.activity.MapActivity,200] // The page of top resume still stays in the onResume state after reconstruction. 10-10 16:12:06.244 20930 20930 I wm_on_top_resumed_lost_called: [237413577,com.miui.gallery.activity.MapActivity,pausing] 10-10 16:12:06.284 20930 20930 I wm_on_paused_called: [0,237413577,com.miui.gallery.activity.MapActivity,performPause,39] 10-10 16:12:06.294 20930 20930 I wm_on_stop_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleRelaunchActivity,2] 10-10 16:12:06.328 20930 20930 I wm_on_destroy_called: [0,237413577,com.miui.gallery.activity.MapActivity,performDestroy,32] 10-10 16:12:06.461 20930 20930 I wm_on_create_called: [0,237413577,com.miui.gallery.activity.MapActivity,performCreate,29] 10-10 16:12:06.599 20930 20930 I wm_on_start_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleStartActivity,135] 10-10 16:12:06.603 20930 20930 I wm_on_resume_called: [0,237413577,com.miui.gallery.activity.MapActivity,RESUME_ACTIVITY,2] 10-10 16:12:06.603 20930 20930 I wm_on_top_resumed_gained_called: [237413577,com.miui.gallery.activity.MapActivity,topWhenResuming]
// ATMS.java /** Applies latest configuration and/or visibility updates if needed. */ boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {<!-- --> boolean kept = true; final Task mainRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask(); // mainRootTask is null during startup. if (mainRootTask != null) {<!-- --> if (changes != 0 & amp; & amp; starting == null) {<!-- --> // If the configuration changed, and the caller is not already // in the process of starting an activity, then find the top // activity to check if its configuration needs to change. starting = mainRootTask.topRunningActivity(); } if (starting != null) {<!-- --> //Update the configuration of the top running page kept = starting.ensureActivityConfiguration(changes, false /* preserveWindow */); // And we need to make sure at this point that all other activities // are made visible with the correct configuration. // Update the configuration of other visible activities mRootWindowContainer.ensureActivitiesVisible(starting, changes, !PRESERVE_WINDOWS); } } return kept; }
Update the Configuration of other visible activities
// EnsureActivitiesVisibleHelper.java private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting, final boolean resumeTopActivity) {<!-- --> ..... final boolean reallyVisible = r.shouldBeVisibleUnchecked(); ... // If visible and not top if (reallyVisible) {<!-- --> ..... // First: if this is not the current activity being started, make // sure it matches the current configuration. if (r != mStarting & amp; & amp; mNotifyClients) {<!-- --> r.ensureActivityConfiguration(0 /* globalChanges */, mPreserveWindows, true /* ignoreVisibility */); }
10-10 16:12:05.951 3972 8346 I configuration_changed: 512 10-10 16:12:06.022 3972 8346 I wm_relaunch_activity: [0,218943334,21,com.miui.gallery/.activity.HomePageActivity,200] // Visible but the final state of the pause page is still onPause after reconstruction 10-10 16:12:06.625 20930 20930 I wm_on_stop_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleRelaunchActivity,6] 10-10 16:12:06.649 20930 20930 I wm_on_destroy_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performDestroy,13] 10-10 16:12:06.701 20930 20930 I wm_on_create_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performCreate,34] 10-10 16:12:06.903 20930 20930 I wm_on_start_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleStartActivity,199] 10-10 16:12:06.910 20930 20930 I wm_on_resume_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,LIFECYCLER_RESUME_ACTIVITY,5] 10-10 16:12:06.926 20930 20930 I wm_on_paused_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performPause,1]
Update the Configuration of other invisible activities
Other activities will trigger relaunch the next time they resume, and are not executed in the same thread and at the same time as the above two. If you want to find the specific reason for relaunch, you need to look forward in time to find the corresponding configuration_changed log. For details, refer to https://blog .csdn.net/xiaoyantan/article/details/126292133
10-11 10:58:57.071 3998 11823 I wm_set_resumed_activity: [0,com.miui.gallery/.activity.HomePageActivity,resumeTopActivity - onActivityStateChanged] 10-11 10:58:57.074 3998 11823 I wm_relaunch_resume_activity: [0,197612339,22,com.miui.gallery/.activity.HomePageActivity,200]