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

Commit f3c6a47b authored by Bryce Lee's avatar Bryce Lee
Browse files

Store bounds in WindowConfiguration.

This changelist consolidates the usage of frame bounds in containers
into the WindowConfiguration. As a result, the bounds are now shared
across AM and WM. Any changes to the bounds on one side are
propagated to the other via override configuration changes. Previous
instrumentation to synchronize the two sides is no longer necessary.

This changelist does not attempt to consolidate common logic shared
between WM or AM components for setting bounds.

Bug: 68719294
Test: go/wm-smoke
Change-Id: Ia8978dba8525b83201640e159caefe16e626b7c1
parent 9cc5b4f0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -75,9 +75,11 @@ package android.app {
    method public int describeContents();
    method public int getActivityType();
    method public android.graphics.Rect getAppBounds();
    method public android.graphics.Rect getBounds();
    method public int getWindowingMode();
    method public void setActivityType(int);
    method public void setAppBounds(android.graphics.Rect);
    method public void setBounds(android.graphics.Rect);
    method public void setTo(android.app.WindowConfiguration);
    method public void setWindowingMode(int);
    method public void writeToParcel(android.os.Parcel, int);
+60 −5
Original line number Diff line number Diff line
@@ -40,6 +40,13 @@ import android.view.DisplayInfo;
 */
@TestApi
public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {
    /**
     * bounds that can differ from app bounds, which may include things such as insets.
     *
     * TODO: Investigate combining with {@link mAppBounds}. Can the latter be a product of the
     * former?
     */
    private Rect mBounds = new Rect();

    /**
     * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
@@ -117,22 +124,26 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
    })
    public @interface ActivityType {}

    /** Bit that indicates that the {@link #mBounds} changed.
     * @hide */
    public static final int WINDOW_CONFIG_BOUNDS = 1 << 0;
    /** Bit that indicates that the {@link #mAppBounds} changed.
     * @hide */
    public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 0;
    public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 1;
    /** Bit that indicates that the {@link #mWindowingMode} changed.
     * @hide */
    public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 1;
    public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 2;
    /** Bit that indicates that the {@link #mActivityType} changed.
     * @hide */
    public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 2;
    public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 3;

    /** @hide */
    @IntDef(flag = true,
            value = {
                    WINDOW_CONFIG_BOUNDS,
                    WINDOW_CONFIG_APP_BOUNDS,
                    WINDOW_CONFIG_WINDOWING_MODE,
                    WINDOW_CONFIG_ACTIVITY_TYPE,
                    WINDOW_CONFIG_ACTIVITY_TYPE
            })
    public @interface WindowConfig {}

@@ -151,12 +162,14 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(mBounds, flags);
        dest.writeParcelable(mAppBounds, flags);
        dest.writeInt(mWindowingMode);
        dest.writeInt(mActivityType);
    }

    private void readFromParcel(Parcel source) {
        mBounds = source.readParcelable(Rect.class.getClassLoader());
        mAppBounds = source.readParcelable(Rect.class.getClassLoader());
        mWindowingMode = source.readInt();
        mActivityType = source.readInt();
@@ -180,6 +193,19 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
        }
    };

    /**
     * Sets the bounds to the provided {@link Rect}.
     * @param rect the new bounds value.
     */
    public void setBounds(Rect rect) {
        if (rect == null) {
            mBounds.setEmpty();
            return;
        }

        mBounds.set(rect);
    }

    /**
     * Set {@link #mAppBounds} to the input Rect.
     * @param rect The rect value to set {@link #mAppBounds} to.
@@ -212,6 +238,11 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
        return mAppBounds;
    }

    /** @see #setBounds(Rect) */
    public Rect getBounds() {
        return mBounds;
    }

    public void setWindowingMode(@WindowingMode int windowingMode) {
        mWindowingMode = windowingMode;
    }
@@ -244,6 +275,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
    }

    public void setTo(WindowConfiguration other) {
        setBounds(other.mBounds);
        setAppBounds(other.mAppBounds);
        setWindowingMode(other.mWindowingMode);
        setActivityType(other.mActivityType);
@@ -258,6 +290,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
    /** @hide */
    public void setToDefaults() {
        setAppBounds(null);
        setBounds(null);
        setWindowingMode(WINDOWING_MODE_UNDEFINED);
        setActivityType(ACTIVITY_TYPE_UNDEFINED);
    }
@@ -272,6 +305,11 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
     */
    public @WindowConfig int updateFrom(@NonNull WindowConfiguration delta) {
        int changed = 0;
        // Only allow override if bounds is not empty
        if (!delta.mBounds.isEmpty() && !delta.mBounds.equals(mBounds)) {
            changed |= WINDOW_CONFIG_BOUNDS;
            setBounds(delta.mBounds);
        }
        if (delta.mAppBounds != null && !delta.mAppBounds.equals(mAppBounds)) {
            changed |= WINDOW_CONFIG_APP_BOUNDS;
            setAppBounds(delta.mAppBounds);
@@ -303,6 +341,10 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
    public @WindowConfig long diff(WindowConfiguration other, boolean compareUndefined) {
        long changes = 0;

        if (!mBounds.equals(other.mBounds)) {
            changes |= WINDOW_CONFIG_BOUNDS;
        }

        // Make sure that one of the values is not null and that they are not equal.
        if ((compareUndefined || other.mAppBounds != null)
                && mAppBounds != other.mAppBounds
@@ -340,6 +382,16 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
            n = mAppBounds.bottom - that.mAppBounds.bottom;
            if (n != 0) return n;
        }

        n = mBounds.left - that.mBounds.left;
        if (n != 0) return n;
        n = mBounds.top - that.mBounds.top;
        if (n != 0) return n;
        n = mBounds.right - that.mBounds.right;
        if (n != 0) return n;
        n = mBounds.bottom - that.mBounds.bottom;
        if (n != 0) return n;

        n = mWindowingMode - that.mWindowingMode;
        if (n != 0) return n;
        n = mActivityType - that.mActivityType;
@@ -367,6 +419,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
        if (mAppBounds != null) {
            result = 31 * result + mAppBounds.hashCode();
        }
        result = 31 * result + mBounds.hashCode();

        result = 31 * result + mWindowingMode;
        result = 31 * result + mActivityType;
        return result;
@@ -375,7 +429,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
    /** @hide */
    @Override
    public String toString() {
        return "{mAppBounds=" + mAppBounds
        return "{ mBounds=" + mBounds
                + " mAppBounds=" + mAppBounds
                + " mWindowingMode=" + windowingModeToString(mWindowingMode)
                + " mActivityType=" + activityTypeToString(mActivityType) + "}";
    }
+12 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.IntArray;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -89,6 +91,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
    private ActivityStack mPinnedStack = null;
    private ActivityStack mSplitScreenPrimaryStack = null;

    // Used in updating the display size
    private Point mTmpDisplaySize = new Point();

    ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
        mSupervisor = supervisor;
        mDisplayId = displayId;
@@ -97,6 +102,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
            throw new IllegalStateException("Display does not exist displayId=" + displayId);
        }
        mDisplay = display;

        updateBounds();
    }

    void updateBounds() {
        mDisplay.getSize(mTmpDisplaySize);
        setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
    }

    void addChild(ActivityStack stack, int position) {
+3 −3
Original line number Diff line number Diff line
@@ -8092,7 +8092,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    return false;
                }
                // An activity is consider to be in multi-window mode if its task isn't fullscreen.
                return !r.getTask().mFullscreen;
                return r.inMultiWindowMode();
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
@@ -10111,8 +10111,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                } else {
                    // Task isn't in window manager yet since it isn't associated with a stack.
                    // Return the persist value from activity manager
                    if (task.mBounds != null) {
                        rect.set(task.mBounds);
                    if (!task.matchParentBounds()) {
                        rect.set(task.getBounds());
                    } else if (task.mLastNonFullscreenBounds != null) {
                        rect.set(task.mLastNonFullscreenBounds);
                    }
+18 −39
Original line number Diff line number Diff line
@@ -165,7 +165,6 @@ import android.view.IApplicationToken;
import android.view.WindowManager.LayoutParams;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.util.XmlUtils;
@@ -343,12 +342,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
    // on the window.
    int mRotationAnimationHint = -1;

    // The bounds of this activity. Mainly used for aspect-ratio compatibility.
    // TODO(b/36505427): Every level on ConfigurationContainer now has bounds information, which
    // directly affects the configuration. We should probably move this into that class and have it
    // handle calculating override configuration from the bounds.
    private final Rect mBounds = new Rect();

    private boolean mShowWhenLocked;
    private boolean mTurnScreenOn;

@@ -414,8 +407,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        if (!getOverrideConfiguration().equals(EMPTY)) {
            pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration());
        }
        if (!mBounds.isEmpty()) {
            pw.println(prefix + "mBounds=" + mBounds);
        if (!matchParentBounds()) {
            pw.println(prefix + "bounds=" + getBounds());
        }
        if (resultTo != null || resultWho != null) {
            pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
@@ -648,7 +641,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        }

        // An activity is considered to be in multi-window mode if its task isn't fullscreen.
        final boolean inMultiWindowMode = !task.mFullscreen;
        final boolean inMultiWindowMode = task.inMultiWindowMode();
        if (inMultiWindowMode != mLastReportedMultiWindowMode) {
            mLastReportedMultiWindowMode = inMultiWindowMode;
            scheduleMultiWindowModeChanged(getConfiguration());
@@ -966,14 +959,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
                (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
                task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
                appInfo.targetSdkVersion, mRotationAnimationHint,
                ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L, mBounds);
                ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);

        task.addActivityToTop(this);

        // When an activity is started directly into a split-screen fullscreen stack, we need to
        // update the initial multi-window modes so that the callbacks are scheduled correctly when
        // the user leaves that mode.
        mLastReportedMultiWindowMode = !task.mFullscreen;
        mLastReportedMultiWindowMode = inMultiWindowMode();
        mLastReportedPictureInPictureMode = inPinnedWindowingMode();
    }

@@ -2172,33 +2165,25 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        mLastReportedConfiguration.setConfiguration(global, override);
    }

    @Override
    public void onOverrideConfigurationChanged(Configuration newConfig) {
        final Configuration currentConfig = getOverrideConfiguration();
        if (currentConfig.equals(newConfig)) {
            return;
        }
        super.onOverrideConfigurationChanged(newConfig);
        if (mWindowContainerController == null) {
            return;
        }
        mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds);
    }

    // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
    private void updateOverrideConfiguration() {
        mTmpConfig.unset();
        computeBounds(mTmpBounds);
        if (mTmpBounds.equals(mBounds)) {

        if (mTmpBounds.equals(getOverrideBounds())) {
            return;
        }

        mBounds.set(mTmpBounds);
        setBounds(mTmpBounds);

        final Rect updatedBounds = getOverrideBounds();

        // Bounds changed...update configuration to match.
        if (!mBounds.isEmpty()) {
            task.computeOverrideConfiguration(mTmpConfig, mBounds, null /* insetBounds */,
        if (!matchParentBounds()) {
            task.computeOverrideConfiguration(mTmpConfig, updatedBounds, null /* insetBounds */,
                    false /* overrideWidth */, false /* overrideHeight */);
        }

        onOverrideConfigurationChanged(mTmpConfig);
    }

@@ -2225,7 +2210,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        outBounds.setEmpty();
        final float maxAspectRatio = info.maxAspectRatio;
        final ActivityStack stack = getStack();
        if (task == null || stack == null || !task.mFullscreen || maxAspectRatio == 0
        if (task == null || stack == null || task.inMultiWindowMode() || maxAspectRatio == 0
                || isInVrUiMode(getConfiguration())) {
            // We don't set override configuration if that activity task isn't fullscreen. I.e. the
            // activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
@@ -2256,11 +2241,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
            // The display matches or is less than the activity aspect ratio, so nothing else to do.
            // Return the existing bounds. If this method is running for the first time,
            // {@link mBounds} will be empty (representing no override). If the method has run
            // before, then effect of {@link mBounds} will already have been applied to the
            // {@link #getOverrideBounds()} will be empty (representing no override). If the method has run
            // before, then effect of {@link #getOverrideBounds()} will already have been applied to the
            // value returned from {@link getConfiguration}. Refer to
            // {@link TaskRecord#computeOverrideConfiguration}.
            outBounds.set(mBounds);
            outBounds.set(getOverrideBounds());
            return;
        }

@@ -2272,12 +2257,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        outBounds.offsetTo(left, 0 /* top */);
    }

    /** Get bounds of the activity. */
    @VisibleForTesting
    Rect getBounds() {
        return new Rect(mBounds);
    }

    /**
     * Make sure the given activity matches the current configuration. Returns false if the activity
     * had to be destroyed.  Returns true if the configuration is the same, or the activity will
Loading