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

Commit 49636f6f authored by Graciela Putri's avatar Graciela Putri
Browse files

Consolidate task resizable definition with activity

In ActivityRecord, the activity can be forced resizable with:
1. Device manufacturer sets force resize override for the app
2. Device manufacturer sets fullscreen override for the app
3. User sets the app to be resizable with the fullscreen override
4. Activity is universal resizeable (targetSDK >= 36, isLargeScreen
   device and not Category.GAME).

And device manufacturer can also set the app to be non-resizable with
FORCE_NON_RESIZE.

By definition, this should also affect task resizability, and allow app
to enter multi-window mode if resizability has been overridden. To
consolidate resizability definition, if the root activity has been
overridden and app has not opted out from the override, task
resizability should respect the overrides.

Flag: EXEMPT bug fix
Fix: 364878310
Test: atest TaskTests
      atest WindowOrganizerTests
Change-Id: I151bc1b26dc0fa08e07335b4ec8cac89ea096e48
parent d7aec9a6
Loading
Loading
Loading
Loading
+20 −29
Original line number Diff line number Diff line
@@ -35,8 +35,6 @@ import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.FORCE_NON_RESIZE_APP;
import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP;
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;
@@ -51,7 +49,6 @@ import static android.view.Display.INVALID_DISPLAY;
import static android.view.SurfaceControl.METADATA_TASK_ID;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -132,7 +129,6 @@ import android.app.IActivityController;
import android.app.PictureInPictureParams;
import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -514,10 +510,16 @@ class Task extends TaskFragment {
    boolean mIsPerceptible = false;

    /**
     * Whether the compatibility overrides that change the resizability of the app should be allowed
     * for the specific app.
     * Whether the task has been forced resizable, which is determined by the
     *  activity that started this task.
     */
    boolean mAllowForceResizeOverride = true;
    private boolean mForceResizeOverride;

    /**
     * Whether the task has been forced non-resizable, which is determined by
     * the activity that started this task.
     */
    private boolean mForceNonResizeOverride;

    private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_TASK_MSG + 1;

@@ -675,7 +677,6 @@ class Task extends TaskFragment {
            intent = _intent;
            mMinWidth = minWidth;
            mMinHeight = minHeight;
            updateAllowForceResizeOverride();
        }
        mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
        mHandler = new ActivityTaskHandler(mTaskSupervisor.mLooper);
@@ -946,6 +947,7 @@ class Task extends TaskFragment {
            mCallingPackage = r.launchedFromPackage;
            mCallingFeatureId = r.launchedFromFeatureId;
            setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
            updateForceResizeOverrides(r);
        }
        setLockTaskAuth(r);
    }
@@ -1038,7 +1040,6 @@ class Task extends TaskFragment {
            mTaskSupervisor.mRecentTasks.remove(this);
            mTaskSupervisor.mRecentTasks.add(this);
        }
        updateAllowForceResizeOverride();
    }

    /** Sets the original minimal width and height. */
@@ -1844,15 +1845,14 @@ class Task extends TaskFragment {
                -1 /* don't check PID */, -1 /* don't check UID */, this);
    }

    private void updateAllowForceResizeOverride() {
        try {
            mAllowForceResizeOverride = mAtmService.mContext.getPackageManager().getPropertyAsUser(
                    PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES,
                    getBasePackageName(), null /* className */, mUserId).getBoolean();
        } catch (PackageManager.NameNotFoundException e) {
            // Package not found or property not defined, reset to default value.
            mAllowForceResizeOverride = true;
        }
    private void updateForceResizeOverrides(@NonNull ActivityRecord r) {
        final AppCompatResizeOverrides resizeOverrides = r.mAppCompatController
                .getResizeOverrides();
        mForceResizeOverride = resizeOverrides.shouldOverrideForceResizeApp()
                || r.isUniversalResizeable()
                || r.mAppCompatController.getAspectRatioOverrides()
                    .hasFullscreenOverride();
        mForceNonResizeOverride = resizeOverrides.shouldOverrideForceNonResizeApp();
    }

    /**
@@ -2856,17 +2856,8 @@ class Task extends TaskFragment {
        final boolean forceResizable = mAtmService.mForceResizableActivities
                && getActivityType() == ACTIVITY_TYPE_STANDARD;
        if (forceResizable) return true;

        final UserHandle userHandle = UserHandle.getUserHandleForUid(mUserId);
        final boolean forceResizableOverride = mAllowForceResizeOverride
                && CompatChanges.isChangeEnabled(
                        FORCE_RESIZE_APP, getBasePackageName(), userHandle);
        final boolean forceNonResizableOverride = mAllowForceResizeOverride
                && CompatChanges.isChangeEnabled(
                        FORCE_NON_RESIZE_APP, getBasePackageName(), userHandle);

        if (forceNonResizableOverride) return false;
        return forceResizableOverride || ActivityInfo.isResizeableMode(mResizeMode)
        if (mForceNonResizeOverride) return false;
        return mForceResizeOverride || ActivityInfo.isResizeableMode(mResizeMode)
                || (mSupportsPictureInPicture && checkPictureInPictureSupport);
    }

+50 −35
Original line number Diff line number Diff line
@@ -100,8 +100,6 @@ import androidx.test.filters.MediumTest;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;

import libcore.junit.util.compat.CoreCompatChangeRule;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
@@ -414,79 +412,96 @@ public class TaskTests extends WindowTestsBase {
    }

    @Test
    @CoreCompatChangeRule.EnableCompatChanges({ActivityInfo.FORCE_RESIZE_APP})
    public void testIsResizeable_nonResizeable_forceResize_overridesEnabled_Resizeable() {
    public void testIsResizeable_nonResizeable_forceResize_overridesEnabled_resizeable() {
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateActivity(true)
                .setComponent(
                        ComponentName.createRelative(mContext, SizeCompatTests.class.getName()))
                .build();
        task.setResizeMode(RESIZE_MODE_UNRESIZEABLE);
        final ActivityRecord activity = task.getRootActivity();
        final AppCompatResizeOverrides resizeOverrides =
                activity.mAppCompatController.getResizeOverrides();
        spyOn(activity);
        spyOn(resizeOverrides);
        doReturn(true).when(resizeOverrides).shouldOverrideForceResizeApp();
        task.intent = null;
        task.setIntent(activity);
        // Override should take effect and task should be resizeable.
        assertTrue(task.getTaskInfo().isResizeable);
    }

    @Test
    @CoreCompatChangeRule.EnableCompatChanges({ActivityInfo.FORCE_RESIZE_APP})
    public void testIsResizeable_nonResizeable_forceResize_overridesDisabled_nonResizeable() {
    public void testIsResizeable_resizeable_forceNonResize_overridesEnabled_nonResizeable() {
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateActivity(true)
                .setComponent(
                        ComponentName.createRelative(mContext, SizeCompatTests.class.getName()))
                .build();
        task.setResizeMode(RESIZE_MODE_UNRESIZEABLE);

        // Disallow resize overrides.
        task.mAllowForceResizeOverride = false;
        task.setResizeMode(RESIZE_MODE_RESIZEABLE);
        final ActivityRecord activity = task.getRootActivity();
        final AppCompatResizeOverrides resizeOverrides =
                activity.mAppCompatController.getResizeOverrides();
        spyOn(activity);
        spyOn(resizeOverrides);
        doReturn(true).when(resizeOverrides).shouldOverrideForceNonResizeApp();
        task.intent = null;
        task.setIntent(activity);

        // Override should not take effect and task should be un-resizeable.
        // Override should take effect and task should be un-resizeable.
        assertFalse(task.getTaskInfo().isResizeable);
    }

    @Test
    @CoreCompatChangeRule.EnableCompatChanges({ActivityInfo.FORCE_NON_RESIZE_APP})
    public void testIsResizeable_resizeable_forceNonResize_overridesEnabled_nonResizeable() {
    public void testIsResizeable_resizeableTask_fullscreenOverride_resizeable() {
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateActivity(true)
                .setComponent(
                        ComponentName.createRelative(mContext, SizeCompatTests.class.getName()))
                .build();
        task.setResizeMode(RESIZE_MODE_RESIZEABLE);
        task.setResizeMode(RESIZE_MODE_UNRESIZEABLE);
        final ActivityRecord activity = task.getRootActivity();
        final AppCompatAspectRatioOverrides aspectRatioOverrides =
                activity.mAppCompatController.getAspectRatioOverrides();
        spyOn(aspectRatioOverrides);
        doReturn(true).when(aspectRatioOverrides).hasFullscreenOverride();
        task.intent = null;
        task.setIntent(activity);

        // Override should take effect and task should be un-resizeable.
        assertFalse(task.getTaskInfo().isResizeable);
        // Override should take effect and task should be resizeable.
        assertTrue(task.getTaskInfo().isResizeable);
    }

    @Test
    @CoreCompatChangeRule.EnableCompatChanges({ActivityInfo.FORCE_NON_RESIZE_APP})
    public void testIsResizeable_resizeable_forceNonResize_overridesDisabled_Resizeable() {
    public void testIsResizeable_resizeableTask_universalResizeable_resizeable() {
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateActivity(true)
                .setComponent(
                        ComponentName.createRelative(mContext, SizeCompatTests.class.getName()))
                .build();
        task.setResizeMode(RESIZE_MODE_RESIZEABLE);

        // Disallow resize overrides.
        task.mAllowForceResizeOverride = false;
        task.setResizeMode(RESIZE_MODE_UNRESIZEABLE);
        final ActivityRecord activity = task.getRootActivity();
        spyOn(activity);
        doReturn(true).when(activity).isUniversalResizeable();
        task.intent = null;
        task.setIntent(activity);

        // Override should not take effect and task should be resizeable.
        // Override should take effect and task should be resizeable.
        assertTrue(task.getTaskInfo().isResizeable);
    }

    @Test
    @CoreCompatChangeRule.EnableCompatChanges({ActivityInfo.FORCE_NON_RESIZE_APP})
    public void testIsResizeable_systemWideForceResize_compatForceNonResize__Resizeable() {
    public void testIsResizeable_systemWideForceResize_compatForceNonResize_resizeable() {
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateActivity(true)
                .setComponent(
                        ComponentName.createRelative(mContext, SizeCompatTests.class.getName()))
                .setComponent(ComponentName.createRelative(mContext, TaskTests.class.getName()))
                .build();
        task.setResizeMode(RESIZE_MODE_RESIZEABLE);

        // Set system-wide force resizeable override.
        task.mAtmService.mForceResizableActivities = true;

        final ActivityRecord activity = task.getRootActivity();
        final AppCompatResizeOverrides resizeOverrides =
                activity.mAppCompatController.getResizeOverrides();
        spyOn(activity);
        spyOn(resizeOverrides);
        doReturn(true).when(resizeOverrides).shouldOverrideForceNonResizeApp();
        task.intent = null;
        task.setIntent(activity);

        // System wide override should tak priority over app compat override so the task should
        // remain resizeable.
        assertTrue(task.getTaskInfo().isResizeable);