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

Commit bd48dca2 authored by Louis Chang's avatar Louis Chang Committed by Andrii Kulian
Browse files

Support launching home activity on secondary display

- Add a new flag indicating that the display should show
  system decorations, such as status bar, nav bar, home and IME.
- Automatically launches home activity on secondary display
  if the display support system decorations and home
  activity has multiple instances supports.
- Remove ActivityStackSupervisor#mHomeStack and move several
  home stack related methods to ActivityDisplay.

Bug: 111363427
Test: atest ActivityManagerMultiDisplayTests
      atest com.android.server.am
      Manual test on virtual display and chromecast

Change-Id: I48fe245ad12965a19a6768f5dbb4e974ce94b01a
parent 33110132
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -297,6 +297,15 @@ public final class DisplayManager {
     */
    public static final int VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 8;

    /**
     * Virtual display flag: Indicates that the display should support system decorations. Virtual
     * displays without this flag shouldn't show home, IME or any other system decorations.
     *
     * @see #createVirtualDisplay
     * @hide
     */
    public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9;

    /** @hide */
    public DisplayManager(Context context) {
        mContext = context;
+22 −0
Original line number Diff line number Diff line
@@ -220,6 +220,18 @@ public final class Display {
     */
    public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;

    /**
     * Display flag: Indicates that the display should show system decorations.
     * <p>
     * This flag identifies secondary displays that should show system decorations, such as status
     * bar, navigation bar, home activity or IME.
     * </p>
     *
     * @see #supportsSystemDecorations
     * @hide
     */
    public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 6;

    /**
     * Display flag: Indicates that the contents of the display should not be scaled
     * to fit the physical screen dimensions.  Used for development only to emulate
@@ -873,6 +885,16 @@ public final class Display {
        return mDisplayInfo.removeMode;
    }

    /**
     * Returns whether this display should support showing system decorations.
     *
     * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
     * @hide
     */
    public boolean supportsSystemDecorations() {
        return (mDisplayInfo.flags & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0;
    }

    /**
     * Returns the display's HDR capabilities.
     *
+59 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.os.UserHandle;
import android.util.IntArray;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -911,6 +912,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
        return mDisplayAccessUIDs;
    }

    /**
     * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
     */
    boolean supportsSystemDecorations() {
        return mDisplay.supportsSystemDecorations();
    }

    private boolean shouldDestroyContentOnRemove() {
        return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
    }
@@ -981,6 +989,57 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
        positionChildAt(stack, Math.max(0, insertIndex));
    }

    void moveHomeStackToFront(String reason) {
        if (mHomeStack != null) {
            mHomeStack.moveToFront(reason);
        }
    }

    /** Returns true if the focus activity was adjusted to the home stack top activity. */
    boolean moveHomeActivityToTop(String reason) {
        final ActivityRecord top = getHomeActivity();
        if (top == null) {
            return false;
        }
        mSupervisor.moveFocusableActivityToTop(top, reason);
        return true;
    }

    @Nullable
    ActivityStack getHomeStack() {
        return mHomeStack;
    }

    @Nullable
    ActivityRecord getHomeActivity() {
        return getHomeActivityForUser(mSupervisor.mCurrentUser);
    }

    @Nullable
    ActivityRecord getHomeActivityForUser(int userId) {
        if (mHomeStack == null) {
            return null;
        }

        final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
            final TaskRecord task = tasks.get(taskNdx);
            if (!task.isActivityTypeHome()) {
                continue;
            }

            final ArrayList<ActivityRecord> activities = task.mActivities;
            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                final ActivityRecord r = activities.get(activityNdx);
                if (r.isActivityTypeHome()
                        && ((userId == UserHandle.USER_ALL) || (r.userId == userId))) {
                    return r;
                }
            }
        }
        return null;
    }

    boolean isSleeping() {
        return mSleeping;
    }
+12 −2
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
@@ -3725,6 +3726,14 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    boolean startHomeActivityLocked(int userId, String reason) {
        return startHomeActivityLocked(userId, reason, DEFAULT_DISPLAY);
    }
    /**
     * This starts home activity on displays that can have system decorations and only if the
     * home activity can have multiple instances.
     */
    boolean startHomeActivityLocked(int userId, String reason, int displayId) {
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            // We are running in factory test mode, but unable to find
@@ -3748,7 +3757,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                // For ANR debugging to verify if the user activity is the one that actually
                // launched.
                final String myReason = reason + ":" + userId + ":" + resolvedUserId;
                mActivityTaskManager.getActivityStartController().startHomeActivity(intent, aInfo, myReason);
                mActivityTaskManager.getActivityStartController().startHomeActivity(intent, aInfo,
                        myReason, displayId);
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
@@ -8817,7 +8827,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                        ? new ActivityOptions(options)
                        : ActivityOptions.makeBasic();
                activityOptions.setLaunchTaskId(
                        mStackSupervisor.getHomeActivity().getTask().taskId);
                        mStackSupervisor.getDefaultDisplayHomeActivity().getTask().taskId);
                mContext.startActivityAsUser(intent, activityOptions.toBundle(),
                        UserHandle.CURRENT);
            } finally {
+9 −28
Original line number Diff line number Diff line
@@ -1102,8 +1102,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        if (!isActivityTypeHome() && returnsToHomeStack()) {
            // Make sure the home stack is behind this stack since that is where we should return to
            // when this stack is no longer visible.
            // TODO(b/111541062): Move home stack on the current display
            mStackSupervisor.moveHomeStackToFront(reason + " returnToHome");
            display.moveHomeStackToFront(reason + " returnToHome");
        }

        display.positionChildAtTop(this, true /* includingParents */);
@@ -2854,9 +2853,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        // Only resume home if on home display
        return isOnHomeDisplay() &&
                mStackSupervisor.resumeHomeStackTask(prev, reason);
        return mStackSupervisor.resumeHomeActivity(prev, reason, mDisplayId);
    }

    /** Returns the position the input task should be placed in this stack. */
@@ -3450,8 +3447,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        final String myReason = reason + " adjustFocus";

        if (next == r) {
            mStackSupervisor.moveFocusableActivityStackToFrontLocked(
                    mStackSupervisor.topRunningActivityLocked(), myReason);
            mStackSupervisor.moveFocusableActivityToTop(mStackSupervisor.topRunningActivityLocked(),
                    myReason);
            return;
        }

@@ -3482,7 +3479,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        }

        // Whatever...go home.
        mStackSupervisor.moveHomeStackTaskToTop(myReason);
        getDisplay().moveHomeActivityToTop(myReason);
    }

    /**
@@ -3511,7 +3508,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        if (stack.isActivityTypeHome() && (top == null || !top.visible)) {
            // If we will be focusing on the home stack next and its current top activity isn't
            // visible, then use the move the home stack task to top to make the activity visible.
            mStackSupervisor.moveHomeStackTaskToTop(reason);
            stack.getDisplay().moveHomeActivityToTop(reason);
            return stack;
        }

@@ -4619,22 +4616,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        mStackSupervisor.invalidateTaskLayers();
    }

    void moveHomeStackTaskToTop() {
        if (!isActivityTypeHome()) {
            throw new IllegalStateException("Calling moveHomeStackTaskToTop() on non-home stack: "
                    + this);
        }
        final int top = mTaskHistory.size() - 1;
        if (top >= 0) {
            final TaskRecord task = mTaskHistory.get(top);
            if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK,
                    "moveHomeStackTaskToTop: moving " + task);
            mTaskHistory.remove(top);
            mTaskHistory.add(top, task);
            updateTaskMovement(task, true);
        }
    }

    final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
            AppTimeTracker timeTracker, String reason) {
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
@@ -4682,7 +4663,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai

            // Set focus to the top running activity of this stack.
            final ActivityRecord r = topRunningActivityLocked();
            mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
            mStackSupervisor.moveFocusableActivityToTop(r, reason);

            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
            if (noAnimation) {
@@ -5223,11 +5204,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
            if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
            // We only need to adjust focused stack if this stack is in focus and we are not in the
            // process of moving the task to the top of the stack that will be focused.
            if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
            if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP
                    && mStackSupervisor.isTopDisplayFocusedStack(this)) {
                String myReason = reason + " leftTaskHistoryEmpty";
                if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
                    mStackSupervisor.moveHomeStackToFront(myReason);
                    getDisplay().moveHomeStackToFront(myReason);
                }
            }
            if (isAttached()) {
Loading