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

Commit 550ec7d7 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Fix that the top process is not cleared after device sleeps

Commit 8f7dd599 makes getTopApp lock-free by the field mTopApp.
And it is updated when the top activity is changed. When making
device sleep, the given top resumed activity is null and the
pausing activity is chosen. But there won't be next top activity
change to replace the mTopApp of previous pausing activity.
That causes the process stays on top state.

This change clears mTopApp when pausing the top activity for
sleeping. This also aligns the condition in OomAdjuster that if
the current top state is not PROCESS_STATE_TOP, there won't be
a top process.

Fixes: 171060345
Test: atest ActivityTaskManagerServiceTests#testUpdateSleep
      CtsStatsdAtomHostTestCases:ProcStateAtomTests#testTopSleeping
Change-Id: Ie96113ab4002a559a5af974f83b36f56f28ff438
parent a3eea61e
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -5572,7 +5572,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    }

    void updateTopApp(ActivityRecord topResumedActivity) {
        final ActivityRecord top = topResumedActivity != null ? topResumedActivity
        // If system is sleeping, use the given record (it should be null) because there won't be
        // the next resumed activity. Otherwise the process of pausing activity will keep with top
        // state even the activity has paused and stopped.
        final ActivityRecord top = mSleeping || topResumedActivity != null ? topResumedActivity
                // If there is no resumed activity, it will choose the pausing activity.
                : mRootWindowContainer.getTopResumedActivity();
        mTopApp = top != null ? top.app : null;
+35 −0
Original line number Diff line number Diff line
@@ -23,20 +23,24 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.PictureInPictureParams;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.EnterPipRequestedItem;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.IDisplayWindowListener;
@@ -252,5 +256,36 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
        assertEquals(Task.ActivityState.RESUMED, homeActivity.getState());
        assertEquals(homeActivity.app, mAtm.mInternal.getTopApp());
    }

    @Test
    public void testUpdateSleep() {
        doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
        mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
        final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        topActivity.setState(Task.ActivityState.RESUMED, "test");

        final Runnable assertTopNonSleeping = () -> {
            assertFalse(mAtm.mInternal.isSleeping());
            assertEquals(ActivityManager.PROCESS_STATE_TOP, mAtm.mInternal.getTopProcessState());
            assertEquals(topActivity.app, mAtm.mInternal.getTopApp());
        };
        assertTopNonSleeping.run();

        // Sleep all displays.
        mWm.mRoot.forAllDisplays(display -> doReturn(true).when(display).shouldSleep());
        mAtm.updateSleepIfNeededLocked();

        assertEquals(Task.ActivityState.PAUSING, topActivity.getState());
        assertTrue(mAtm.mInternal.isSleeping());
        assertEquals(ActivityManager.PROCESS_STATE_TOP_SLEEPING,
                mAtm.mInternal.getTopProcessState());
        assertNull(mAtm.mInternal.getTopApp());

        // Wake all displays.
        mWm.mRoot.forAllDisplays(display -> doReturn(false).when(display).shouldSleep());
        mAtm.updateSleepIfNeededLocked();

        assertTopNonSleeping.run();
    }
}