Fix NPE in WakeLock#finalize for unit test

The stubbed method of "mock(PowerManager.WakeLock.class)" will
lose effect after clearInlineMocks. And then finalizer runs
the real method finalize() that cause NPE because the mocked
object didn't initialize fields.

Bug: 219640050
Test: atest WmTests

Change-Id: If8ee4fbc98c9e33d6ab6ba75a65ba177fa06f09c
This commit is contained in:
Riddle Hsu
2022-03-02 22:14:20 -06:00
parent c67b2ca345
commit b5b32d479d
2 changed files with 19 additions and 3 deletions

View File

@@ -267,7 +267,8 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
@Test
public void testUpdateSleep() {
doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
mSupervisor.mGoingToSleepWakeLock =
mSystemServicesTestRule.createStubbedWakeLock(true /* needVerification */);
final Task rootHomeTask = mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
final ActivityRecord homeActivity = new ActivityBuilder(mAtm).setTask(rootHomeTask).build();
final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();

View File

@@ -102,6 +102,10 @@ public class SystemServicesTestRule implements TestRule {
static int sNextTaskId = 100;
private static final int[] TEST_USER_PROFILE_IDS = {};
/** Use a real static object so there won't be NPE in finalize() after clearInlineMocks(). */
private static final PowerManager.WakeLock sWakeLock = getInstrumentation().getContext()
.getSystemService(PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
private PowerManager.WakeLock mStubbedWakeLock;
private Description mDescription;
private Context mContext;
@@ -196,7 +200,8 @@ public class SystemServicesTestRule implements TestRule {
// Prevent "WakeLock finalized while still held: SCREEN_FROZEN".
final PowerManager pm = mock(PowerManager.class);
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
doReturn(mock(PowerManager.WakeLock.class)).when(pm).newWakeLock(anyInt(), anyString());
mStubbedWakeLock = createStubbedWakeLock(false /* needVerification */);
doReturn(mStubbedWakeLock).when(pm).newWakeLock(anyInt(), anyString());
// DisplayManagerInternal
final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
@@ -403,6 +408,16 @@ public class SystemServicesTestRule implements TestRule {
return mPowerManagerWrapper;
}
/** Creates a no-op wakelock object. */
PowerManager.WakeLock createStubbedWakeLock(boolean needVerification) {
if (needVerification) {
return mock(PowerManager.WakeLock.class, Mockito.withSettings()
.spiedInstance(sWakeLock).defaultAnswer(Mockito.RETURNS_DEFAULTS));
}
return mock(PowerManager.WakeLock.class, Mockito.withSettings()
.spiedInstance(sWakeLock).stubOnly());
}
void setSurfaceFactory(Supplier<Surface> factory) {
mSurfaceFactory = factory;
}
@@ -558,7 +573,7 @@ public class SystemServicesTestRule implements TestRule {
// unit test version does not handle launch wake lock
doNothing().when(this).acquireLaunchWakelock();
mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
mLaunchingActivityWakeLock = mStubbedWakeLock;
initialize();