Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a507b5d authored by Andrii Kulian's avatar Andrii Kulian
Browse files

Extract global configuration update

- Separated config update in AM into several methods.
- Updated global config update in WM to reconfigure and
  notify all displays.
- Removed redundant list of displays that are waiting for
  configuration update.

Test: Manual testing and existing tests still pass.
Change-Id: I60d3013301267bd668348565dcd0a68e09023a0e
parent f97de8b1
Loading
Loading
Loading
Loading
+143 −114
Original line number Diff line number Diff line
@@ -1125,11 +1125,14 @@ public final class ActivityManagerService extends ActivityManagerNative
     */
    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
     * configurations.
     * Temp object used when global configuration is updated. It is also sent to outer world
     * instead of {@link #mGlobalConfiguration} because we don't trust anyone...
     */
    private int mConfigurationSeq;
    private Configuration mTempGlobalConfig = new Configuration();
    boolean mSuppressResizeConfigChanges;
@@ -18833,6 +18836,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        throw new SecurityException(msg);
    }
    @Override
    public void updateConfiguration(Configuration values) {
        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                "updateConfiguration()");
@@ -18857,10 +18861,12 @@ public final class ActivityManagerService extends ActivityManagerNative
    }
    void updateUserConfigurationLocked() {
        Configuration configuration = new Configuration(mGlobalConfiguration);
        final Configuration configuration = new Configuration(mGlobalConfiguration);
        final int currentUserId = mUserController.getCurrentUserIdLocked();
        Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration,
                mUserController.getCurrentUserIdLocked(), Settings.System.canWrite(mContext));
        updateConfigurationLocked(configuration, null, false);
                currentUserId, Settings.System.canWrite(mContext));
        updateConfigurationLocked(configuration, null /* starting */, false /* initLocale */,
                false /* persistent */, currentUserId, false /* deferResume */);
    }
    boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
@@ -18891,16 +18897,37 @@ public final class ActivityManagerService extends ActivityManagerNative
    private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
            boolean initLocale, boolean persistent, int userId, boolean deferResume) {
        int changes = 0;
        boolean kept = true;
        if (mWindowManager != null) {
            mWindowManager.deferSurfaceLayout();
        }
        try {
            if (values != null) {
            Configuration newConfig = new Configuration(mGlobalConfiguration);
            changes = newConfig.updateFrom(values);
            if (changes != 0) {
                changes = updateGlobalConfiguration(values, initLocale, persistent, userId,
                        deferResume);
            }
            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,
                        "Updating configuration to: " + values);
                "Updating global configuration to: " + values);
        EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
@@ -18909,11 +18936,9 @@ public final class ActivityManagerService extends ActivityManagerNative
            int bestLocaleIndex = 0;
            if (locales.size() > 1) {
                if (mSupportedSystemLocales == null) {
                            mSupportedSystemLocales =
                                    Resources.getSystem().getAssets().getLocales();
                    mSupportedSystemLocales = Resources.getSystem().getAssets().getLocales();
                }
                        bestLocaleIndex = Math.max(0,
                                locales.getFirstMatchIndex(mSupportedSystemLocales));
                bestLocaleIndex = Math.max(0, locales.getFirstMatchIndex(mSupportedSystemLocales));
            }
            SystemProperties.set("persist.sys.locale",
                    locales.get(bestLocaleIndex).toLanguageTag());
@@ -18922,44 +18947,40 @@ public final class ActivityManagerService extends ActivityManagerNative
                    locales.get(bestLocaleIndex)));
        }
                mConfigurationSeq++;
                if (mConfigurationSeq <= 0) {
                    mConfigurationSeq = 1;
                }
                newConfig.seq = mConfigurationSeq;
                mGlobalConfiguration = newConfig;
                Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
                mUsageStatsService.reportConfigurationChange(newConfig,
                        mUserController.getCurrentUserIdLocked());
                //mUsageStatsService.noteStartConfig(newConfig);
        mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
        mTempGlobalConfig.seq = mConfigurationSeq;
                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
                // showing dialogs?
                mShowDialogs = shouldShowDialogs(newConfig, mInVrMode);
        // TODO: If our config changes, should we auto dismiss any currently showing dialogs?
        mShowDialogs = shouldShowDialogs(mTempGlobalConfig, mInVrMode);
        AttributeCache ac = AttributeCache.instance();
        if (ac != null) {
                    ac.updateConfiguration(configCopy);
            ac.updateConfiguration(mTempGlobalConfig);
        }
                // Make sure all resources in our process are updated
                // right now, so that anyone who is going to retrieve
                // resource values after we return will be sure to get
                // the new ones.  This is especially important during
                // boot, where the first config change needs to guarantee
                // all resources have that config before following boot
                // code is executed.
                mSystemThread.applyConfigurationToResources(configCopy);
        // Make sure all resources in our process are updated right now, so that anyone who is going
        // to retrieve resource values after we return will be sure to get the new ones. This is
        // especially important during boot, where the first config change needs to guarantee all
        // resources have that config before following boot code is executed.
        mSystemThread.applyConfigurationToResources(mTempGlobalConfig);
        // 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)) {
            Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
                    msg.obj = new Configuration(configCopy);
            msg.obj = configCopy;
            msg.arg1 = userId;
            mHandler.sendMessage(msg);
        }
        // TODO(multi-display): Clear also on secondary display density change?
        final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
        if (isDensityChange) {
            // Reset the unsupported display size dialog.
@@ -18974,47 +18995,49 @@ public final class ActivityManagerService extends ActivityManagerNative
            try {
                if (app.thread != null) {
                    if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc "
                                    + app.processName + " new config " + mGlobalConfiguration);
                            + app.processName + " new config " + configCopy);
                    app.thread.scheduleConfigurationChanged(configCopy);
                }
            } catch (Exception e) {
            }
        }
        Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_REPLACE_PENDING
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING
                | Intent.FLAG_RECEIVER_FOREGROUND);
                broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
                        null, AppOpsManager.OP_NONE, null, false, false,
                        MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
        broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
                AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
                UserHandle.USER_ALL);
        if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
            intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            if (!mProcessesReady) {
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            }
                    broadcastIntentLocked(null, null, intent,
                            null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                            null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                }
            broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
                    AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
                    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
            // relaunches if necessary. This way we don't need to relaunch again below in
        // 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 relaunches if
        // necessary. This way we don't need to relaunch again afterwards in
        // ensureActivityConfigurationLocked().
        if (mWindowManager != null) {
            final int[] resizedStacks =
                        mWindowManager.setNewConfiguration(mGlobalConfiguration);
                    mWindowManager.setNewConfiguration(mTempGlobalConfig);
            if (resizedStacks != null) {
                for (int stackId : resizedStacks) {
                        final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId);
                        mStackSupervisor.resizeStackLocked(
                                stackId, newBounds, null, null, false, false, deferResume);
                    resizeStackWithBoundsFromWindowManager(stackId, deferResume);
                }
            }
        }
        return changes;
    }
    /** Applies latest configuration and/or visibility updates if needed. */
    private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
        boolean kept = true;
        final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
        // mainStack is null during startup.
@@ -19034,12 +19057,18 @@ public final class ActivityManagerService extends ActivityManagerNative
                        !PRESERVE_WINDOWS);
            }
        }
        if (mWindowManager != null) {
            mWindowManager.continueSurfaceLayout();
        }
        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,
     * crash, etc dialogs.  The idea is that if there is no affordance to
+3 −0
Original line number Diff line number Diff line
@@ -1932,6 +1932,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    public void setInitialDisplaySize(Display display, int width, int height, int density) {
        // This method might be called before the policy has been fully initialized
        // 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) {
            return;
        }
@@ -2027,6 +2028,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    @Override
    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) {
            mOverscanLeft = left;
            mOverscanTop = top;
@@ -2428,6 +2430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    @Override
    public void onConfigurationChanged() {
        // TODO(multi-display): Define policy for secondary displays.
        final Resources res = mContext.getResources();

        mStatusBarHeight =
+19 −0
Original line number Diff line number Diff line
@@ -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.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;

import android.annotation.NonNull;
import android.app.ActivityManager.StackId;
import android.graphics.Rect;
import android.graphics.Region;
@@ -60,6 +61,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class DisplayContentList extends ArrayList<DisplayContent> {
}
@@ -212,6 +214,23 @@ class DisplayContent {
        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() {
        for (int i = mStacks.size() - 1; i >= 0; --i) {
            final TaskStack stack = mStacks.get(i);
+9 −32
Original line number Diff line number Diff line
@@ -886,13 +886,6 @@ public class WindowManagerService extends IWindowManager.Stub
    // since they won't be notified through the app window animator.
    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
    // instances will be replaced with an instance that writes a binary representation of all
    // commands to mSurfaceTraceFd.
@@ -3168,30 +3161,19 @@ public class WindowManagerService extends IWindowManager.Stub
        }

    }

    private int[] 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();
        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
            if (stack.onConfigurationChanged()) {
                mChangedStackList.add(stack.mStackId);
            }

        final int numDisplays = mDisplayContents.size();
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
            displayContent.onConfigurationChanged(mChangedStackList);
        }
        return mChangedStackList.isEmpty() ?
                null : ArrayUtils.convertToIntArray(mChangedStackList);

        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
    }

    @Override
@@ -8130,9 +8112,7 @@ public class WindowManagerService extends IWindowManager.Stub
        reconfigureDisplayLocked(displayContent);
    }

    // displayContent must not be null
    private void reconfigureDisplayLocked(DisplayContent displayContent) {
        // TODO: Multidisplay: for now only use with default display.
    void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) {
        if (!mDisplayReady) {
            return;
        }
@@ -8148,9 +8128,6 @@ public class WindowManagerService extends IWindowManager.Stub
            mWaitingForConfig = true;
            startFreezingDisplayLocked(false, 0, 0);
            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
            if (!mReconfigureOnConfigurationChanged.contains(displayContent)) {
                mReconfigureOnConfigurationChanged.add(displayContent);
            }
        }

        mWindowPlacerLocked.performSurfacePlacement();