Loading packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +23 −3 Original line number Diff line number Diff line Loading @@ -221,7 +221,14 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamOverlayTouchMonitor.init(); mStateController.setShouldShowComplications(shouldShowComplications()); addOverlayWindowLocked(layoutParams); // If we are not able to add the overlay window, reset the overlay. if (!addOverlayWindowLocked(layoutParams)) { resetCurrentDreamOverlayLocked(); return; } setCurrentStateLocked(Lifecycle.State.RESUMED); mStateController.setOverlayActive(true); final ComponentName dreamComponent = getDreamComponent(); Loading Loading @@ -267,7 +274,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ * @param layoutParams The {@link android.view.WindowManager.LayoutParams} which allow inserting * into the dream window. */ private void addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) { private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) { mWindow = new PhoneWindow(mContext); // Default to SystemUI name for TalkBack. mWindow.setTitle(""); Loading @@ -292,9 +299,22 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ // risk an IllegalStateException in some cases when setting the container view as the // window's content view and the container view hasn't been properly removed previously). removeContainerViewFromParentLocked(); mWindow.setContentView(mDreamOverlayContainerViewController.getContainerView()); // It is possible that a dream's window (and the dream as a whole) is no longer valid by // the time the overlay service processes the dream. This can happen for example if // another dream is started immediately after the existing dream begins. In this case, the // overlay service should identify the situation through the thrown exception and tear down // the overlay. try { mWindowManager.addView(mWindow.getDecorView(), mWindow.getAttributes()); return true; } catch (WindowManager.BadTokenException exception) { Log.e(TAG, "Dream activity window invalid: " + layoutParams.packageName, exception); return false; } } private void removeContainerViewFromParentLocked() { Loading packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; Loading Loading @@ -231,6 +232,31 @@ public class DreamOverlayServiceTest extends SysuiTestCase { verify(mWindowManager).addView(any(), any()); } // Validates that {@link DreamOverlayService} properly handles the case where the dream's // window is no longer valid by the time start is called. @Test public void testInvalidWindowAddStart() throws Exception { final IDreamOverlayClient client = getClient(); doThrow(new WindowManager.BadTokenException()).when(mWindowManager).addView(any(), any()); // Inform the overlay service of dream starting. client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT, false /*shouldShowComplication*/); mMainExecutor.runAllReady(); verify(mWindowManager).addView(any(), any()); verify(mStateController).setOverlayActive(false); verify(mStateController).setLowLightActive(false); verify(mStateController).setEntryAnimationsFinished(false); verify(mStateController, never()).setOverlayActive(true); verify(mUiEventLogger, never()).log( DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START); verify(mDreamOverlayCallbackController, never()).onStartDream(); } @Test public void testDreamOverlayContainerViewControllerInitialized() throws Exception { final IDreamOverlayClient client = getClient(); Loading Loading
packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +23 −3 Original line number Diff line number Diff line Loading @@ -221,7 +221,14 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamOverlayTouchMonitor.init(); mStateController.setShouldShowComplications(shouldShowComplications()); addOverlayWindowLocked(layoutParams); // If we are not able to add the overlay window, reset the overlay. if (!addOverlayWindowLocked(layoutParams)) { resetCurrentDreamOverlayLocked(); return; } setCurrentStateLocked(Lifecycle.State.RESUMED); mStateController.setOverlayActive(true); final ComponentName dreamComponent = getDreamComponent(); Loading Loading @@ -267,7 +274,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ * @param layoutParams The {@link android.view.WindowManager.LayoutParams} which allow inserting * into the dream window. */ private void addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) { private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) { mWindow = new PhoneWindow(mContext); // Default to SystemUI name for TalkBack. mWindow.setTitle(""); Loading @@ -292,9 +299,22 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ // risk an IllegalStateException in some cases when setting the container view as the // window's content view and the container view hasn't been properly removed previously). removeContainerViewFromParentLocked(); mWindow.setContentView(mDreamOverlayContainerViewController.getContainerView()); // It is possible that a dream's window (and the dream as a whole) is no longer valid by // the time the overlay service processes the dream. This can happen for example if // another dream is started immediately after the existing dream begins. In this case, the // overlay service should identify the situation through the thrown exception and tear down // the overlay. try { mWindowManager.addView(mWindow.getDecorView(), mWindow.getAttributes()); return true; } catch (WindowManager.BadTokenException exception) { Log.e(TAG, "Dream activity window invalid: " + layoutParams.packageName, exception); return false; } } private void removeContainerViewFromParentLocked() { Loading
packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; Loading Loading @@ -231,6 +232,31 @@ public class DreamOverlayServiceTest extends SysuiTestCase { verify(mWindowManager).addView(any(), any()); } // Validates that {@link DreamOverlayService} properly handles the case where the dream's // window is no longer valid by the time start is called. @Test public void testInvalidWindowAddStart() throws Exception { final IDreamOverlayClient client = getClient(); doThrow(new WindowManager.BadTokenException()).when(mWindowManager).addView(any(), any()); // Inform the overlay service of dream starting. client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT, false /*shouldShowComplication*/); mMainExecutor.runAllReady(); verify(mWindowManager).addView(any(), any()); verify(mStateController).setOverlayActive(false); verify(mStateController).setLowLightActive(false); verify(mStateController).setEntryAnimationsFinished(false); verify(mStateController, never()).setOverlayActive(true); verify(mUiEventLogger, never()).log( DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START); verify(mDreamOverlayCallbackController, never()).onStartDream(); } @Test public void testDreamOverlayContainerViewControllerInitialized() throws Exception { final IDreamOverlayClient client = getClient(); Loading