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

Commit 167bbfac authored by Chong Zhang's avatar Chong Zhang
Browse files

Avoid extra relaunch when rotating side-by-side apps

Update configuration with WM first and check if the stacks need to be
resized due to the update. If so, let activity manager resize the stacks
inline, instead of letting WM schedule another pass of resizeStack. This
way the configuration will be updated to the latest before ensureActivity-
ConfigurationLocked, and we don't need another relaunch there.

bug: 27834014

Change-Id: Ib761a96cada0c3247b0480f18370670c593159da
parent c2a091a0
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -180,7 +180,12 @@ interface IWindowManager
    // caller must call setNewConfiguration() sometime later.
    Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
            IBinder freezeThisOneIfNeeded);
    void setNewConfiguration(in Configuration config);
    // Notify window manager of the new configuration. Returns an array of stack ids that's
    // affected by the update, ActivityManager should resize these stacks.
    int[] setNewConfiguration(in Configuration config);

    // Retrieves the new bounds after the configuration update evaluated by window manager.
    Rect getBoundsForNewConfiguration(int stackId);

    void startFreezingScreen(int exitAnim, int enterAnim);
    void stopFreezingScreen();
+8 −0
Original line number Diff line number Diff line
@@ -238,6 +238,14 @@ public class ArrayUtils {
        return total;
    }

    public static int[] convertToIntArray(List<Integer> list) {
        int[] array = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            array[i] = list.get(i);
        }
        return array;
    }

    /**
     * Adds value to given array if not already present, providing set-like
     * behavior.
+19 −4
Original line number Diff line number Diff line
@@ -18044,6 +18044,9 @@ public final class ActivityManagerService extends ActivityManagerNative
            ActivityRecord starting, boolean initLocale, boolean persistent, int userId) {
        int changes = 0;
        if (mWindowManager != null) {
            mWindowManager.deferSurfaceLayout();
        }
        if (values != null) {
            Configuration newConfig = new Configuration(mConfiguration);
            changes = newConfig.updateFrom(values);
@@ -18144,6 +18147,20 @@ public final class ActivityManagerService extends ActivityManagerNative
                            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
            // ensureActivityConfigurationLocked().
            if (mWindowManager != null) {
                final int[] resizedStacks = mWindowManager.setNewConfiguration(mConfiguration);
                if (resizedStacks != null) {
                    for (int stackId : resizedStacks) {
                        final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId);
                        mStackSupervisor.resizeStackLocked(
                                stackId, newBounds, null, null, false, false);
                    }
                }
            }
        }
        boolean kept = true;
@@ -18165,11 +18182,9 @@ public final class ActivityManagerService extends ActivityManagerNative
                        !PRESERVE_WINDOWS);
            }
        }
        if (values != null && mWindowManager != null) {
            mWindowManager.setNewConfiguration(mConfiguration);
        if (mWindowManager != null) {
            mWindowManager.continueSurfaceLayout();
        }
        return kept;
    }
+26 −11
Original line number Diff line number Diff line
@@ -128,6 +128,10 @@ public class TaskStack implements DimLayer.DimLayerUser,
    // in which case a second window animation would cause jitter.
    private boolean mFreezeMovementAnimations = false;

    // Temporary storage for the new bounds that should be used after the configuration change.
    // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
    private final Rect mBoundsAfterRotation = new Rect();

    TaskStack(WindowManagerService service, int stackId) {
        mService = service;
        mStackId = stackId;
@@ -343,28 +347,28 @@ public class TaskStack implements DimLayer.DimLayerUser,
            setBounds(mTmpRect2);
        } else {
            mLastUpdateDisplayInfoRotation = newRotation;
            updateBoundsAfterRotation();
            updateBoundsAfterRotation(true);
        }
    }

    void onConfigurationChanged() {
    boolean onConfigurationChanged() {
        mLastConfigChangedRotation = getDisplayInfo().rotation;
        updateBoundsAfterRotation();
        return updateBoundsAfterRotation(false);
    }

    void updateBoundsAfterRotation() {
    boolean updateBoundsAfterRotation(boolean scheduleResize) {
        if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) {
            // We wait for the rotation values after configuration change and display info. update
            // to be equal before updating the bounds due to rotation change otherwise things might
            // get out of alignment...
            return;
            return false;
        }

        final int newRotation = getDisplayInfo().rotation;

        if (mRotation == newRotation) {
            // Nothing to do here if the rotation didn't change
            return;
            return false;
        }

        mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
@@ -373,11 +377,22 @@ public class TaskStack implements DimLayer.DimLayerUser,
            snapDockedStackAfterRotation(mTmpRect2);
        }

        if (scheduleResize) {
            // Post message to inform activity manager of the bounds change simulating
            // a one-way call. We do this to prevent a deadlock between window manager
            // lock and activity manager lock been held.
        mService.mH.obtainMessage(
                RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget();
            mService.mH.obtainMessage(RESIZE_STACK, mStackId,
                    0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget();
        } else {
            mBoundsAfterRotation.set(mTmpRect2);
        }

        return true;
    }

    void getBoundsForNewConfiguration(Rect outBounds) {
        outBounds.set(mBoundsAfterRotation);
        mBoundsAfterRotation.setEmpty();
    }

    /**
+22 −5
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ import com.android.internal.R;
import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IShortcutService;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -515,6 +516,8 @@ public class WindowManagerService extends IWindowManager.Stub

    private final SparseIntArray mTmpTaskIds = new SparseIntArray();

    private final ArrayList<Integer> mChangedStackList = new ArrayList();

    boolean mForceResizableTasks = false;

    int getDragLayerLocked() {
@@ -3580,7 +3583,7 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    @Override
    public void setNewConfiguration(Configuration config) {
    public int[] setNewConfiguration(Configuration config) {
        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                "setNewConfiguration()")) {
            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -3592,16 +3595,30 @@ public class WindowManagerService extends IWindowManager.Stub
                mWaitingForConfig = false;
                mLastFinishedFreezeSource = "new-config";
            }
            onConfigurationChanged();
            mWindowPlacerLocked.performSurfacePlacement();
            return onConfigurationChanged();
        }
    }

    private void onConfigurationChanged() {
    @Override
    public Rect getBoundsForNewConfiguration(int stackId) {
        synchronized(mWindowMap) {
            final TaskStack stack = mStackIdToStack.get(stackId);
            final Rect outBounds = new Rect();
            stack.getBoundsForNewConfiguration(outBounds);
            return outBounds;
        }
    }

    private int[] onConfigurationChanged() {
        mChangedStackList.clear();
        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
            stack.onConfigurationChanged();
            if (stack.onConfigurationChanged()) {
                mChangedStackList.add(stack.mStackId);
            }
        }
        return mChangedStackList.isEmpty() ?
                null : ArrayUtils.convertToIntArray(mChangedStackList);
    }

    @Override
Loading