Merge "Remove Dream Overlay when Dream Window detaches." into tm-qpr-dev

This commit is contained in:
Bryce Lee
2023-01-20 03:38:02 +00:00
committed by Android (Google) Code Review
7 changed files with 82 additions and 9 deletions

View File

@@ -2411,6 +2411,7 @@ package android.service.dreams {
public abstract class DreamOverlayService extends android.app.Service { public abstract class DreamOverlayService extends android.app.Service {
ctor public DreamOverlayService(); ctor public DreamOverlayService();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); 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 abstract void onStartDream(@NonNull android.view.WindowManager.LayoutParams);
method public final void requestExit(); method public final void requestExit();
method public final boolean shouldShowComplications(); method public final boolean shouldShowComplications();

View File

@@ -50,6 +50,11 @@ public abstract class DreamOverlayService extends Service {
onStartDream(layoutParams); onStartDream(layoutParams);
} }
@Override
public void endDream() {
onEndDream();
}
@Override @Override
public void wakeUp() { public void wakeUp() {
onWakeUp(() -> { onWakeUp(() -> {
@@ -83,13 +88,22 @@ public abstract class DreamOverlayService extends Service {
/** /**
* This method is overridden by implementations to handle when the dream has been requested * 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 * @param onCompleteCallback The callback to trigger to notify the dream service that the
* overlay has completed waking up. * overlay has completed waking up.
* @hide * @hide
*/ */
public void onWakeUp(@NonNull Runnable onCompleteCallback) { 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() {
} }
/** /**

View File

@@ -297,14 +297,20 @@ public class DreamService extends Service implements Window.Callback {
} }
public void addConsumer(Consumer<IDreamOverlay> consumer) { public void addConsumer(Consumer<IDreamOverlay> consumer) {
execute(() -> {
mConsumers.add(consumer); mConsumers.add(consumer);
if (mOverlay != null) { if (mOverlay != null) {
consumer.accept(mOverlay); consumer.accept(mOverlay);
} }
});
} }
public void removeConsumer(Consumer<IDreamOverlay> consumer) { 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 @Override
public void onViewDetachedFromWindow(View v) { 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()) { if (mActivity == null || !mActivity.isChangingConfigurations()) {
// Only stop the dream if the view is not detached by relaunching // Only stop the dream if the view is not detached by relaunching
// activity for configuration changes. It is important to also clear // activity for configuration changes. It is important to also clear
@@ -1391,9 +1408,6 @@ public class DreamService extends Service implements Window.Callback {
mActivity = null; mActivity = null;
finish(); finish();
} }
if (mOverlayConnection != null && mDreamStartOverlayConsumer != null) {
mOverlayConnection.removeConsumer(mDreamStartOverlayConsumer);
}
} }
}); });
} }

View File

@@ -41,4 +41,7 @@ interface IDreamOverlay {
/** Called when the dream is waking, to do any exit animations */ /** Called when the dream is waking, to do any exit animations */
void wakeUp(); void wakeUp();
/** Called when the dream has ended. */
void endDream();
} }

View File

@@ -164,6 +164,13 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
mFlags = flags; mFlags = flags;
} }
/**
* Executes code on the executor specified at construction.
*/
public void execute(Runnable runnable) {
mExecutor.execute(runnable);
}
/** /**
* Initiate binding to the service. * Initiate binding to the service.
* *

View File

@@ -208,6 +208,13 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
}); });
} }
@Override
public void onEndDream() {
mExecutor.execute(() -> {
resetCurrentDreamOverlayLocked();
});
}
private Lifecycle.State getCurrentStateLocked() { private Lifecycle.State getCurrentStateLocked() {
return mLifecycleRegistry.getCurrentState(); return mLifecycleRegistry.getCurrentState();
} }
@@ -291,6 +298,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
mDreamOverlayContainerViewController = null; mDreamOverlayContainerViewController = null;
mDreamOverlayTouchMonitor = null; mDreamOverlayTouchMonitor = null;
mWindow = null;
mStarted = false; mStarted = false;
} }
} }

View File

@@ -233,6 +233,32 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
verify(mStateController).setLowLightActive(true); verify(mStateController).setLowLightActive(true);
} }
@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 @Test
public void testDestroy() throws RemoteException { public void testDestroy() throws RemoteException {
final IBinder proxy = mService.onBind(new Intent()); final IBinder proxy = mService.onBind(new Intent());