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

Commit 036e3adc authored by Andrii Kulian's avatar Andrii Kulian
Browse files

Don't put non-resizeable activities on secondary displays

There is a contract that a non-resizeable activity cannot get
a configuration different from the global config (or fullscreen
config on primary display). This CL ensures that for launching on
secondary displays and checks if target display's config matches
the global config.
If a forced-resizeable activity is launched to a secondary display
or there was an attempt to launch a non-resizeable activity that
failed, corresponding toast message will be displayed.

Bug: 36777179
Test: android.server.cts.ActivityManagerDisplayTests
Test: #testLaunchNonResizeableActivityOnSecondaryDisplay
Test: #testLaunchNonResizeableActivityWithSplitScreen
Test: #testMoveNonResizeableActivityToSecondaryDisplay
Change-Id: I5346afe740e78e4e5ba9a9694e97ac60b92663e9
parent aa6b649a
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -21,6 +21,11 @@ import android.content.ComponentName;

/** @hide */
oneway interface ITaskStackListener {
    /** Activity was resized to be displayed in split-screen. */
    const int FORCED_RESIZEABLE_REASON_SPLIT_SCREEN = 1;
    /** Activity was resized to be displayed on a secondary display. */
    const int FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY = 2;

    /** Called whenever there are changes to the state of tasks in a stack. */
    void onTaskStackChanged();

@@ -49,14 +54,25 @@ oneway interface ITaskStackListener {

    /**
     * Called when we launched an activity that we forced to be resizable.
     *
     * @param packageName Package name of the top activity in the task.
     * @param taskId Id of the task.
     * @param reason {@link #FORCED_RESIZEABLE_REASON_SPLIT_SCREEN} or
      *              {@link #FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY}.
     */
    void onActivityForcedResizable(String packageName, int taskId);
    void onActivityForcedResizable(String packageName, int taskId, int reason);

    /**
     * Callen when we launched an activity that is dismissed the docked stack.
     * Called when we launched an activity that dismissed the docked stack.
     */
    void onActivityDismissingDockedStack();

    /**
     * Called when an activity was requested to be launched on a secondary display but was not
     * allowed there.
     */
    void onActivityLaunchOnSecondaryDisplayFailed();

    /**
     * Called when a task is added.
     *
+6 −1
Original line number Diff line number Diff line
@@ -51,13 +51,18 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
    }

    @Override
    public void onActivityForcedResizable(String packageName, int taskId) throws RemoteException {
    public void onActivityForcedResizable(String packageName, int taskId, int reason)
            throws RemoteException {
    }

    @Override
    public void onActivityDismissingDockedStack() throws RemoteException {
    }

    @Override
    public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
    }

    @Override
    public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
    }
+6 −2
Original line number Diff line number Diff line
@@ -1811,10 +1811,14 @@
    <string name="report_rejected_touch" translatable="false">Report rejected touch</string>

    <!-- Multi-Window strings -->
    <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity and that things might crash/not work properly [CHAR LIMIT=NONE] -->
    <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity to be displayed in split-screen and that things might crash/not work properly [CHAR LIMIT=NONE] -->
    <string name="dock_forced_resizable">App may not work with split-screen.</string>
    <!-- Warning message when we try to dock a non-resizeble tasks and launch it in fullscreen instead. -->
    <!-- Warning message when we try to dock a non-resizeable task and launch it in fullscreen instead. -->
    <string name="dock_non_resizeble_failed_to_dock_text">App does not support split-screen.</string>
    <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity to be displayed on a secondary display and that things might crash/not work properly [CHAR LIMIT=NONE] -->
    <string name="forced_resizable_secondary_display">App may not work on a secondary display.</string>
    <!-- Warning message when we try to launch a non-resizeable activity on a secondary display and launch it on the primary instead. -->
    <string name="activity_launch_on_secondary_display_failed_text">App does not support launch on secondary displays.</string>

    <!-- accessibility label for button to open settings [CHAR LIMIT=NONE] -->
    <string name="accessibility_quick_settings_settings">Open settings.</string>
+17 −4
Original line number Diff line number Diff line
@@ -156,8 +156,9 @@ public class SystemServicesProxy {
        public void onPinnedActivityRestartAttempt() { }
        public void onPinnedStackAnimationStarted() { }
        public void onPinnedStackAnimationEnded() { }
        public void onActivityForcedResizable(String packageName, int taskId) { }
        public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
        public void onActivityDismissingDockedStack() { }
        public void onActivityLaunchOnSecondaryDisplayFailed() { }
        public void onTaskProfileLocked(int taskId, int userId) { }

        /**
@@ -224,9 +225,9 @@ public class SystemServicesProxy {
        }

        @Override
        public void onActivityForcedResizable(String packageName, int taskId)
        public void onActivityForcedResizable(String packageName, int taskId, int reason)
                throws RemoteException {
            mHandler.obtainMessage(H.ON_ACTIVITY_FORCED_RESIZABLE, taskId, 0, packageName)
            mHandler.obtainMessage(H.ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName)
                    .sendToTarget();
        }

@@ -235,6 +236,11 @@ public class SystemServicesProxy {
            mHandler.sendEmptyMessage(H.ON_ACTIVITY_DISMISSING_DOCKED_STACK);
        }

        @Override
        public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
            mHandler.sendEmptyMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED);
        }

        @Override
        public void onTaskProfileLocked(int taskId, int userId) {
            mHandler.obtainMessage(H.ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
@@ -1235,6 +1241,7 @@ public class SystemServicesProxy {
        private static final int ON_TASK_PROFILE_LOCKED = 8;
        private static final int ON_PINNED_STACK_ANIMATION_STARTED = 9;
        private static final int ON_ACTIVITY_UNPINNED = 10;
        private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED = 11;

        @Override
        public void handleMessage(Message msg) {
@@ -1285,7 +1292,7 @@ public class SystemServicesProxy {
                case ON_ACTIVITY_FORCED_RESIZABLE: {
                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
                        mTaskStackListeners.get(i).onActivityForcedResizable(
                                (String) msg.obj, msg.arg1);
                                (String) msg.obj, msg.arg1, msg.arg2);
                    }
                    break;
                }
@@ -1295,6 +1302,12 @@ public class SystemServicesProxy {
                    }
                    break;
                }
                case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
                        mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
                    }
                    break;
                }
                case ON_TASK_PROFILE_LOCKED: {
                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
                        mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2);
+20 −2
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.stackdivider;

import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;

import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
@@ -34,6 +37,8 @@ import com.android.systemui.R;
 */
public class ForcedResizableInfoActivity extends Activity implements OnTouchListener {

    public static final String EXTRA_FORCED_RESIZEABLE_REASON = "extra_forced_resizeable_reason";

    private static final long DISMISS_DELAY = 2500;

    private final Runnable mFinishRunnable = new Runnable() {
@@ -48,8 +53,21 @@ public class ForcedResizableInfoActivity extends Activity implements OnTouchList
        super.onCreate(savedInstanceState);
        setContentView(R.layout.forced_resizable_activity);
        TextView tv = (TextView) findViewById(com.android.internal.R.id.message);
        tv.setText(R.string.dock_forced_resizable);
        getWindow().setTitle(getString(R.string.dock_forced_resizable));
        int reason = getIntent().getIntExtra(EXTRA_FORCED_RESIZEABLE_REASON, -1);
        String text;
        switch (reason) {
            case FORCED_RESIZEABLE_REASON_SPLIT_SCREEN:
                text = getString(R.string.dock_forced_resizable);
                break;
            case FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY:
                text = getString(R.string.forced_resizable_secondary_display);
                break;
            default:
                throw new IllegalArgumentException("Unexpected forced resizeable reason: "
                        + reason);
        }
        tv.setText(text);
        getWindow().setTitle(text);
        getWindow().getDecorView().setOnTouchListener(this);
    }

Loading