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

Commit ba422045 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Reducing number of configuration changes during PiP transition."

parents 04c959a3 bdc646f5
Loading
Loading
Loading
Loading
+15 −16
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -47,7 +46,6 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static android.os.Build.VERSION_CODES.O;
@@ -85,7 +83,6 @@ import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
@@ -290,8 +287,8 @@ final class ActivityRecord implements AppWindowContainerListener {
    /**
     * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
     */
    private final Configuration mTmpGlobalConfig = new Configuration();
    private final Configuration mTmpTaskConfig = new Configuration();
    private final Configuration mTmpConfig1 = new Configuration();
    private final Configuration mTmpConfig2 = new Configuration();

    private static String startingWindowStateToString(int state) {
        switch (state) {
@@ -1975,13 +1972,13 @@ final class ActivityRecord implements AppWindowContainerListener {
        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                "Ensuring correct configuration: " + this);

        // Short circuit: if the two configurations are equal (the common case), then there is
        // nothing to do.
        final Configuration newGlobalConfig = service.getGlobalConfiguration();
        final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
        if (mLastReportedConfiguration.equals(newGlobalConfig)
                && mLastReportedOverrideConfiguration.equals(newTaskMergedOverrideConfig)
                && !forceNewConfig) {
        // Short circuit: if the two full configurations are equal (the common case), then there is
        // nothing to do.  We test the full configuration instead of the global and merged override
        // configurations because there are cases (like moving a task to the pinned stack) where
        // the combine configurations are equal, but would otherwise differ in the override config
        mTmpConfig1.setTo(mLastReportedConfiguration);
        mTmpConfig1.updateFrom(mLastReportedOverrideConfiguration);
        if (task.getConfiguration().equals(mTmpConfig1) && !forceNewConfig) {
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Configuration unchanged in " + this);
            return true;
@@ -1997,14 +1994,16 @@ final class ActivityRecord implements AppWindowContainerListener {

        // Okay we now are going to make this activity have the new config.
        // But then we need to figure out how it needs to deal with that.
        mTmpGlobalConfig.setTo(mLastReportedConfiguration);
        mTmpTaskConfig.setTo(mLastReportedOverrideConfiguration);
        final Configuration newGlobalConfig = service.getGlobalConfiguration();
        final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
        mTmpConfig1.setTo(mLastReportedConfiguration);
        mTmpConfig2.setTo(mLastReportedOverrideConfiguration);
        mLastReportedConfiguration.setTo(newGlobalConfig);
        mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);

        int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
                mTmpTaskConfig);
        final int changes = mTmpGlobalConfig.diff(newGlobalConfig) | taskChanges;
                mTmpConfig2);
        final int changes = mTmpConfig1.diff(newGlobalConfig) | taskChanges;
        if (changes == 0 && !forceNewConfig) {
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Configuration no differences in " + this);
+16 −47
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Debug;
@@ -52,6 +51,7 @@ import com.android.internal.app.IVoiceInteractor;
import com.android.internal.util.XmlUtils;

import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.StackWindowController;
import com.android.server.wm.TaskWindowContainerController;
import com.android.server.wm.TaskWindowContainerListener;

@@ -278,7 +278,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
    private final Rect mTmpStableBounds = new Rect();
    private final Rect mTmpNonDecorBounds = new Rect();
    private final Rect mTmpRect = new Rect();
    private final Rect mTmpRect2 = new Rect();

    // Last non-fullscreen bounds the task was launched in or resized to.
    // The information is persisted and used to determine the appropriate stack to launch the
@@ -1838,60 +1837,32 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
        return !mTmpConfig.equals(newConfig);
    }

    private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
                                        boolean overrideWidth, boolean overrideHeight) {
        mTmpRect2.set(inInsetBounds);
        mService.mWindowManager.subtractNonDecorInsets(mTmpRect2);
        int leftInset = mTmpRect2.left - inInsetBounds.left;
        int topInset = mTmpRect2.top - inInsetBounds.top;
        int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
        int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
        inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
    }

    private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds,
                                      boolean overrideWidth, boolean overrideHeight) {
        mTmpRect2.set(inInsetBounds);
        mService.mWindowManager.subtractStableInsets(mTmpRect2);
        int leftInset = mTmpRect2.left - inInsetBounds.left;
        int topInset = mTmpRect2.top - inInsetBounds.top;
        int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
        int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
        inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
    }

    /** Clears passed config and fills it with new override values. */
    private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
            boolean overrideWidth, boolean overrideHeight) {
        mTmpNonDecorBounds.set(bounds);
        mTmpStableBounds.set(bounds);

        final Configuration parentConfig = getParent().getConfiguration();
        config.unset();
        final Configuration parentConfig = getParent().getConfiguration();
        final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
        final boolean isFloatingTask = mStack != null && StackId.tasksAreFloating(mStack.mStackId);
        if (isFloatingTask) {
            // Floating tasks should not be resized to the screen's bounds.
            config.screenWidthDp = (int) (mTmpStableBounds.width() / density);
            config.screenHeightDp = (int) (mTmpStableBounds.height() / density);
        } else {
            // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
            // i.e. the screen area without the system bars.
            // Additionally task dimensions should not be bigger than its parents dimensions.
            subtractNonDecorInsets(mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
                    overrideWidth, overrideHeight);
            subtractStableInsets(mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
                    overrideWidth, overrideHeight);
            config.screenWidthDp = Math.min(
                    (int) (mTmpStableBounds.width() / density), parentConfig.screenWidthDp);
            config.screenHeightDp = Math.min(
                    (int) (mTmpStableBounds.height() / density), parentConfig.screenHeightDp);
        }

        // TODO: Orientation?
        config.orientation = (config.screenWidthDp <= config.screenHeightDp)
                ? Configuration.ORIENTATION_PORTRAIT
                : Configuration.ORIENTATION_LANDSCAPE;
        if (mStack != null) {
            final StackWindowController stackController = mStack.getWindowContainerController();
            stackController.adjustConfigurationForBounds(bounds, insetBounds,
                    mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
                    config, parentConfig);
        } else {
            // No stack, give some default values
            config.smallestScreenWidthDp =
                    mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
            config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
            Slog.wtf(TAG, "Expected stack when caclulating override config");
        }

        // For calculating screen layout, we need to use the non-decor inset screen area for the
        // calculation for compatibility reasons, i.e. screen area without system bars that could
@@ -1905,8 +1876,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
        final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
        config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);

        config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
                insetBounds != null ? insetBounds : bounds);
    }

    /**
+1 −6
Original line number Diff line number Diff line
@@ -152,11 +152,6 @@ public class DockedStackDividerController implements DimLayerUser {
    int getSmallestWidthDpForBounds(Rect bounds) {
        final DisplayInfo di = mDisplayContent.getDisplayInfo();

        // If the bounds are fullscreen, return the value of the fullscreen configuration
        if (bounds == null || (bounds.left == 0 && bounds.top == 0
                && bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
            return mDisplayContent.getConfiguration().smallestScreenWidthDp;
        }
        final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
        final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
        int minWidth = Integer.MAX_VALUE;
@@ -185,7 +180,7 @@ public class DockedStackDividerController implements DimLayerUser {
                    mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
            mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
                    mTmpRect3);
            mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
            mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
            minWidth = Math.min(mTmpRect.width(), minWidth);
        }
        return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
+112 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.server.wm;

import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;

import android.app.ActivityManager.StackId;
import android.app.RemoteAction;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -24,6 +27,8 @@ import android.os.Looper;
import android.os.Message;
import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayInfo;

import com.android.server.UiThread;
import com.android.internal.annotations.VisibleForTesting;

@@ -48,6 +53,12 @@ public class StackWindowController

    private final H mHandler;

    // Temp bounds only used in adjustConfigurationForBounds()
    private final Rect mTmpRect = new Rect();
    private final Rect mTmpStableInsets = new Rect();
    private final Rect mTmpNonDecorInsets = new Rect();
    private final Rect mTmpDisplayBounds = new Rect();

    public StackWindowController(int stackId, StackWindowListener listener,
            int displayId, boolean onTop, Rect outBounds) {
        this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
@@ -289,6 +300,107 @@ public class StackWindowController
        }
    }

    /**
     * Adjusts the screen size in dp's for the {@param config} for the given params.
     */
    public void adjustConfigurationForBounds(Rect bounds, Rect insetBounds,
            Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth,
            boolean overrideHeight, float density, Configuration config,
            Configuration parentConfig) {
        synchronized (mWindowMap) {
            final TaskStack stack = mContainer;
            final DisplayContent displayContent = stack.getDisplayContent();
            final DisplayInfo di = displayContent.getDisplayInfo();

            // Get the insets and display bounds
            mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
                    mTmpStableInsets);
            mService.mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
                    mTmpNonDecorInsets);
            mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);

            int width;
            int height;
            if (StackId.tasksAreFloating(mStackId)) {
                // Floating tasks should not be resized to the screen's bounds.

                if (bounds.width() == mTmpDisplayBounds.width() &&
                        bounds.height() == mTmpDisplayBounds.height()) {
                    // If the bounds we are animating is the same as the fullscreen stack
                    // dimensions, then apply the same inset calculations that we normally do for
                    // the fullscreen stack, without intersecting it with the display bounds
                    stableBounds.inset(mTmpStableInsets);
                    nonDecorBounds.inset(mTmpNonDecorInsets);
                }
                width = (int) (stableBounds.width() / density);
                height = (int) (stableBounds.height() / density);
            } else {
                // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
                // area, i.e. the screen area without the system bars.
                // Additionally task dimensions should not be bigger than its parents dimensions.
                // The non decor inset are areas that could never be removed in Honeycomb. See
                // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
                intersectDisplayBoundsExcludeInsets(nonDecorBounds,
                        insetBounds != null ? insetBounds : bounds, mTmpNonDecorInsets,
                        mTmpDisplayBounds, overrideWidth, overrideHeight);
                intersectDisplayBoundsExcludeInsets(stableBounds,
                        insetBounds != null ? insetBounds : bounds, mTmpStableInsets,
                        mTmpDisplayBounds, overrideWidth, overrideHeight);
                width = Math.min((int) (stableBounds.width() / density),
                        parentConfig.screenWidthDp);
                height = Math.min((int) (stableBounds.height() / density),
                        parentConfig.screenHeightDp);
            }

            config.screenWidthDp = width;
            config.screenHeightDp = height;
            config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
                    insetBounds != null ? insetBounds : bounds, density);
        }
    }

    /**
     * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
     * inset areas.
     *
     * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
     */
    private void intersectDisplayBoundsExcludeInsets(Rect inOutBounds, Rect inInsetBounds,
            Rect stableInsets, Rect displayBounds, boolean overrideWidth, boolean overrideHeight) {
        mTmpRect.set(inInsetBounds);
        mService.intersectDisplayInsetBounds(displayBounds, stableInsets, mTmpRect);
        int leftInset = mTmpRect.left - inInsetBounds.left;
        int topInset = mTmpRect.top - inInsetBounds.top;
        int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect.right;
        int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect.bottom;
        inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
    }

    /**
     * Calculates the smallest width for a task given the {@param bounds}.
     *
     * @return the smallest width to be used in the Configuration, in dips
     */
    private int getSmallestWidthForTaskBounds(Rect bounds, float density) {
        final DisplayContent displayContent = mContainer.getDisplayContent();
        final DisplayInfo displayInfo = displayContent.getDisplayInfo();

        if (bounds == null || (bounds.width() == displayInfo.logicalWidth &&
                bounds.height() == displayInfo.logicalHeight)) {
            // If the bounds are fullscreen, return the value of the fullscreen configuration
            return displayContent.getConfiguration().smallestScreenWidthDp;
        } else if (StackId.tasksAreFloating(mStackId)) {
            // For floating tasks, calculate the smallest width from the bounds of the task
            return (int) (Math.min(bounds.width(), bounds.height()) / density);
        } else {
            // Iterating across all screen orientations, and return the minimum of the task
            // width taking into account that the bounds might change because the snap algorithm
            // snaps to a different value
            return displayContent.getDockedDividerController()
                    .getSmallestWidthDpForBounds(bounds);
        }
    }

    void requestResize(Rect bounds) {
        mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
    }
+4 −1
Original line number Diff line number Diff line
@@ -1476,7 +1476,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye

    @Override
    public void getFullScreenBounds(Rect bounds) {
        getDisplayContent().getContentRect(bounds);
        // This is currently only used for the pinned stack animation when leaving PiP
        // (see {@link BoundsAnimationController}), and in that case we need to animate this back
        // to the full bounds to match the fullscreen stack
        getDisplayContent().getLogicalDisplayRect(bounds);
    }

    public boolean hasMovementAnimations() {
Loading