diff options
7 files changed, 82 insertions, 9 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 70a23cdf106b..1a9e75b31e62 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2412,6 +2412,7 @@ package android.service.dreams { public abstract class DreamOverlayService extends android.app.Service { ctor public DreamOverlayService(); method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); + method public void onEndDream(); method public abstract void onStartDream(@NonNull android.view.WindowManager.LayoutParams); method public final void requestExit(); method public final boolean shouldShowComplications(); diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java index 6e8198ba0cd1..bf5b970311d0 100644 --- a/core/java/android/service/dreams/DreamOverlayService.java +++ b/core/java/android/service/dreams/DreamOverlayService.java @@ -51,6 +51,11 @@ public abstract class DreamOverlayService extends Service { } @Override + public void endDream() { + onEndDream(); + } + + @Override public void wakeUp() { onWakeUp(() -> { try { @@ -83,13 +88,22 @@ public abstract class DreamOverlayService extends Service { /** * This method is overridden by implementations to handle when the dream has been requested - * to wakeup. This allows any overlay animations to run. + * to wakeup. This allows any overlay animations to run. By default, the method will invoke + * the callback immediately. * * @param onCompleteCallback The callback to trigger to notify the dream service that the * overlay has completed waking up. * @hide */ public void onWakeUp(@NonNull Runnable onCompleteCallback) { + onCompleteCallback.run(); + } + + /** + * This method is overridden by implementations to handle when the dream has ended. There may + * be earlier signals leading up to this step, such as @{@link #onWakeUp(Runnable)}. + */ + public void onEndDream() { } /** diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 8b9852a8f1b7..d3788862b6c0 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -297,14 +297,20 @@ public class DreamService extends Service implements Window.Callback { } public void addConsumer(Consumer<IDreamOverlay> consumer) { - mConsumers.add(consumer); - if (mOverlay != null) { - consumer.accept(mOverlay); - } + execute(() -> { + mConsumers.add(consumer); + if (mOverlay != null) { + consumer.accept(mOverlay); + } + }); } public void removeConsumer(Consumer<IDreamOverlay> consumer) { - mConsumers.remove(consumer); + execute(() -> mConsumers.remove(consumer)); + } + + public void clearConsumers() { + execute(() -> mConsumers.clear()); } } @@ -1383,6 +1389,17 @@ public class DreamService extends Service implements Window.Callback { @Override public void onViewDetachedFromWindow(View v) { + if (mOverlayConnection != null) { + mOverlayConnection.addConsumer(overlay -> { + try { + overlay.endDream(); + } catch (RemoteException e) { + Log.e(mTag, "could not inform overlay of dream end:" + e); + } + }); + mOverlayConnection.clearConsumers(); + } + if (mActivity == null || !mActivity.isChangingConfigurations()) { // Only stop the dream if the view is not detached by relaunching // activity for configuration changes. It is important to also clear @@ -1391,9 +1408,6 @@ public class DreamService extends Service implements Window.Callback { mActivity = null; finish(); } - if (mOverlayConnection != null && mDreamStartOverlayConsumer != null) { - mOverlayConnection.removeConsumer(mDreamStartOverlayConsumer); - } } }); } diff --git a/core/java/android/service/dreams/IDreamOverlay.aidl b/core/java/android/service/dreams/IDreamOverlay.aidl index 7aeceb2ce538..0e4bd3bd547b 100644 --- a/core/java/android/service/dreams/IDreamOverlay.aidl +++ b/core/java/android/service/dreams/IDreamOverlay.aidl @@ -41,4 +41,7 @@ interface IDreamOverlay { /** Called when the dream is waking, to do any exit animations */ void wakeUp(); + + /** Called when the dream has ended. */ + void endDream(); } diff --git a/core/java/com/android/internal/util/ObservableServiceConnection.java b/core/java/com/android/internal/util/ObservableServiceConnection.java index 3165d293bd91..45256fd26cba 100644 --- a/core/java/com/android/internal/util/ObservableServiceConnection.java +++ b/core/java/com/android/internal/util/ObservableServiceConnection.java @@ -165,6 +165,13 @@ public class ObservableServiceConnection<T> implements ServiceConnection { } /** + * Executes code on the executor specified at construction. + */ + public void execute(Runnable runnable) { + mExecutor.execute(runnable); + } + + /** * Initiate binding to the service. * * @return {@code true} if initiating binding succeed, {@code false} if the binding failed or diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index a9a9caed314b..dd01be0ef031 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -208,6 +208,13 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ }); } + @Override + public void onEndDream() { + mExecutor.execute(() -> { + resetCurrentDreamOverlayLocked(); + }); + } + private Lifecycle.State getCurrentStateLocked() { return mLifecycleRegistry.getCurrentState(); } @@ -291,6 +298,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamOverlayContainerViewController = null; mDreamOverlayTouchMonitor = null; + mWindow = null; mStarted = false; } } 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 4568d1e9b3bd..3b8bb8089910 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java @@ -234,6 +234,32 @@ public class DreamOverlayServiceTest extends SysuiTestCase { } @Test + public void testOnEndDream() throws RemoteException { + 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, + LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/); + mMainExecutor.runAllReady(); + + // Verify view added. + verify(mWindowManager).addView(mViewCaptor.capture(), any()); + + // Service destroyed. + mService.onEndDream(); + mMainExecutor.runAllReady(); + + // Verify view removed. + verify(mWindowManager).removeView(mViewCaptor.getValue()); + + // Verify state correctly set. + verify(mStateController).setOverlayActive(false); + verify(mStateController).setLowLightActive(false); + verify(mStateController).setEntryAnimationsFinished(false); + } + + @Test public void testDestroy() throws RemoteException { final IBinder proxy = mService.onBind(new Intent()); final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy); |