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

Commit d02eb8c7 authored by Louis Chang's avatar Louis Chang
Browse files

Fix NPE when starting activity while no focused task

NexusLauncher was not started when FallbackHome finished itself
because activities was prevented to be resumed while display is
sleeping. So, NPE was thrown while starting an activity because
there was no focused task in the display since FallbackHome
activity was removed from the task and all tasks were also removed.

The activities should still be able to be resumed when calling
resumeTop methods explicitly (even when display is sleeping).

For the original issue of bubble activities, the activities in
secondary display can be prevented from starting by evaluating
keyguard-going-away state for default display only.

Bug: 164572568
Bug: 160338354
Test: atest ActivityStackTests

Change-Id: Ica58b7e8c93e7aa688b335d1ecf7464bc8450e30
parent a437988c
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -1712,8 +1712,9 @@ class ActivityStarter {
        mRootWindowContainer.startPowerModeLaunchIfNeeded(
        mRootWindowContainer.startPowerModeLaunchIfNeeded(
                false /* forceSend */, mStartActivity);
                false /* forceSend */, mStartActivity);


        mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
        mTargetStack.startActivityLocked(mStartActivity,
                newTask, mKeepCurTransition, mOptions);
                topStack != null ? topStack.getTopNonFinishingActivity() : null, newTask,
                mKeepCurTransition, mOptions);
        if (mDoResume) {
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
                    mStartActivity.getTask().topRunningActivityLocked();
+0 −4
Original line number Original line Diff line number Diff line
@@ -2289,10 +2289,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>


        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            final DisplayContent display = getChildAt(displayNdx);
            final DisplayContent display = getChildAt(displayNdx);
            if (display.shouldSleep()) {
                continue;
            }

            final boolean curResult = result;
            final boolean curResult = result;
            boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas(
            boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas(
                    (taskDisplayArea, resumed) -> {
                    (taskDisplayArea, resumed) -> {
+6 −2
Original line number Original line Diff line number Diff line
@@ -6353,7 +6353,7 @@ class Task extends WindowContainer<WindowContainer> {
        return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
        return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
    }
    }


    void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
    void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
        Task rTask = r.getTask();
        Task rTask = r.getTask();
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
@@ -7589,7 +7589,11 @@ class Task extends WindowContainer<WindowContainer> {
        // Do not sleep activities in this stack if we're marked as focused and the keyguard
        // Do not sleep activities in this stack if we're marked as focused and the keyguard
        // is in the process of going away.
        // is in the process of going away.
        if (isFocusedStackOnDisplay()
        if (isFocusedStackOnDisplay()
                && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
                && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()
                // Avoid resuming activities on secondary displays since we don't want bubble
                // activities to be resumed while bubble is still collapsed.
                // TODO(b/113840485): Having keyguard going away state for secondary displays.
                && display.isDefaultDisplay) {
            return false;
            return false;
        }
        }


+11 −6
Original line number Original line Diff line number Diff line
@@ -1202,19 +1202,22 @@ public class ActivityStackTests extends WindowTestsBase {
    @Test
    @Test
    public void testShouldSleepActivities() {
    public void testShouldSleepActivities() {
        // When focused activity and keyguard is going away, we should not sleep regardless
        // When focused activity and keyguard is going away, we should not sleep regardless
        // of the display state
        // of the display state, but keyguard-going-away should only take effects on default
        // display since there is no keyguard on secondary displays (yet).
        verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
        verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
                true /* displaySleeping */, false /* expected*/);
                true /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
        verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
                true /* displaySleeping */, false /* isDefaultDisplay */, true /* expected */);


        // When not the focused stack, defer to display sleeping state.
        // When not the focused stack, defer to display sleeping state.
        verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/,
        verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/,
                true /* displaySleeping */, true /* expected*/);
                true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);


        // If keyguard is going away, defer to the display sleeping state.
        // If keyguard is going away, defer to the display sleeping state.
        verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
        verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
                true /* displaySleeping */, true /* expected*/);
                true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);
        verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
        verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
                false /* displaySleeping */, false /* expected*/);
                false /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
    }
    }


    @Test
    @Test
@@ -1423,9 +1426,11 @@ public class ActivityStackTests extends WindowTestsBase {
    }
    }


    private void verifyShouldSleepActivities(boolean focusedStack,
    private void verifyShouldSleepActivities(boolean focusedStack,
            boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
            boolean keyguardGoingAway, boolean displaySleeping, boolean isDefaultDisplay,
            boolean expected) {
        final DisplayContent display = mock(DisplayContent.class);
        final DisplayContent display = mock(DisplayContent.class);
        final KeyguardController keyguardController = mSupervisor.getKeyguardController();
        final KeyguardController keyguardController = mSupervisor.getKeyguardController();
        display.isDefaultDisplay = isDefaultDisplay;


        doReturn(display).when(mStack).getDisplay();
        doReturn(display).when(mStack).getDisplay();
        doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
        doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
+0 −18
Original line number Original line Diff line number Diff line
@@ -915,24 +915,6 @@ public class RootActivityContainerTests extends WindowTestsBase {
        assertEquals(taskDisplayArea.getTopStack(), taskDisplayArea.getRootHomeTask());
        assertEquals(taskDisplayArea.getTopStack(), taskDisplayArea.getRootHomeTask());
    }
    }


    @Test
    public void testResumeFocusedStackOnSleepingDisplay() {
        // Create an activity on secondary display.
        final TestDisplayContent secondDisplay = addNewDisplayContentAt(
                DisplayContent.POSITION_TOP);
        final Task stack = secondDisplay.getDefaultTaskDisplayArea()
                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        final ActivityRecord activity = new ActivityBuilder(mAtm).setStack(stack).build();
        spyOn(activity);
        spyOn(stack);

        // Cannot resumed activities on secondary display if the display should sleep.
        doReturn(true).when(secondDisplay).shouldSleep();
        mRootWindowContainer.resumeFocusedStacksTopActivities();
        verify(stack, never()).resumeTopActivityUncheckedLocked(any(), any());
        verify(activity, never()).makeActiveIfNeeded(any());
    }

    /**
    /**
     * Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
     * Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
     * info for test cases.
     * info for test cases.