Loading services/core/java/com/android/server/am/ActivityManagerService.java +143 −114 Original line number Original line Diff line number Diff line Loading @@ -1125,11 +1125,14 @@ public final class ActivityManagerService extends ActivityManagerNative */ */ Configuration mGlobalConfiguration = new Configuration(); Configuration mGlobalConfiguration = new Configuration(); /** Current sequencing integer of the configuration, for skipping old configurations. */ private int mConfigurationSeq; /** /** * Current sequencing integer of the configuration, for skipping old * Temp object used when global configuration is updated. It is also sent to outer world * configurations. * instead of {@link #mGlobalConfiguration} because we don't trust anyone... */ */ private int mConfigurationSeq; private Configuration mTempGlobalConfig = new Configuration(); boolean mSuppressResizeConfigChanges; boolean mSuppressResizeConfigChanges; Loading Loading @@ -18836,6 +18839,7 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); throw new SecurityException(msg); } } @Override public void updateConfiguration(Configuration values) { public void updateConfiguration(Configuration values) { enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()"); "updateConfiguration()"); Loading @@ -18860,10 +18864,12 @@ public final class ActivityManagerService extends ActivityManagerNative } } void updateUserConfigurationLocked() { void updateUserConfigurationLocked() { Configuration configuration = new Configuration(mGlobalConfiguration); final Configuration configuration = new Configuration(mGlobalConfiguration); final int currentUserId = mUserController.getCurrentUserIdLocked(); Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration, Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration, mUserController.getCurrentUserIdLocked(), Settings.System.canWrite(mContext)); currentUserId, Settings.System.canWrite(mContext)); updateConfigurationLocked(configuration, null, false); updateConfigurationLocked(configuration, null /* starting */, false /* initLocale */, false /* persistent */, currentUserId, false /* deferResume */); } } boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, Loading Loading @@ -18894,16 +18900,37 @@ public final class ActivityManagerService extends ActivityManagerNative private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, boolean initLocale, boolean persistent, int userId, boolean deferResume) { boolean initLocale, boolean persistent, int userId, boolean deferResume) { int changes = 0; int changes = 0; boolean kept = true; if (mWindowManager != null) { if (mWindowManager != null) { mWindowManager.deferSurfaceLayout(); mWindowManager.deferSurfaceLayout(); } } try { if (values != null) { if (values != null) { Configuration newConfig = new Configuration(mGlobalConfiguration); changes = updateGlobalConfiguration(values, initLocale, persistent, userId, changes = newConfig.updateFrom(values); deferResume); if (changes != 0) { } kept = ensureConfigAndVisibilityAfterUpdate(starting, changes); } finally { if (mWindowManager != null) { mWindowManager.continueSurfaceLayout(); } } return kept; } /** Update default (global) configuration and notify listeners about changes. */ private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale, boolean persistent, int userId, boolean deferResume) { mTempGlobalConfig.setTo(mGlobalConfiguration); final int changes = mTempGlobalConfig.updateFrom(values); if (changes == 0) { return 0; } if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION, if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION, "Updating configuration to: " + values); "Updating global configuration to: " + values); EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes); EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes); Loading @@ -18912,11 +18939,9 @@ public final class ActivityManagerService extends ActivityManagerNative int bestLocaleIndex = 0; int bestLocaleIndex = 0; if (locales.size() > 1) { if (locales.size() > 1) { if (mSupportedSystemLocales == null) { if (mSupportedSystemLocales == null) { mSupportedSystemLocales = mSupportedSystemLocales = Resources.getSystem().getAssets().getLocales(); Resources.getSystem().getAssets().getLocales(); } } bestLocaleIndex = Math.max(0, bestLocaleIndex = Math.max(0, locales.getFirstMatchIndex(mSupportedSystemLocales)); locales.getFirstMatchIndex(mSupportedSystemLocales)); } } SystemProperties.set("persist.sys.locale", SystemProperties.set("persist.sys.locale", locales.get(bestLocaleIndex).toLanguageTag()); locales.get(bestLocaleIndex).toLanguageTag()); Loading @@ -18925,44 +18950,40 @@ public final class ActivityManagerService extends ActivityManagerNative locales.get(bestLocaleIndex))); locales.get(bestLocaleIndex))); } } mConfigurationSeq++; mConfigurationSeq = Math.max(++mConfigurationSeq, 1); if (mConfigurationSeq <= 0) { mTempGlobalConfig.seq = mConfigurationSeq; mConfigurationSeq = 1; } newConfig.seq = mConfigurationSeq; mGlobalConfiguration = newConfig; Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig); mUsageStatsService.reportConfigurationChange(newConfig, mUserController.getCurrentUserIdLocked()); //mUsageStatsService.noteStartConfig(newConfig); final Configuration configCopy = new Configuration(mGlobalConfiguration); mGlobalConfiguration.setTo(mTempGlobalConfig); Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempGlobalConfig); // TODO(multi-display): Update UsageEvents#Event to include displayId. mUsageStatsService.reportConfigurationChange(mTempGlobalConfig, mUserController.getCurrentUserIdLocked()); // TODO: If our config changes, should we auto dismiss any currently // TODO: If our config changes, should we auto dismiss any currently showing dialogs? // showing dialogs? mShowDialogs = shouldShowDialogs(mTempGlobalConfig, mInVrMode); mShowDialogs = shouldShowDialogs(newConfig, mInVrMode); AttributeCache ac = AttributeCache.instance(); AttributeCache ac = AttributeCache.instance(); if (ac != null) { if (ac != null) { ac.updateConfiguration(configCopy); ac.updateConfiguration(mTempGlobalConfig); } } // Make sure all resources in our process are updated // Make sure all resources in our process are updated right now, so that anyone who is going // right now, so that anyone who is going to retrieve // to retrieve resource values after we return will be sure to get the new ones. This is // resource values after we return will be sure to get // especially important during boot, where the first config change needs to guarantee all // the new ones. This is especially important during // resources have that config before following boot code is executed. // boot, where the first config change needs to guarantee mSystemThread.applyConfigurationToResources(mTempGlobalConfig); // all resources have that config before following boot // code is executed. mSystemThread.applyConfigurationToResources(configCopy); // We need another copy of global config because we're scheduling some calls instead of // running them in place. We need to be sure that object we send will be handled unchanged. final Configuration configCopy = new Configuration(mGlobalConfiguration); if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) { if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) { Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG); Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG); msg.obj = new Configuration(configCopy); msg.obj = configCopy; msg.arg1 = userId; msg.arg1 = userId; mHandler.sendMessage(msg); mHandler.sendMessage(msg); } } // TODO(multi-display): Clear also on secondary display density change? final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; if (isDensityChange) { if (isDensityChange) { // Reset the unsupported display size dialog. // Reset the unsupported display size dialog. Loading @@ -18977,47 +18998,49 @@ public final class ActivityManagerService extends ActivityManagerNative try { try { if (app.thread != null) { if (app.thread != null) { if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc " if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc " + app.processName + " new config " + mGlobalConfiguration); + app.processName + " new config " + configCopy); app.thread.scheduleConfigurationChanged(configCopy); app.thread.scheduleConfigurationChanged(configCopy); } } } catch (Exception e) { } catch (Exception e) { } } } } Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED); Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_FOREGROUND); | Intent.FLAG_RECEIVER_FOREGROUND); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, null, AppOpsManager.OP_NONE, null, false, false, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); UserHandle.USER_ALL); if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) { if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) { intent = new Intent(Intent.ACTION_LOCALE_CHANGED); intent = new Intent(Intent.ACTION_LOCALE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); if (!mProcessesReady) { if (!mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } } broadcastIntentLocked(null, null, intent, broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, null, null, 0, null, null, null, AppOpsManager.OP_NONE, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); UserHandle.USER_ALL); } } } // Update the configuration with WM first and check if any of the stacks need to be // resized due to the configuration change. If so, resize the stacks now and do any // Update the configuration with WM first and check if any of the stacks need to be resized // relaunches if necessary. This way we don't need to relaunch again below in // due to the configuration change. If so, resize the stacks now and do any relaunches if // necessary. This way we don't need to relaunch again afterwards in // ensureActivityConfigurationLocked(). // ensureActivityConfigurationLocked(). if (mWindowManager != null) { if (mWindowManager != null) { final int[] resizedStacks = final int[] resizedStacks = mWindowManager.setNewConfiguration(mGlobalConfiguration); mWindowManager.setNewConfiguration(mTempGlobalConfig); if (resizedStacks != null) { if (resizedStacks != null) { for (int stackId : resizedStacks) { for (int stackId : resizedStacks) { final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId); resizeStackWithBoundsFromWindowManager(stackId, deferResume); mStackSupervisor.resizeStackLocked( stackId, newBounds, null, null, false, false, deferResume); } } } } } } return changes; } } /** Applies latest configuration and/or visibility updates if needed. */ private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) { boolean kept = true; boolean kept = true; final ActivityStack mainStack = mStackSupervisor.getFocusedStack(); final ActivityStack mainStack = mStackSupervisor.getFocusedStack(); // mainStack is null during startup. // mainStack is null during startup. Loading @@ -19037,12 +19060,18 @@ public final class ActivityManagerService extends ActivityManagerNative !PRESERVE_WINDOWS); !PRESERVE_WINDOWS); } } } } if (mWindowManager != null) { mWindowManager.continueSurfaceLayout(); } return kept; return kept; } } /** Helper method that requests bounds from WM and applies them to stack. */ private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) { final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId); mStackSupervisor.resizeStackLocked( stackId, newBounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */, false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume); } /** /** * Decide based on the configuration whether we should show the ANR, * Decide based on the configuration whether we should show the ANR, * crash, etc dialogs. The idea is that if there is no affordance to * crash, etc dialogs. The idea is that if there is no affordance to services/core/java/com/android/server/policy/PhoneWindowManager.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1932,6 +1932,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void setInitialDisplaySize(Display display, int width, int height, int density) { public void setInitialDisplaySize(Display display, int width, int height, int density) { // This method might be called before the policy has been fully initialized // This method might be called before the policy has been fully initialized // or for other displays we don't care about. // or for other displays we don't care about. // TODO(multi-display): Define policy for secondary displays. if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { return; return; } } Loading Loading @@ -2027,6 +2028,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override @Override public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { // TODO(multi-display): Define policy for secondary displays. if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { mOverscanLeft = left; mOverscanLeft = left; mOverscanTop = top; mOverscanTop = top; Loading Loading @@ -2428,6 +2430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override @Override public void onConfigurationChanged() { public void onConfigurationChanged() { // TODO(multi-display): Define policy for secondary displays. final Resources res = mContext.getResources(); final Resources res = mContext.getResources(); mStatusBarHeight = mStatusBarHeight = Loading services/core/java/com/android/server/wm/DisplayContent.java +19 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; import android.annotation.NonNull; import android.app.ActivityManager.StackId; import android.app.ActivityManager.StackId; import android.graphics.Rect; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Region; Loading @@ -60,6 +61,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.List; class DisplayContentList extends ArrayList<DisplayContent> { class DisplayContentList extends ArrayList<DisplayContent> { } } Loading Loading @@ -212,6 +214,23 @@ class DisplayContent { return null; return null; } } /** Callback used to notify about configuration changes. */ void onConfigurationChanged(@NonNull List<Integer> changedStackList) { // The display size information is heavily dependent on the resources in the current // configuration, so we need to reconfigure it every time the configuration changes. // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... mService.reconfigureDisplayLocked(this); getDockedDividerController().onConfigurationChanged(); for (int i = 0; i < mStacks.size(); i++) { final TaskStack stack = mStacks.get(i); if (stack.onConfigurationChanged()) { changedStackList.add(stack.mStackId); } } } void checkAppWindowsReadyToShow() { void checkAppWindowsReadyToShow() { for (int i = mStacks.size() - 1; i >= 0; --i) { for (int i = mStacks.size() - 1; i >= 0; --i) { final TaskStack stack = mStacks.get(i); final TaskStack stack = mStacks.get(i); Loading services/core/java/com/android/server/wm/WindowManagerService.java +9 −32 Original line number Original line Diff line number Diff line Loading @@ -886,13 +886,6 @@ public class WindowManagerService extends IWindowManager.Stub // since they won't be notified through the app window animator. // since they won't be notified through the app window animator. final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); // List of displays to reconfigure after configuration changes. // Some of the information reported for a display is dependent on resources to do the right // calculations. For example, {@link DisplayInfo#smallestNominalAppWidth} and company are // dependent on the height and width of the status and nav bar which change depending on the // current configuration. private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList(); // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl // instances will be replaced with an instance that writes a binary representation of all // instances will be replaced with an instance that writes a binary representation of all // commands to mSurfaceTraceFd. // commands to mSurfaceTraceFd. Loading Loading @@ -3168,30 +3161,19 @@ public class WindowManagerService extends IWindowManager.Stub } } } } private int[] onConfigurationChanged() { private int[] onConfigurationChanged() { mPolicy.onConfigurationChanged(); mPolicy.onConfigurationChanged(); final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); if (!mReconfigureOnConfigurationChanged.contains(defaultDisplayContent)) { // The default display size information is heavily dependent on the resources in the // current configuration, so we need to reconfigure it everytime the configuration // changes. See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... mReconfigureOnConfigurationChanged.add(defaultDisplayContent); } for (int i = mReconfigureOnConfigurationChanged.size() - 1; i >= 0; i--) { reconfigureDisplayLocked(mReconfigureOnConfigurationChanged.remove(i)); } defaultDisplayContent.getDockedDividerController().onConfigurationChanged(); mChangedStackList.clear(); mChangedStackList.clear(); for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) { final TaskStack stack = mStackIdToStack.valueAt(stackNdx); final int numDisplays = mDisplayContents.size(); if (stack.onConfigurationChanged()) { for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { mChangedStackList.add(stack.mStackId); final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); } displayContent.onConfigurationChanged(mChangedStackList); } } return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList); return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList); } } @Override @Override Loading Loading @@ -8130,9 +8112,7 @@ public class WindowManagerService extends IWindowManager.Stub reconfigureDisplayLocked(displayContent); reconfigureDisplayLocked(displayContent); } } // displayContent must not be null void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) { private void reconfigureDisplayLocked(DisplayContent displayContent) { // TODO: Multidisplay: for now only use with default display. if (!mDisplayReady) { if (!mDisplayReady) { return; return; } } Loading @@ -8148,9 +8128,6 @@ public class WindowManagerService extends IWindowManager.Stub mWaitingForConfig = true; mWaitingForConfig = true; startFreezingDisplayLocked(false, 0, 0); startFreezingDisplayLocked(false, 0, 0); mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); if (!mReconfigureOnConfigurationChanged.contains(displayContent)) { mReconfigureOnConfigurationChanged.add(displayContent); } } } mWindowPlacerLocked.performSurfacePlacement(); mWindowPlacerLocked.performSurfacePlacement(); Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +143 −114 Original line number Original line Diff line number Diff line Loading @@ -1125,11 +1125,14 @@ public final class ActivityManagerService extends ActivityManagerNative */ */ Configuration mGlobalConfiguration = new Configuration(); Configuration mGlobalConfiguration = new Configuration(); /** Current sequencing integer of the configuration, for skipping old configurations. */ private int mConfigurationSeq; /** /** * Current sequencing integer of the configuration, for skipping old * Temp object used when global configuration is updated. It is also sent to outer world * configurations. * instead of {@link #mGlobalConfiguration} because we don't trust anyone... */ */ private int mConfigurationSeq; private Configuration mTempGlobalConfig = new Configuration(); boolean mSuppressResizeConfigChanges; boolean mSuppressResizeConfigChanges; Loading Loading @@ -18836,6 +18839,7 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); throw new SecurityException(msg); } } @Override public void updateConfiguration(Configuration values) { public void updateConfiguration(Configuration values) { enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()"); "updateConfiguration()"); Loading @@ -18860,10 +18864,12 @@ public final class ActivityManagerService extends ActivityManagerNative } } void updateUserConfigurationLocked() { void updateUserConfigurationLocked() { Configuration configuration = new Configuration(mGlobalConfiguration); final Configuration configuration = new Configuration(mGlobalConfiguration); final int currentUserId = mUserController.getCurrentUserIdLocked(); Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration, Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration, mUserController.getCurrentUserIdLocked(), Settings.System.canWrite(mContext)); currentUserId, Settings.System.canWrite(mContext)); updateConfigurationLocked(configuration, null, false); updateConfigurationLocked(configuration, null /* starting */, false /* initLocale */, false /* persistent */, currentUserId, false /* deferResume */); } } boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, Loading Loading @@ -18894,16 +18900,37 @@ public final class ActivityManagerService extends ActivityManagerNative private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, boolean initLocale, boolean persistent, int userId, boolean deferResume) { boolean initLocale, boolean persistent, int userId, boolean deferResume) { int changes = 0; int changes = 0; boolean kept = true; if (mWindowManager != null) { if (mWindowManager != null) { mWindowManager.deferSurfaceLayout(); mWindowManager.deferSurfaceLayout(); } } try { if (values != null) { if (values != null) { Configuration newConfig = new Configuration(mGlobalConfiguration); changes = updateGlobalConfiguration(values, initLocale, persistent, userId, changes = newConfig.updateFrom(values); deferResume); if (changes != 0) { } kept = ensureConfigAndVisibilityAfterUpdate(starting, changes); } finally { if (mWindowManager != null) { mWindowManager.continueSurfaceLayout(); } } return kept; } /** Update default (global) configuration and notify listeners about changes. */ private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale, boolean persistent, int userId, boolean deferResume) { mTempGlobalConfig.setTo(mGlobalConfiguration); final int changes = mTempGlobalConfig.updateFrom(values); if (changes == 0) { return 0; } if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION, if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION, "Updating configuration to: " + values); "Updating global configuration to: " + values); EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes); EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes); Loading @@ -18912,11 +18939,9 @@ public final class ActivityManagerService extends ActivityManagerNative int bestLocaleIndex = 0; int bestLocaleIndex = 0; if (locales.size() > 1) { if (locales.size() > 1) { if (mSupportedSystemLocales == null) { if (mSupportedSystemLocales == null) { mSupportedSystemLocales = mSupportedSystemLocales = Resources.getSystem().getAssets().getLocales(); Resources.getSystem().getAssets().getLocales(); } } bestLocaleIndex = Math.max(0, bestLocaleIndex = Math.max(0, locales.getFirstMatchIndex(mSupportedSystemLocales)); locales.getFirstMatchIndex(mSupportedSystemLocales)); } } SystemProperties.set("persist.sys.locale", SystemProperties.set("persist.sys.locale", locales.get(bestLocaleIndex).toLanguageTag()); locales.get(bestLocaleIndex).toLanguageTag()); Loading @@ -18925,44 +18950,40 @@ public final class ActivityManagerService extends ActivityManagerNative locales.get(bestLocaleIndex))); locales.get(bestLocaleIndex))); } } mConfigurationSeq++; mConfigurationSeq = Math.max(++mConfigurationSeq, 1); if (mConfigurationSeq <= 0) { mTempGlobalConfig.seq = mConfigurationSeq; mConfigurationSeq = 1; } newConfig.seq = mConfigurationSeq; mGlobalConfiguration = newConfig; Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig); mUsageStatsService.reportConfigurationChange(newConfig, mUserController.getCurrentUserIdLocked()); //mUsageStatsService.noteStartConfig(newConfig); final Configuration configCopy = new Configuration(mGlobalConfiguration); mGlobalConfiguration.setTo(mTempGlobalConfig); Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempGlobalConfig); // TODO(multi-display): Update UsageEvents#Event to include displayId. mUsageStatsService.reportConfigurationChange(mTempGlobalConfig, mUserController.getCurrentUserIdLocked()); // TODO: If our config changes, should we auto dismiss any currently // TODO: If our config changes, should we auto dismiss any currently showing dialogs? // showing dialogs? mShowDialogs = shouldShowDialogs(mTempGlobalConfig, mInVrMode); mShowDialogs = shouldShowDialogs(newConfig, mInVrMode); AttributeCache ac = AttributeCache.instance(); AttributeCache ac = AttributeCache.instance(); if (ac != null) { if (ac != null) { ac.updateConfiguration(configCopy); ac.updateConfiguration(mTempGlobalConfig); } } // Make sure all resources in our process are updated // Make sure all resources in our process are updated right now, so that anyone who is going // right now, so that anyone who is going to retrieve // to retrieve resource values after we return will be sure to get the new ones. This is // resource values after we return will be sure to get // especially important during boot, where the first config change needs to guarantee all // the new ones. This is especially important during // resources have that config before following boot code is executed. // boot, where the first config change needs to guarantee mSystemThread.applyConfigurationToResources(mTempGlobalConfig); // all resources have that config before following boot // code is executed. mSystemThread.applyConfigurationToResources(configCopy); // We need another copy of global config because we're scheduling some calls instead of // running them in place. We need to be sure that object we send will be handled unchanged. final Configuration configCopy = new Configuration(mGlobalConfiguration); if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) { if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) { Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG); Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG); msg.obj = new Configuration(configCopy); msg.obj = configCopy; msg.arg1 = userId; msg.arg1 = userId; mHandler.sendMessage(msg); mHandler.sendMessage(msg); } } // TODO(multi-display): Clear also on secondary display density change? final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; if (isDensityChange) { if (isDensityChange) { // Reset the unsupported display size dialog. // Reset the unsupported display size dialog. Loading @@ -18977,47 +18998,49 @@ public final class ActivityManagerService extends ActivityManagerNative try { try { if (app.thread != null) { if (app.thread != null) { if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc " if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc " + app.processName + " new config " + mGlobalConfiguration); + app.processName + " new config " + configCopy); app.thread.scheduleConfigurationChanged(configCopy); app.thread.scheduleConfigurationChanged(configCopy); } } } catch (Exception e) { } catch (Exception e) { } } } } Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED); Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_FOREGROUND); | Intent.FLAG_RECEIVER_FOREGROUND); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, null, AppOpsManager.OP_NONE, null, false, false, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); UserHandle.USER_ALL); if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) { if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) { intent = new Intent(Intent.ACTION_LOCALE_CHANGED); intent = new Intent(Intent.ACTION_LOCALE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); if (!mProcessesReady) { if (!mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } } broadcastIntentLocked(null, null, intent, broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, null, null, 0, null, null, null, AppOpsManager.OP_NONE, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); UserHandle.USER_ALL); } } } // Update the configuration with WM first and check if any of the stacks need to be // resized due to the configuration change. If so, resize the stacks now and do any // Update the configuration with WM first and check if any of the stacks need to be resized // relaunches if necessary. This way we don't need to relaunch again below in // due to the configuration change. If so, resize the stacks now and do any relaunches if // necessary. This way we don't need to relaunch again afterwards in // ensureActivityConfigurationLocked(). // ensureActivityConfigurationLocked(). if (mWindowManager != null) { if (mWindowManager != null) { final int[] resizedStacks = final int[] resizedStacks = mWindowManager.setNewConfiguration(mGlobalConfiguration); mWindowManager.setNewConfiguration(mTempGlobalConfig); if (resizedStacks != null) { if (resizedStacks != null) { for (int stackId : resizedStacks) { for (int stackId : resizedStacks) { final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId); resizeStackWithBoundsFromWindowManager(stackId, deferResume); mStackSupervisor.resizeStackLocked( stackId, newBounds, null, null, false, false, deferResume); } } } } } } return changes; } } /** Applies latest configuration and/or visibility updates if needed. */ private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) { boolean kept = true; boolean kept = true; final ActivityStack mainStack = mStackSupervisor.getFocusedStack(); final ActivityStack mainStack = mStackSupervisor.getFocusedStack(); // mainStack is null during startup. // mainStack is null during startup. Loading @@ -19037,12 +19060,18 @@ public final class ActivityManagerService extends ActivityManagerNative !PRESERVE_WINDOWS); !PRESERVE_WINDOWS); } } } } if (mWindowManager != null) { mWindowManager.continueSurfaceLayout(); } return kept; return kept; } } /** Helper method that requests bounds from WM and applies them to stack. */ private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) { final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId); mStackSupervisor.resizeStackLocked( stackId, newBounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */, false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume); } /** /** * Decide based on the configuration whether we should show the ANR, * Decide based on the configuration whether we should show the ANR, * crash, etc dialogs. The idea is that if there is no affordance to * crash, etc dialogs. The idea is that if there is no affordance to
services/core/java/com/android/server/policy/PhoneWindowManager.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1932,6 +1932,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void setInitialDisplaySize(Display display, int width, int height, int density) { public void setInitialDisplaySize(Display display, int width, int height, int density) { // This method might be called before the policy has been fully initialized // This method might be called before the policy has been fully initialized // or for other displays we don't care about. // or for other displays we don't care about. // TODO(multi-display): Define policy for secondary displays. if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { return; return; } } Loading Loading @@ -2027,6 +2028,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override @Override public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { // TODO(multi-display): Define policy for secondary displays. if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { mOverscanLeft = left; mOverscanLeft = left; mOverscanTop = top; mOverscanTop = top; Loading Loading @@ -2428,6 +2430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override @Override public void onConfigurationChanged() { public void onConfigurationChanged() { // TODO(multi-display): Define policy for secondary displays. final Resources res = mContext.getResources(); final Resources res = mContext.getResources(); mStatusBarHeight = mStatusBarHeight = Loading
services/core/java/com/android/server/wm/DisplayContent.java +19 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; import android.annotation.NonNull; import android.app.ActivityManager.StackId; import android.app.ActivityManager.StackId; import android.graphics.Rect; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Region; Loading @@ -60,6 +61,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.List; class DisplayContentList extends ArrayList<DisplayContent> { class DisplayContentList extends ArrayList<DisplayContent> { } } Loading Loading @@ -212,6 +214,23 @@ class DisplayContent { return null; return null; } } /** Callback used to notify about configuration changes. */ void onConfigurationChanged(@NonNull List<Integer> changedStackList) { // The display size information is heavily dependent on the resources in the current // configuration, so we need to reconfigure it every time the configuration changes. // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... mService.reconfigureDisplayLocked(this); getDockedDividerController().onConfigurationChanged(); for (int i = 0; i < mStacks.size(); i++) { final TaskStack stack = mStacks.get(i); if (stack.onConfigurationChanged()) { changedStackList.add(stack.mStackId); } } } void checkAppWindowsReadyToShow() { void checkAppWindowsReadyToShow() { for (int i = mStacks.size() - 1; i >= 0; --i) { for (int i = mStacks.size() - 1; i >= 0; --i) { final TaskStack stack = mStacks.get(i); final TaskStack stack = mStacks.get(i); Loading
services/core/java/com/android/server/wm/WindowManagerService.java +9 −32 Original line number Original line Diff line number Diff line Loading @@ -886,13 +886,6 @@ public class WindowManagerService extends IWindowManager.Stub // since they won't be notified through the app window animator. // since they won't be notified through the app window animator. final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); // List of displays to reconfigure after configuration changes. // Some of the information reported for a display is dependent on resources to do the right // calculations. For example, {@link DisplayInfo#smallestNominalAppWidth} and company are // dependent on the height and width of the status and nav bar which change depending on the // current configuration. private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList(); // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl // instances will be replaced with an instance that writes a binary representation of all // instances will be replaced with an instance that writes a binary representation of all // commands to mSurfaceTraceFd. // commands to mSurfaceTraceFd. Loading Loading @@ -3168,30 +3161,19 @@ public class WindowManagerService extends IWindowManager.Stub } } } } private int[] onConfigurationChanged() { private int[] onConfigurationChanged() { mPolicy.onConfigurationChanged(); mPolicy.onConfigurationChanged(); final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); if (!mReconfigureOnConfigurationChanged.contains(defaultDisplayContent)) { // The default display size information is heavily dependent on the resources in the // current configuration, so we need to reconfigure it everytime the configuration // changes. See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... mReconfigureOnConfigurationChanged.add(defaultDisplayContent); } for (int i = mReconfigureOnConfigurationChanged.size() - 1; i >= 0; i--) { reconfigureDisplayLocked(mReconfigureOnConfigurationChanged.remove(i)); } defaultDisplayContent.getDockedDividerController().onConfigurationChanged(); mChangedStackList.clear(); mChangedStackList.clear(); for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) { final TaskStack stack = mStackIdToStack.valueAt(stackNdx); final int numDisplays = mDisplayContents.size(); if (stack.onConfigurationChanged()) { for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { mChangedStackList.add(stack.mStackId); final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); } displayContent.onConfigurationChanged(mChangedStackList); } } return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList); return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList); } } @Override @Override Loading Loading @@ -8130,9 +8112,7 @@ public class WindowManagerService extends IWindowManager.Stub reconfigureDisplayLocked(displayContent); reconfigureDisplayLocked(displayContent); } } // displayContent must not be null void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) { private void reconfigureDisplayLocked(DisplayContent displayContent) { // TODO: Multidisplay: for now only use with default display. if (!mDisplayReady) { if (!mDisplayReady) { return; return; } } Loading @@ -8148,9 +8128,6 @@ public class WindowManagerService extends IWindowManager.Stub mWaitingForConfig = true; mWaitingForConfig = true; startFreezingDisplayLocked(false, 0, 0); startFreezingDisplayLocked(false, 0, 0); mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); if (!mReconfigureOnConfigurationChanged.contains(displayContent)) { mReconfigureOnConfigurationChanged.add(displayContent); } } } mWindowPlacerLocked.performSurfacePlacement(); mWindowPlacerLocked.performSurfacePlacement(); Loading