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

Commit 72a73e34 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Track making activity resizeable based on sdk version separately.

To support resizeable home activities we need to make the home activity
resizeable only when the app explicitly says it is resizeable. To be able
to do that we need to track if we are allowing the app to be resizeable
due to the sdk version it is targetting separately from it explicitly
setting it so that activity manager and window manager can make the right
choices in a follow-up CL.

Bug: 30982291
Test: cts/hostsidetests/services/activityandwindowmanager/util/run-test android.server.cts
Change-Id: I10f53ee9e57a41a3edece91cf68c5e8ef4bf4489
parent 3eadad75
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -163,7 +163,13 @@ public class ActivityInfo extends ComponentInfo
     */
    public static final int RESIZE_MODE_UNRESIZEABLE = 0;
    /**
     * Activity is resizeable.
     * Activity didn't explicitly request to be resizeable, but we are making it resizeable because
     * of the SDK version it targets.
     * @hide
     */
    public static final int RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION = 1;
    /**
     * Activity explicitly requested to be resizeable.
     * @hide
     */
    public static final int RESIZE_MODE_RESIZEABLE = 2;
@@ -856,7 +862,8 @@ public class ActivityInfo extends ComponentInfo
    public static boolean isResizeableMode(int mode) {
        return mode == RESIZE_MODE_RESIZEABLE
                || mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
                || mode == RESIZE_MODE_FORCE_RESIZEABLE;
                || mode == RESIZE_MODE_FORCE_RESIZEABLE
                || mode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
    }

    /** @hide */
@@ -864,6 +871,8 @@ public class ActivityInfo extends ComponentInfo
        switch (mode) {
            case RESIZE_MODE_UNRESIZEABLE:
                return "RESIZE_MODE_UNRESIZEABLE";
            case RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
                return "RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION";
            case RESIZE_MODE_RESIZEABLE:
                return "RESIZE_MODE_RESIZEABLE";
            case RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
+17 −3
Original line number Diff line number Diff line
@@ -520,12 +520,26 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
    public static final int PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER = 1 << 10;

    /**
     * When set, the activities associated with this application are resizeable by default.
     * When set, the application explicitly requested that its activities by resizeable by default.
     * @see android.R.styleable#AndroidManifestActivity_resizeableActivity
     *
     * @hide
     */
    public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES = 1 << 11;
    public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET = 1 << 11;

    /**
     * The application isn't requesting explicitly requesting for its activities to be resizeable or
     * non-resizeable by default. So, we are making it activities resizeable by default based on the
     * target SDK version of the app.
     * @see android.R.styleable#AndroidManifestActivity_resizeableActivity
     *
     * NOTE: This only affects apps with target SDK >= N where the resizeableActivity attribute was
     * introduced. It shouldn't be confused with {@link ActivityInfo#RESIZE_MODE_FORCE_RESIZEABLE}
     * where certain pre-N apps are forced to the resizeable.
     *
     * @hide
     */
    public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION = 1 << 12;

    /**
     * Value for {@link #privateFlags}: {@code true} means the OS should go ahead and
@@ -533,7 +547,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     * foreground-equivalent run state.  Defaults to {@code false} if unspecified.
     * @hide
     */
    public static final int PRIVATE_FLAG_BACKUP_IN_FOREGROUND = 1 << 12;
    public static final int PRIVATE_FLAG_BACKUP_IN_FOREGROUND = 1 << 13;

    /**
     * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
+36 −26
Original line number Diff line number Diff line
@@ -83,10 +83,12 @@ 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_RESIZEABLE;
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_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
@@ -2940,9 +2942,12 @@ public class PackageParser {
            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
        }

        if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
                owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N)) {
            ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
        if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
            if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
                ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET;
            }
        } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
            ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION;
        }

        ai.networkSecurityConfigRes = sa.getResourceId(
@@ -3683,31 +3688,36 @@ public class PackageParser {
    }

    private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
        aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
        final boolean appDefault = (owner.applicationInfo.privateFlags
                & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES) != 0;
        // This flag is used to workaround the issue with ignored resizeableActivity param when
        // either targetSdkVersion is not set at all or <uses-sdk> tag is below <application>
        // tag in AndroidManifest. If this param was explicitly set to 'false' we need to set
        // corresponding resizeMode regardless of targetSdkVersion value at this point in time.
        final boolean resizeableSetExplicitly
                = sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity);
        final boolean resizeable = sa.getBoolean(
                R.styleable.AndroidManifestActivity_resizeableActivity, appDefault);

        if (resizeable) {
            if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
                    false)) {
                aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
        final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
                & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET) != 0;
        final boolean supportsPip =
                sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture, false);

        if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
                || appExplicitDefault) {
            // Activity or app explicitly set if it is resizeable or not;
            if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
                    appExplicitDefault)) {
                aInfo.resizeMode =
                        supportsPip ? RESIZE_MODE_RESIZEABLE_AND_PIPABLE : RESIZE_MODE_RESIZEABLE;
            } else {
                aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
            }
        } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N
                || resizeableSetExplicitly) {
                aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
        } else if (!aInfo.isFixedOrientation() && (aInfo.flags & FLAG_IMMERSIVE) == 0) {
            aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
            }
            return;
        }

        if ((owner.applicationInfo.privateFlags
                & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION) != 0) {
            // The activity or app didn't explicitly set the resizing option, however we want to
            // make it resize due to the sdk version it is targeting.
            aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
            return;
        }

        // 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.
        aInfo.resizeMode = (aInfo.isFixedOrientation() || (aInfo.flags & FLAG_IMMERSIVE) != 0)
                ? RESIZE_MODE_UNRESIZEABLE : RESIZE_MODE_FORCE_RESIZEABLE;
    }

    private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
+1 −0
Original line number Diff line number Diff line
@@ -479,6 +479,7 @@ public class Recents extends SystemUI
                return COUNTER_WINDOW_UNSUPPORTED;
            case ActivityInfo.RESIZE_MODE_RESIZEABLE:
            case ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
            case ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
                return COUNTER_WINDOW_SUPPORTED;
            default:
                return COUNTER_WINDOW_INCOMPATIBLE;
+3 −3
Original line number Diff line number Diff line
@@ -28,8 +28,7 @@ import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
import static android.view.Display.DEFAULT_DISPLAY;

import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS;
@@ -897,7 +896,8 @@ final class ActivityRecord {

    boolean isNonResizableOrForced() {
        return !isHomeActivity() && info.resizeMode != RESIZE_MODE_RESIZEABLE
                && info.resizeMode != RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
                && info.resizeMode != RESIZE_MODE_RESIZEABLE_AND_PIPABLE
                && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
    }

    boolean supportsPictureInPicture() {
Loading