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

Commit 21199bd9 authored by Filip Gruszczynski's avatar Filip Gruszczynski
Browse files

Run activity visibility adjustment even if there is no top running.

Ensuring visibility is triggered in unpredictable fashion, e.g. it can
be triggered by attachment of application. It can happen between an
activity stopping due to change of user, but before that operation is
finished and as a result the stopped activity will get marked as
visible even if we mark it as invisible in stop. Instead of trying the
activity as invisbile during stopping, we adjust the visibility ensuring
method to go through stack contents even if there is no top running
activity (because the top running activity is run by a different user)
and force the correct visibility.

Bug: 25958227

Change-Id: I4662667e8151fa25d947bacf33ba915389dd32e8
parent e920098f
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2113,7 +2113,9 @@ public class ActivityManager {
        public int[] taskIds;
        public String[] taskNames;
        public Rect[] taskBounds;
        public int[] taskUserIds;
        public int displayId;
        public int userId;

        @Override
        public int describeContents() {
@@ -2137,7 +2139,9 @@ public class ActivityManager {
                dest.writeInt(taskBounds[i].right);
                dest.writeInt(taskBounds[i].bottom);
            }
            dest.writeIntArray(taskUserIds);
            dest.writeInt(displayId);
            dest.writeInt(userId);
        }

        public void readFromParcel(Parcel source) {
@@ -2157,7 +2161,9 @@ public class ActivityManager {
            } else {
                taskBounds = null;
            }
            taskUserIds = source.createIntArray();
            displayId = source.readInt();
            userId = source.readInt();
        }

        public static final Creator<StackInfo> CREATOR = new Creator<StackInfo>() {
@@ -2183,6 +2189,7 @@ public class ActivityManager {
            sb.append(prefix); sb.append("Stack id="); sb.append(stackId);
                    sb.append(" bounds="); sb.append(bounds.toShortString());
                    sb.append(" displayId="); sb.append(displayId);
                    sb.append(" userId="); sb.append(userId);
                    sb.append("\n");
            prefix = prefix + "  ";
            for (int i = 0; i < taskIds.length; ++i) {
@@ -2191,6 +2198,7 @@ public class ActivityManager {
                        if (taskBounds != null) {
                            sb.append(" bounds="); sb.append(taskBounds[i].toShortString());
                        }
                        sb.append(" userId=").append(taskUserIds[i]);
                        sb.append("\n");
            }
            return sb.toString();
+18 −17
Original line number Diff line number Diff line
@@ -1424,16 +1424,15 @@ final class ActivityStack {
    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
            boolean preserveWindows) {
        ActivityRecord top = topRunningActivityLocked();
        if (top == null) {
            return;
        }
        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
                + " configChanges=0x" + Integer.toHexString(configChanges));
        if (top != null) {
            checkTranslucentActivityWaiting(top);
        }

        // If the top activity is not fullscreen, then we need to
        // make sure any activities under it are now visible.
        boolean aboveTop = true;
        boolean aboveTop = top != null;
        final boolean stackInvisible = !isStackVisibleLocked();
        boolean behindFullscreenActivity = stackInvisible;
        boolean noStackActivityResumed = (isInStackLocked(starting) == null);
@@ -1447,13 +1446,15 @@ final class ActivityStack {
                if (r.finishing) {
                    continue;
                }
                if (aboveTop && r != top) {
                final boolean isTop = r == top;
                if (aboveTop && !isTop) {
                    continue;
                }
                aboveTop = false;
                // mLaunchingBehind: Activities launching behind are at the back of the task stack
                // but must be drawn initially for the animation as though they were visible.
                if (!behindFullscreenActivity || r.mLaunchTaskBehind) {
                if ((!behindFullscreenActivity || r.mLaunchTaskBehind)
                        && okToShowLocked(r)) {
                    if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                            "Make visible? " + r + " finishing=" + r.finishing
                            + " state=" + r.state);
@@ -1464,7 +1465,7 @@ final class ActivityStack {
                    }

                    if (r.app == null || r.app.thread == null) {
                        if (makeVisibleAndRestartIfNeeded(starting, configChanges, top,
                        if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
                                noStackActivityResumed, r)) {
                            if (activityNdx >= activities.size()) {
                                // Record may be removed if its process needs to restart.
@@ -1474,18 +1475,19 @@ final class ActivityStack {
                            }
                        }
                    } else if (r.visible) {
                        if (alreadyVisible(r)) {
                        // If this activity is already visible, then there is nothing to do here.
                        if (handleAlreadyVisible(r)) {
                            noStackActivityResumed = false;
                        }
                    } else {
                        becomeVisible(starting, r);
                        makeVisible(starting, r);
                    }
                    // Aggregate current change flags.
                    configChanges |= r.configChangeFlags;
                    behindFullscreenActivity = updateBehindFullscreen(stackInvisible,
                            behindFullscreenActivity, task, r);
                } else {
                    becomeInvisible(stackInvisible, behindFullscreenActivity, r);
                    makeInvisible(stackInvisible, behindFullscreenActivity, r);
                }
            }
            if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
@@ -1516,12 +1518,12 @@ final class ActivityStack {
    }

    private boolean makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
            ActivityRecord top, boolean noStackActivityResumed, ActivityRecord r) {
            boolean isTop, boolean noStackActivityResumed, ActivityRecord r) {
        // We need to make sure the app is running if it's the top, or it is just made visible from
        // invisible. If the app is already visible, it must have died while it was visible. In this
        // case, we'll show the dead window but will not restart the app. Otherwise we could end up
        // thrashing.
        if (r == top || !r.visible) {
        if (isTop || !r.visible) {
            // This activity needs to be visible, but isn't even running...
            // get it started and resume if no other stack in this stack is resumed.
            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
@@ -1540,7 +1542,7 @@ final class ActivityStack {
        return false;
    }

    private void becomeInvisible(boolean stackInvisible, boolean behindFullscreenActivity,
    private void makeInvisible(boolean stackInvisible, boolean behindFullscreenActivity,
            ActivityRecord r) {
        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r + " finishing="
                + r.finishing + " state=" + r.state + " stackInvisible=" + stackInvisible
@@ -1606,7 +1608,7 @@ final class ActivityStack {
        return behindFullscreenActivity;
    }

    private void becomeVisible(ActivityRecord starting, ActivityRecord r) {
    private void makeVisible(ActivityRecord starting, ActivityRecord r) {
        // This activity is not currently visible, but is running. Tell it to become visible.
        r.visible = true;
        if (r.state != ActivityState.RESUMED && r != starting) {
@@ -1631,8 +1633,7 @@ final class ActivityStack {
        }
    }

    private boolean alreadyVisible(ActivityRecord r) {
        // If this activity is already visible, then there is nothing else to do here.
    private boolean handleAlreadyVisible(ActivityRecord r) {
        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Skipping: already visible at " + r);
        r.stopFreezingScreenLocked(false);
        try {
+5 −2
Original line number Diff line number Diff line
@@ -2702,7 +2702,6 @@ public final class ActivityStackSupervisor implements DisplayListener {
            Configuration config) {
        if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);

        ArrayList<ActivityRecord> stops = null;
        ArrayList<ActivityRecord> finishes = null;
        ArrayList<UserState> startingUsers = null;
        int NS = 0;
@@ -2756,7 +2755,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
        }

        // Atomically retrieve all of the other things to do.
        stops = processStoppingActivitiesLocked(true);
        final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(true);
        NS = stops != null ? stops.size() : 0;
        if ((NF = mFinishingActivities.size()) > 0) {
            finishes = new ArrayList<>(mFinishingActivities);
@@ -4304,12 +4303,14 @@ public final class ActivityStackSupervisor implements DisplayListener {
        mWindowManager.getStackBounds(stack.mStackId, info.bounds);
        info.displayId = Display.DEFAULT_DISPLAY;
        info.stackId = stack.mStackId;
        info.userId = stack.mCurrentUser;

        ArrayList<TaskRecord> tasks = stack.getAllTasks();
        final int numTasks = tasks.size();
        int[] taskIds = new int[numTasks];
        String[] taskNames = new String[numTasks];
        Rect[] taskBounds = new Rect[numTasks];
        int[] taskUserIds = new int[numTasks];
        for (int i = 0; i < numTasks; ++i) {
            final TaskRecord task = tasks.get(i);
            taskIds[i] = task.taskId;
@@ -4319,10 +4320,12 @@ public final class ActivityStackSupervisor implements DisplayListener {
                    : "unknown";
            taskBounds[i] = new Rect();
            mWindowManager.getTaskBounds(task.taskId, taskBounds[i]);
            taskUserIds[i] = task.userId;
        }
        info.taskIds = taskIds;
        info.taskNames = taskNames;
        info.taskBounds = taskBounds;
        info.taskUserIds = taskUserIds;
        return info;
    }