diff options
4 files changed, 100 insertions, 1 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index 3ee0cad32097..2160744c6803 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -88,16 +88,20 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ } }; + private DreamOverlayStateController mStateController; + @Inject public DreamOverlayService( Context context, @Main Executor executor, DreamOverlayComponent.Factory dreamOverlayComponentFactory, + DreamOverlayStateController stateController, KeyguardUpdateMonitor keyguardUpdateMonitor) { mContext = context; mExecutor = executor; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback); + mStateController = stateController; final DreamOverlayComponent component = dreamOverlayComponentFactory.create(mViewModelStore, mHost); @@ -118,6 +122,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ setCurrentState(Lifecycle.State.DESTROYED); final WindowManager windowManager = mContext.getSystemService(WindowManager.class); windowManager.removeView(mWindow.getDecorView()); + mStateController.setOverlayActive(false); super.onDestroy(); } @@ -127,6 +132,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mExecutor.execute(() -> { addOverlayWindowLocked(layoutParams); setCurrentState(Lifecycle.State.RESUMED); + mStateController.setOverlayActive(true); }); } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java index e83884819f70..3e4ae57000f1 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java @@ -16,6 +16,8 @@ package com.android.systemui.dreams; +import android.util.Log; + import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; @@ -30,6 +32,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.function.Consumer; import javax.inject.Inject; @@ -41,6 +44,16 @@ import javax.inject.Inject; @SysUISingleton public class DreamOverlayStateController implements CallbackController<DreamOverlayStateController.Callback> { + private static final String TAG = "DreamOverlayStateCtlr"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + public static final int STATE_DREAM_OVERLAY_ACTIVE = 1 << 0; + + private static final int OP_CLEAR_STATE = 1; + private static final int OP_SET_STATE = 2; + + private int mState; + /** * Callback for dream overlay events. */ @@ -50,6 +63,12 @@ public class DreamOverlayStateController implements */ default void onComplicationsChanged() { } + + /** + * Called when the dream overlay state changes. + */ + default void onStateChanged() { + } } private final Executor mExecutor; @@ -92,6 +111,14 @@ public class DreamOverlayStateController implements return Collections.unmodifiableCollection(mComplications); } + private void notifyCallbacks(Consumer<Callback> callbackConsumer) { + mExecutor.execute(() -> { + for (Callback callback : mCallbacks) { + callbackConsumer.accept(callback); + } + }); + } + @Override public void addCallback(@NonNull Callback callback) { mExecutor.execute(() -> { @@ -117,4 +144,40 @@ public class DreamOverlayStateController implements mCallbacks.remove(callback); }); } + + /** + * Returns whether the overlay is active. + * @return {@code true} if overlay is active, {@code false} otherwise. + */ + public boolean isOverlayActive() { + return containsState(STATE_DREAM_OVERLAY_ACTIVE); + } + + private boolean containsState(int state) { + return (mState & state) != 0; + } + + private void modifyState(int op, int state) { + final int existingState = mState; + switch (op) { + case OP_CLEAR_STATE: + mState &= ~state; + break; + case OP_SET_STATE: + mState |= state; + break; + } + + if (existingState != mState) { + notifyCallbacks(callback -> callback.onStateChanged()); + } + } + + /** + * Sets whether the overlay is active. + * @param active {@code true} if overlay is active, {@code false} otherwise. + */ + public void setOverlayActive(boolean active) { + modifyState(active ? OP_SET_STATE : OP_CLEAR_STATE, STATE_DREAM_OVERLAY_ACTIVE); + } } 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 b3b5fa509105..d5bd67adcf09 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java @@ -91,6 +91,9 @@ public class DreamOverlayServiceTest extends SysuiTestCase { @Mock DreamOverlayTouchMonitor mDreamOverlayTouchMonitor; + @Mock + DreamOverlayStateController mStateController; + DreamOverlayService mService; @@ -115,6 +118,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase { mService = new DreamOverlayService(mContext, mMainExecutor, mDreamOverlayComponentFactory, + mStateController, mKeyguardUpdateMonitor); final IBinder proxy = mService.onBind(new Intent()); final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java index 7d0833db7ae4..1859569bafe5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java @@ -16,9 +16,12 @@ package com.android.systemui.dreams; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -35,6 +38,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.Collection; @@ -56,7 +60,29 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { } @Test - public void testCallback() throws Exception { + public void testStateChange() { + final DreamOverlayStateController stateController = new DreamOverlayStateController( + mExecutor); + stateController.addCallback(mCallback); + stateController.setOverlayActive(true); + mExecutor.runAllReady(); + + verify(mCallback).onStateChanged(); + assertThat(stateController.isOverlayActive()).isTrue(); + + Mockito.clearInvocations(mCallback); + stateController.setOverlayActive(true); + mExecutor.runAllReady(); + verify(mCallback, never()).onStateChanged(); + + stateController.setOverlayActive(false); + mExecutor.runAllReady(); + verify(mCallback).onStateChanged(); + assertThat(stateController.isOverlayActive()).isFalse(); + } + + @Test + public void testCallback() { final DreamOverlayStateController stateController = new DreamOverlayStateController( mExecutor); stateController.addCallback(mCallback); |