diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index ebc766635733d..dfbb0c7c16243 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -65,6 +65,9 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ // A reference to the {@link Window} used to hold the dream overlay. private Window mWindow; + // True if the service has been destroyed. + private boolean mDestroyed; + private final Complication.Host mHost = new Complication.Host() { @Override public void requestExitDream() { @@ -134,6 +137,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mPreviewComplication.setDreamLabel(null); mStateController.removeComplication(mPreviewComplication); mStateController.setPreviewMode(false); + mDestroyed = true; super.onDestroy(); } @@ -141,6 +145,11 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) { setCurrentState(Lifecycle.State.STARTED); mExecutor.execute(() -> { + if (mDestroyed) { + // The task could still be executed after the service has been destroyed. Bail if + // that is the case. + return; + } mStateController.setShouldShowComplications(shouldShowComplications()); mStateController.setPreviewMode(isPreviewMode()); if (isPreviewMode()) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java index 35fda1392512e..7d7ccb462b3ef 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java @@ -19,6 +19,7 @@ package com.android.systemui.dreams; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -222,4 +223,25 @@ public class DreamOverlayServiceTest extends SysuiTestCase { verify(mLifecycleRegistry).setCurrentState(Lifecycle.State.DESTROYED); verify(mStateController).setOverlayActive(false); } + + @Test + public void testDecorViewNotAddedToWindowAfterDestroy() throws Exception { + when(mDreamOverlayContainerView.getParent()) + .thenReturn(mDreamOverlayContainerViewParent) + .thenReturn(null); + + final IBinder proxy = mService.onBind(new Intent()); + final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy); + + // Inform the overlay service of dream starting. + overlay.startDream(mWindowParams, mDreamOverlayCallback); + + // Destroy the service. + mService.onDestroy(); + + // Run executor tasks. + mMainExecutor.runAllReady(); + + verify(mWindowManager, never()).addView(any(), any()); + } }