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

Commit 322347ba authored by skuhne@google.com's avatar skuhne@google.com
Browse files

Adding orientation preserving resizing

Adding freeform resizing to activities which require
a certain orientation. This is needed for e.g. ARC++.

Bug: 33267688
Test: runtest frameworks-services -c com.android.server.wm.TaskPositionerTests
Test: Visually on ARC++
Change-Id: If708c1602cb2ff464174389af4648ad767b0b079
parent 5026cabb
Loading
Loading
Loading
Loading
+55 −6
Original line number Original line Diff line number Diff line
@@ -182,11 +182,29 @@ public class ActivityInfo extends ComponentInfo
     */
     */
    public static final int RESIZE_MODE_RESIZEABLE_AND_PIPABLE = 3;
    public static final int RESIZE_MODE_RESIZEABLE_AND_PIPABLE = 3;
    /**
    /**
     * Activity is does not support resizing, but we are forcing it to be resizeable. Only affects
     * Activity does not support resizing, but we are forcing it to be resizeable. Only affects
     * certain pre-N apps where we force them to be resizeable.
     * certain pre-N apps where we force them to be resizeable.
     * @hide
     * @hide
     */
     */
    public static final int RESIZE_MODE_FORCE_RESIZEABLE = 4;
    public static final int RESIZE_MODE_FORCE_RESIZEABLE = 4;
    /**
     * Activity does not support resizing, but we are forcing it to be resizeable as long
     * as the size remains landscape.
     * @hide
     */
    public static final int RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY = 5;
    /**
     * Activity does not support resizing, but we are forcing it to be resizeable as long
     * as the size remains portrait.
     * @hide
     */
    public static final int RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY = 6;
    /**
     * Activity does not support resizing, but we are forcing it to be resizeable as long
     * as the bounds remain in the same orientation as they are.
     * @hide
     */
    public static final int RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION = 7;
    /**
    /**
     * Value indicating if the resizing mode the activity supports.
     * Value indicating if the resizing mode the activity supports.
     * See {@link android.R.attr#resizeableActivity}.
     * See {@link android.R.attr#resizeableActivity}.
@@ -859,15 +877,30 @@ public class ActivityInfo extends ComponentInfo
     * @hide
     * @hide
     */
     */
    boolean isFixedOrientation() {
    boolean isFixedOrientation() {
        return isFixedOrientationLandscape() || isFixedOrientationPortrait()
                || screenOrientation == SCREEN_ORIENTATION_LOCKED;
    }

    /**
     * Returns true if the activity's orientation is fixed to landscape.
     * @hide
     */
    boolean isFixedOrientationLandscape() {
        return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
        return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
                || screenOrientation == SCREEN_ORIENTATION_PORTRAIT
                || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
                || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
                || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
                || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
                || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
                || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE;
    }

    /**
     * Returns true if the activity's orientation is fixed to portrait.
     * @hide
     */
    boolean isFixedOrientationPortrait() {
        return screenOrientation == SCREEN_ORIENTATION_PORTRAIT
                || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
                || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
                || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
                || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE
                || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT;
                || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT
                || screenOrientation == SCREEN_ORIENTATION_LOCKED;
    }
    }


    /** @hide */
    /** @hide */
@@ -875,9 +908,19 @@ public class ActivityInfo extends ComponentInfo
        return mode == RESIZE_MODE_RESIZEABLE
        return mode == RESIZE_MODE_RESIZEABLE
                || mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
                || mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
                || mode == RESIZE_MODE_FORCE_RESIZEABLE
                || mode == RESIZE_MODE_FORCE_RESIZEABLE
                || mode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
                || mode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
                || mode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION
                || mode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
                || mode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
    }
    }


    /** @hide */
    public static boolean isPreserveOrientationMode(int mode) {
        return mode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
                || mode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
                || mode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
    }

    /** @hide */
    /** @hide */
    public static String resizeModeToString(int mode) {
    public static String resizeModeToString(int mode) {
        switch (mode) {
        switch (mode) {
@@ -891,6 +934,12 @@ public class ActivityInfo extends ComponentInfo
                return "RESIZE_MODE_RESIZEABLE_AND_PIPABLE";
                return "RESIZE_MODE_RESIZEABLE_AND_PIPABLE";
            case RESIZE_MODE_FORCE_RESIZEABLE:
            case RESIZE_MODE_FORCE_RESIZEABLE:
                return "RESIZE_MODE_FORCE_RESIZEABLE";
                return "RESIZE_MODE_FORCE_RESIZEABLE";
            case RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY:
                return "RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY";
            case RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY:
                return "RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY";
            case RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION:
                return "RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION";
            default:
            default:
                return "unknown=" + mode;
                return "unknown=" + mode;
        }
        }
+12 −2
Original line number Original line Diff line number Diff line
@@ -88,6 +88,9 @@ import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
@@ -3896,8 +3899,15 @@ public class PackageParser {


        // resize preference isn't set and target sdk version doesn't support resizing apps by
        // resize preference isn't set and target sdk version doesn't support resizing apps by
        // default. For the app to be resizeable if it isn't fixed orientation or immersive.
        // default. For the app to be resizeable if it isn't fixed orientation or immersive.
        aInfo.resizeMode = (aInfo.isFixedOrientation() || (aInfo.flags & FLAG_IMMERSIVE) != 0)
        if (aInfo.isFixedOrientationPortrait()) {
                ? RESIZE_MODE_UNRESIZEABLE : RESIZE_MODE_FORCE_RESIZEABLE;
            aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
        } else if (aInfo.isFixedOrientationLandscape()) {
            aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
        } else if (aInfo.isFixedOrientation()) {
            aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
        } else {
            aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
        }
    }
    }


    private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
    private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
+5 −0
Original line number Original line Diff line number Diff line
@@ -2322,6 +2322,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer
            return true;
            return true;
        }
        }


        if (!task.canResizeToBounds(bounds)) {
            throw new IllegalArgumentException("resizeTaskLocked: Can not resize task=" + task
                    + " to bounds=" + bounds + " resizeMode=" + task.mResizeMode);
        }

        // Do not move the task to another stack here.
        // Do not move the task to another stack here.
        // This method assumes that the task is already placed in the right stack.
        // This method assumes that the task is already placed in the right stack.
        // we do not mess with that decision and we only do the resize!
        // we do not mess with that decision and we only do the resize!
+24 −1
Original line number Original line Diff line number Diff line
@@ -73,6 +73,9 @@ 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_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
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.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
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;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
@@ -1077,12 +1080,32 @@ final class TaskRecord extends ConfigurationContainer {
                && !mTemporarilyUnresizable;
                && !mTemporarilyUnresizable;
    }
    }


    /**
     * Check that a given bounds matches the application requested orientation.
     *
     * @param bounds The bounds to be tested.
     * @return True if the requested bounds are okay for a resizing request.
     */
    boolean canResizeToBounds(Rect bounds) {
        if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
            // Note: If not on the freeform workspace, we ignore the bounds.
            return true;
        }
        final boolean landscape = bounds.width() > bounds.height();
        if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
            return mBounds == null || landscape == (mBounds.width() > mBounds.height());
        }
        return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
                && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
    }

    boolean isOnTopLauncher() {
    boolean isOnTopLauncher() {
        return isHomeTask() && mIsOnTopLauncher;
        return isHomeTask() && mIsOnTopLauncher;
    }
    }


    boolean canGoInDockedStack() {
    boolean canGoInDockedStack() {
        return isResizeable();
        return isResizeable() &&
                !ActivityInfo.isPreserveOrientationMode(mResizeMode);
    }
    }


    /**
    /**
+14 −1
Original line number Original line Diff line number Diff line
@@ -19,7 +19,9 @@ package com.android.server.wm;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;

import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -280,6 +282,17 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
        return ActivityInfo.isResizeableMode(mResizeMode) || mService.mForceResizableTasks;
        return ActivityInfo.isResizeableMode(mResizeMode) || mService.mForceResizableTasks;
    }
    }


    /**
     * Tests if the orientation should be preserved upon user interactive resizig operations.

     * @return true if orientation should not get changed upon resizing operation.
     */
    boolean preserveOrientationOnResize() {
        return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
                || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
                || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
    }

    boolean isOnTopLauncher() {
    boolean isOnTopLauncher() {
        return mIsOnTopLauncher;
        return mIsOnTopLauncher;
    }
    }
Loading