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

Commit 0a932141 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Exclude stable insets from task config

When a app is in fullscreen, we exclude navigation bar and status bar
size when calculating the config. However, when in multi-window, and
the task was almost fullscreen, the height/width reported to the app
was actually larger than when it was in fullscreen. In order to fix
this, exclude the stable insets when calculating the task
configuration, and also fix a bug when calculating the screen layout.

Change-Id: I843ae012fb3050c79643d125550aacb6e73d27da
parent 9511b0f1
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -334,6 +334,21 @@ public final class Rect implements Parcelable {
        bottom -= insets.bottom;
    }

    /**
     * Insets the rectangle on all sides specified by the insets.
     * @hide
     * @param left The amount to add from the rectangle's left
     * @param top The amount to add from the rectangle's top
     * @param right The amount to subtract from the rectangle's right
     * @param bottom The amount to subtract from the rectangle's bottom
     */
    public void inset(int left, int top, int right, int bottom) {
        this.left += left;
        this.top += top;
        this.right -= right;
        this.bottom -= bottom;
    }

    /**
     * Returns true if (x,y) is inside the rectangle. The left and top are
     * considered to be inside, while the right and bottom are not. This means
+2 −1
Original line number Diff line number Diff line
@@ -1913,7 +1913,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
                    task.updateOverrideConfiguration(tempRect2);
                } else {
                    task.updateOverrideConfiguration(
                            tempTaskBounds != null ? tempTaskBounds : bounds);
                            tempTaskBounds != null ? tempTaskBounds : bounds,
                            tempTaskInsetBounds != null ? tempTaskInsetBounds : bounds);
                }
            }

+68 −34
Original line number Diff line number Diff line
@@ -16,37 +16,7 @@

package com.android.server.am;

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.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;

import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
@@ -55,6 +25,7 @@ import android.app.ActivityManager.TaskThumbnail;
import android.app.ActivityManager.TaskThumbnailInfo;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -86,6 +57,37 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;

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.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;

final class TaskRecord {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
    private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
@@ -238,6 +240,9 @@ final class TaskRecord {

    // Bounds of the Task. null for fullscreen tasks.
    Rect mBounds = null;
    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
    // task into on restore.
@@ -1291,9 +1296,22 @@ final class TaskRecord {

    /**
     * Update task's override configuration based on the bounds.
     * @param bounds The bounds of the task.
     * @return Update configuration or null if there is no change.
     */
    Configuration updateOverrideConfiguration(Rect bounds) {
        return updateOverrideConfiguration(bounds, null /* insetBounds */);
    }

    /**
     * Update task's override configuration based on the bounds.
     * @param bounds The bounds of the task.
     * @param insetBounds The bounds used to calculate the system insets, which is used here to
     *                    subtract the navigation bar/status bar size from the screen size reported
     *                    to the application. See {@link IActivityManager#resizeDockedStack}.
     * @return Update configuration or null if there is no change.
     */
    Configuration updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
        if (Objects.equals(mBounds, bounds)) {
            return null;
        }
@@ -1316,7 +1334,12 @@ final class TaskRecord {
            if (stack == null || StackId.persistTaskBounds(stack.mStackId)) {
                mLastNonFullscreenBounds = mBounds;
            }
            mOverrideConfig = calculateOverrideConfig(mBounds);

            // Stable insets need to be subtracted because we also subtract it in the fullscreen
            // configuration.
            mTmpRect.set(bounds);
            subtractStableInsets(mTmpRect, insetBounds != null ? insetBounds : mTmpRect);
            mOverrideConfig = calculateOverrideConfig(mTmpRect);
        }

        if (mFullscreen != oldFullscreen) {
@@ -1326,6 +1349,16 @@ final class TaskRecord {
        return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
    }

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

    Configuration calculateOverrideConfig(Rect bounds) {
        final Configuration serviceConfig = mService.mConfiguration;
        final Configuration config = new Configuration(Configuration.EMPTY);
@@ -1341,8 +1374,9 @@ final class TaskRecord {
                ? Configuration.ORIENTATION_PORTRAIT
                : Configuration.ORIENTATION_LANDSCAPE;
        final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout);
        config.screenLayout = Configuration.reduceScreenLayout(
                sl, config.screenWidthDp, config.screenHeightDp);
        int longSize = Math.max(config.screenWidthDp, config.screenHeightDp);
        int shortSize = Math.min(config.screenWidthDp, config.screenHeightDp);
        config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
        return config;
    }

+23 −1
Original line number Diff line number Diff line
@@ -464,6 +464,8 @@ public class WindowManagerService extends IWindowManager.Stub
    EmulatorDisplayOverlay mEmulatorDisplayOverlay;

    final float[] mTmpFloats = new float[9];
    final Rect mTmpRect = new Rect();
    final Rect mTmpRect2 = new Rect();

    boolean mDisplayReady;
    boolean mSafeMode;
@@ -10394,9 +10396,29 @@ public class WindowManagerService extends IWindowManager.Stub
    @Override
    public void getStableInsets(Rect outInsets) throws RemoteException {
        synchronized (mWindowMap) {
            getStableInsetsLocked(outInsets);
        }
    }

    private void getStableInsetsLocked(Rect outInsets) {
        final DisplayInfo di = getDefaultDisplayInfoLocked();
        mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
    }

    /**
     * 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.
     */
    public void subtractStableInsets(Rect inOutBounds) {
        synchronized (mWindowMap) {
            getStableInsetsLocked(mTmpRect2);
            final DisplayInfo di = getDefaultDisplayInfoLocked();
            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
            mTmpRect.inset(mTmpRect2);
            inOutBounds.intersect(mTmpRect);
        }
    }

    private final class LocalService extends WindowManagerInternal {