Merge "Improve DreamOverlayService thread safety." into tm-qpr-dev
This commit is contained in:
@@ -90,13 +90,15 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
new KeyguardUpdateMonitorCallback() {
|
||||
@Override
|
||||
public void onShadeExpandedChanged(boolean expanded) {
|
||||
if (mLifecycleRegistry.getCurrentState() != Lifecycle.State.RESUMED
|
||||
&& mLifecycleRegistry.getCurrentState() != Lifecycle.State.STARTED) {
|
||||
return;
|
||||
}
|
||||
mExecutor.execute(() -> {
|
||||
if (getCurrentStateLocked() != Lifecycle.State.RESUMED
|
||||
&& getCurrentStateLocked() != Lifecycle.State.STARTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLifecycleRegistry.setCurrentState(
|
||||
expanded ? Lifecycle.State.STARTED : Lifecycle.State.RESUMED);
|
||||
setCurrentStateLocked(
|
||||
expanded ? Lifecycle.State.STARTED : Lifecycle.State.RESUMED);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -146,29 +148,30 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
() -> mExecutor.execute(DreamOverlayService.this::requestExit);
|
||||
mDreamOverlayComponent = dreamOverlayComponentFactory.create(viewModelStore, host);
|
||||
mLifecycleRegistry = mDreamOverlayComponent.getLifecycleRegistry();
|
||||
setCurrentState(Lifecycle.State.CREATED);
|
||||
}
|
||||
|
||||
private void setCurrentState(Lifecycle.State state) {
|
||||
mExecutor.execute(() -> mLifecycleRegistry.setCurrentState(state));
|
||||
mExecutor.execute(() -> setCurrentStateLocked(Lifecycle.State.CREATED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
mKeyguardUpdateMonitor.removeCallback(mKeyguardCallback);
|
||||
setCurrentState(Lifecycle.State.DESTROYED);
|
||||
|
||||
resetCurrentDreamOverlay();
|
||||
mExecutor.execute(() -> {
|
||||
setCurrentStateLocked(Lifecycle.State.DESTROYED);
|
||||
|
||||
resetCurrentDreamOverlayLocked();
|
||||
|
||||
mDestroyed = true;
|
||||
});
|
||||
|
||||
mDestroyed = true;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
|
||||
setCurrentState(Lifecycle.State.STARTED);
|
||||
|
||||
mExecutor.execute(() -> {
|
||||
setCurrentStateLocked(Lifecycle.State.STARTED);
|
||||
|
||||
mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
|
||||
|
||||
if (mDestroyed) {
|
||||
@@ -181,7 +184,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
// Reset the current dream overlay before starting a new one. This can happen
|
||||
// when two dreams overlap (briefly, for a smoother dream transition) and both
|
||||
// dreams are bound to the dream overlay service.
|
||||
resetCurrentDreamOverlay();
|
||||
resetCurrentDreamOverlayLocked();
|
||||
}
|
||||
|
||||
mDreamOverlayContainerViewController =
|
||||
@@ -191,7 +194,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
|
||||
mStateController.setShouldShowComplications(shouldShowComplications());
|
||||
addOverlayWindowLocked(layoutParams);
|
||||
setCurrentState(Lifecycle.State.RESUMED);
|
||||
setCurrentStateLocked(Lifecycle.State.RESUMED);
|
||||
mStateController.setOverlayActive(true);
|
||||
final ComponentName dreamComponent = getDreamComponent();
|
||||
mStateController.setLowLightActive(
|
||||
@@ -202,6 +205,14 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
});
|
||||
}
|
||||
|
||||
private Lifecycle.State getCurrentStateLocked() {
|
||||
return mLifecycleRegistry.getCurrentState();
|
||||
}
|
||||
|
||||
private void setCurrentStateLocked(Lifecycle.State state) {
|
||||
mLifecycleRegistry.setCurrentState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts {@link Window} to host the dream overlay into the dream's parent window. Must be
|
||||
* called from the main executing thread. The window attributes closely mirror those that are
|
||||
@@ -231,13 +242,13 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
// Make extra sure the container view has been removed from its old parent (otherwise we
|
||||
// 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).
|
||||
removeContainerViewFromParent();
|
||||
removeContainerViewFromParentLocked();
|
||||
mWindow.setContentView(mDreamOverlayContainerViewController.getContainerView());
|
||||
|
||||
mWindowManager.addView(mWindow.getDecorView(), mWindow.getAttributes());
|
||||
}
|
||||
|
||||
private void removeContainerViewFromParent() {
|
||||
private void removeContainerViewFromParentLocked() {
|
||||
View containerView = mDreamOverlayContainerViewController.getContainerView();
|
||||
if (containerView == null) {
|
||||
return;
|
||||
@@ -250,7 +261,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
parentView.removeView(containerView);
|
||||
}
|
||||
|
||||
private void resetCurrentDreamOverlay() {
|
||||
private void resetCurrentDreamOverlayLocked() {
|
||||
if (mStarted && mWindow != null) {
|
||||
mWindowManager.removeView(mWindow.getDecorView());
|
||||
}
|
||||
|
||||
@@ -274,26 +274,30 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@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);
|
||||
|
||||
// Destroy the service.
|
||||
mService.onDestroy();
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
false /*shouldShowComplication*/);
|
||||
|
||||
// Destroy the service.
|
||||
mService.onDestroy();
|
||||
|
||||
// Run executor tasks.
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
verify(mWindowManager, never()).addView(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNeverRemoveDecorViewIfNotAdded() {
|
||||
// Service destroyed before dream started.
|
||||
mService.onDestroy();
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
verify(mWindowManager, never()).removeView(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetCurrentOverlayWhenConnectedToNewDream() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
|
||||
Reference in New Issue
Block a user