diff options
| author | 2022-01-30 19:35:10 +0000 | |
|---|---|---|
| committer | 2022-01-30 19:35:10 +0000 | |
| commit | 37e95f0bf11cb570cdc84c714d5b51eb45800900 (patch) | |
| tree | 6162f6cb28bf2234d82bc96e099eaeda189c24d9 | |
| parent | 2cf963680651ee77c9397e619d73a5f74389f492 (diff) | |
| parent | 294de89b2a6010f3289042688436ceea02b6a1ac (diff) | |
Merge "Media Complication Introduction."
11 files changed, 582 insertions, 4 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java index 031174092703..41287b60fbf8 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java @@ -31,6 +31,7 @@ import com.android.systemui.globalactions.GlobalActionsComponent; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.dagger.KeyguardModule; import com.android.systemui.log.SessionTracker; +import com.android.systemui.media.dream.MediaDreamSentinel; import com.android.systemui.media.systemsounds.HomeSoundEffectController; import com.android.systemui.power.PowerUI; import com.android.systemui.privacy.television.TvOngoingPrivacyChip; @@ -226,4 +227,11 @@ public abstract class SystemUIBinder { @ClassKey(SmartSpaceComplication.Registrant.class) public abstract CoreStartable bindSmartSpaceComplicationRegistrant( SmartSpaceComplication.Registrant registrant); + + /** Inject into MediaDreamSentinel. */ + @Binds + @IntoMap + @ClassKey(MediaDreamSentinel.class) + public abstract CoreStartable bindMediaDreamSentinel( + MediaDreamSentinel sentinel); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index c8cd43287c99..64ebe568c790 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -31,6 +31,7 @@ import androidx.annotation.VisibleForTesting import com.android.systemui.R import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.CrossFadeHelper @@ -82,7 +83,8 @@ class MediaHierarchyManager @Inject constructor( private val notifLockscreenUserManager: NotificationLockscreenUserManager, configurationController: ConfigurationController, wakefulnessLifecycle: WakefulnessLifecycle, - private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager + private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager, + private val dreamOverlayStateController: DreamOverlayStateController ) { /** @@ -167,7 +169,7 @@ class MediaHierarchyManager @Inject constructor( }) } - private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_LOCKSCREEN + 1) + private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_DREAM_OVERLAY + 1) /** * The last location where this view was at before going to the desired location. This is * useful for guided transitions. @@ -349,6 +351,17 @@ class MediaHierarchyManager @Inject constructor( } /** + * Is the doze animation currently Running + */ + private var dreamOverlayActive: Boolean = false + private set(value) { + if (field != value) { + field = value + updateDesiredLocation(forceNoAnimation = true) + } + } + + /** * The current cross fade progress. 0.5f means it's just switching * between the start and the end location and the content is fully faded, while 0.75f means * that we're halfway faded in again in the target state. @@ -444,6 +457,12 @@ class MediaHierarchyManager @Inject constructor( } }) + dreamOverlayStateController.addCallback(object : DreamOverlayStateController.Callback { + override fun onStateChanged() { + dreamOverlayStateController.isOverlayActive.also { dreamOverlayActive = it } + } + }) + wakefulnessLifecycle.addObserver(object : WakefulnessLifecycle.Observer { override fun onFinishedGoingToSleep() { goingToSleep = false @@ -940,6 +959,7 @@ class MediaHierarchyManager @Inject constructor( statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER)) val allowedOnLockscreen = notifLockscreenUserManager.shouldShowLockscreenNotifications() val location = when { + dreamOverlayActive -> LOCATION_DREAM_OVERLAY (qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS qsExpansion > 0.4f && onLockscreen -> LOCATION_QS !hasActiveMedia -> LOCATION_QS @@ -1035,6 +1055,11 @@ class MediaHierarchyManager @Inject constructor( const val LOCATION_LOCKSCREEN = 2 /** + * Attached on the dream overlay + */ + const val LOCATION_DREAM_OVERLAY = 3 + + /** * Attached at the root of the hierarchy in an overlay */ const val IN_OVERLAY = -1000 diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java index 4baef3aef309..2bc910e4a21a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java +++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java @@ -25,6 +25,7 @@ import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.media.MediaHost; import com.android.systemui.media.MediaHostStatesManager; +import com.android.systemui.media.dream.dagger.MediaComplicationComponent; import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper; import com.android.systemui.media.taptotransfer.MediaTttFlags; import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver; @@ -43,11 +44,14 @@ import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; /** Dagger module for the media package. */ -@Module +@Module(subcomponents = { + MediaComplicationComponent.class, +}) public interface MediaModule { String QS_PANEL = "media_qs_panel"; String QUICK_QS_PANEL = "media_quick_qs_panel"; String KEYGUARD = "media_keyguard"; + String DREAM = "dream"; /** */ @Provides @@ -82,6 +86,16 @@ public interface MediaModule { /** */ @Provides @SysUISingleton + @Named(DREAM) + static MediaHost providesDreamMediaHost(MediaHost.MediaHostStateHolder stateHolder, + MediaHierarchyManager hierarchyManager, MediaDataManager dataManager, + MediaHostStatesManager statesManager) { + return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager); + } + + /** */ + @Provides + @SysUISingleton static Optional<MediaTttChipControllerSender> providesMediaTttChipControllerSender( MediaTttFlags mediaTttFlags, Context context, diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaComplicationViewController.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaComplicationViewController.java new file mode 100644 index 000000000000..65c5bc76f3c5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaComplicationViewController.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dream; + +import static com.android.systemui.media.dagger.MediaModule.DREAM; +import static com.android.systemui.media.dream.dagger.MediaComplicationComponent.MediaComplicationModule.MEDIA_COMPLICATION_CONTAINER; + +import android.widget.FrameLayout; + +import com.android.systemui.media.MediaHierarchyManager; +import com.android.systemui.media.MediaHost; +import com.android.systemui.media.MediaHostState; +import com.android.systemui.util.ViewController; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * {@link MediaComplicationViewController} handles connecting the + * {@link com.android.systemui.dreams.complication.Complication} view to the {@link MediaHost}. + */ +public class MediaComplicationViewController extends ViewController<FrameLayout> { + private final MediaHost mMediaHost; + + @Inject + public MediaComplicationViewController( + @Named(MEDIA_COMPLICATION_CONTAINER) FrameLayout view, + @Named(DREAM) MediaHost mediaHost) { + super(view); + mMediaHost = mediaHost; + } + + @Override + protected void onInit() { + super.onInit(); + mMediaHost.setExpansion(MediaHostState.COLLAPSED); + mMediaHost.setShowsOnlyActiveMedia(true); + mMediaHost.setFalsingProtectionNeeded(true); + mMediaHost.init(MediaHierarchyManager.LOCATION_DREAM_OVERLAY); + } + + @Override + protected void onViewAttached() { + mMediaHost.hostView.setLayoutParams(new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.WRAP_CONTENT)); + mView.addView(mMediaHost.hostView); + } + + @Override + protected void onViewDetached() { + mView.removeView(mMediaHost.hostView); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamComplication.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamComplication.java new file mode 100644 index 000000000000..2c35db337cda --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamComplication.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dream; + +import com.android.systemui.dreams.complication.Complication; +import com.android.systemui.dreams.complication.ComplicationViewModel; +import com.android.systemui.media.dream.dagger.MediaComplicationComponent; + +import javax.inject.Inject; + +/** + * Media control complication for dream overlay. + */ +public class MediaDreamComplication implements Complication { + MediaComplicationComponent.Factory mComponentFactory; + + /** + * Default constructor for {@link MediaDreamComplication}. + */ + @Inject + public MediaDreamComplication(MediaComplicationComponent.Factory componentFactory) { + mComponentFactory = componentFactory; + } + + @Override + public ViewHolder createView(ComplicationViewModel model) { + return mComponentFactory.create().getViewHolder(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java new file mode 100644 index 000000000000..8934cd1085b8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dream; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.systemui.CoreStartable; +import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.media.MediaData; +import com.android.systemui.media.MediaDataManager; +import com.android.systemui.media.SmartspaceMediaData; + +import javax.inject.Inject; + +/** + * {@link MediaDreamSentinel} is responsible for tracking media state and registering/unregistering + * the media complication as appropriate + */ +public class MediaDreamSentinel extends CoreStartable { + private MediaDataManager.Listener mListener = new MediaDataManager.Listener() { + private boolean mAdded; + @Override + public void onSmartspaceMediaDataRemoved(@NonNull String key, boolean immediately) { + } + + @Override + public void onMediaDataRemoved(@NonNull String key) { + if (!mAdded) { + return; + } + + if (mMediaDataManager.hasActiveMedia()) { + return; + } + + mAdded = false; + mDreamOverlayStateController.removeComplication(mComplication); + } + + @Override + public void onSmartspaceMediaDataLoaded(@NonNull String key, + @NonNull SmartspaceMediaData data, boolean shouldPrioritize, + boolean isSsReactivated) { + } + + @Override + public void onMediaDataLoaded(@NonNull String key, @Nullable String oldKey, + @NonNull MediaData data, boolean immediately, int receivedSmartspaceCardLatency) { + if (mAdded) { + return; + } + + if (!mMediaDataManager.hasActiveMedia()) { + return; + } + + mAdded = true; + mDreamOverlayStateController.addComplication(mComplication); + } + }; + + private final MediaDataManager mMediaDataManager; + private final DreamOverlayStateController mDreamOverlayStateController; + private final MediaDreamComplication mComplication; + + @Inject + public MediaDreamSentinel(Context context, MediaDataManager mediaDataManager, + DreamOverlayStateController dreamOverlayStateController, + MediaDreamComplication complication) { + super(context); + mMediaDataManager = mediaDataManager; + mDreamOverlayStateController = dreamOverlayStateController; + mComplication = complication; + } + + @Override + public void start() { + mMediaDataManager.addListener(mListener); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaViewHolder.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaViewHolder.java new file mode 100644 index 000000000000..128a38c639be --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaViewHolder.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dream; + +import static com.android.systemui.media.dream.dagger.MediaComplicationComponent.MediaComplicationModule.MEDIA_COMPLICATION_CONTAINER; +import static com.android.systemui.media.dream.dagger.MediaComplicationComponent.MediaComplicationModule.MEDIA_COMPLICATION_LAYOUT_PARAMS; + +import android.view.View; +import android.widget.FrameLayout; + +import com.android.systemui.dreams.complication.Complication; +import com.android.systemui.dreams.complication.ComplicationLayoutParams; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * {@link Complication.ViewHolder} implementation for media control. + */ +public class MediaViewHolder implements Complication.ViewHolder { + private final FrameLayout mContainer; + private final MediaComplicationViewController mViewController; + private final ComplicationLayoutParams mLayoutParams; + + @Inject + MediaViewHolder(@Named(MEDIA_COMPLICATION_CONTAINER) FrameLayout container, + MediaComplicationViewController controller, + @Named(MEDIA_COMPLICATION_LAYOUT_PARAMS) ComplicationLayoutParams layoutParams) { + mContainer = container; + mViewController = controller; + mViewController.init(); + mLayoutParams = layoutParams; + } + + @Override + public View getView() { + return mContainer; + } + + @Override + public ComplicationLayoutParams getLayoutParams() { + return mLayoutParams; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java new file mode 100644 index 000000000000..3372899b8fd7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dream.dagger; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import android.content.Context; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.android.systemui.dreams.complication.ComplicationLayoutParams; +import com.android.systemui.media.dream.MediaViewHolder; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Named; +import javax.inject.Scope; + +import dagger.Module; +import dagger.Provides; +import dagger.Subcomponent; + +/** + * {@link MediaComplicationComponent} is responsible for generating dependencies surrounding the + * media {@link com.android.systemui.dreams.complication.Complication}, such as view controllers + * and layout details. + */ +@Subcomponent(modules = { + MediaComplicationComponent.MediaComplicationModule.class, +}) +@MediaComplicationComponent.MediaComplicationScope +public interface MediaComplicationComponent { + @Documented + @Retention(RUNTIME) + @Scope + @interface MediaComplicationScope {} + + /** + * Generates {@link MediaComplicationComponent}. + */ + @Subcomponent.Factory + interface Factory { + MediaComplicationComponent create(); + } + + /** + * Creates {@link MediaViewHolder}. + */ + MediaViewHolder getViewHolder(); + + /** + * Scoped values for {@link MediaComplicationComponent}. + */ + @Module + interface MediaComplicationModule { + String MEDIA_COMPLICATION_CONTAINER = "media_complication_container"; + String MEDIA_COMPLICATION_LAYOUT_PARAMS = "media_complication_layout_params"; + + /** + * Provides the complication view. + */ + @Provides + @MediaComplicationScope + @Named(MEDIA_COMPLICATION_CONTAINER) + static FrameLayout provideComplicationContainer(Context context) { + return new FrameLayout(context); + } + + /** + * Provides the layout parameters for the complication view. + */ + @Provides + @MediaComplicationScope + @Named(MEDIA_COMPLICATION_LAYOUT_PARAMS) + static ComplicationLayoutParams provideLayoutParams() { + return new ComplicationLayoutParams(0, + ViewGroup.LayoutParams.WRAP_CONTENT, + ComplicationLayoutParams.POSITION_BOTTOM + | ComplicationLayoutParams.POSITION_END, + ComplicationLayoutParams.DIRECTION_UP, + 0, + true); + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt index a3ffb2fe4b8d..97b3b10ebcbf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt @@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq +import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager @@ -85,6 +86,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private lateinit var configurationController: ConfigurationController @Mock private lateinit var uniqueObjectHostView: UniqueObjectHostView + @Mock + private lateinit var dreamOverlayStateController: DreamOverlayStateController @Captor private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)> @Captor @@ -110,7 +113,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() { notificationLockscreenUserManager, configurationController, wakefulnessLifecycle, - statusBarKeyguardViewManager) + statusBarKeyguardViewManager, + dreamOverlayStateController) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java new file mode 100644 index 000000000000..29188da46562 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dream; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.testing.AndroidTestingRunner; +import android.widget.FrameLayout; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.media.MediaHost; +import com.android.systemui.util.animation.UniqueObjectHostView; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class MediaComplicationViewControllerTest extends SysuiTestCase { + @Mock + private MediaHost mMediaHost; + + @Mock + private UniqueObjectHostView mView; + + @Mock + private FrameLayout mComplicationContainer; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mMediaHost.hostView = mView; + } + + @Test + public void testMediaHostViewInteraction() { + final MediaComplicationViewController controller = new MediaComplicationViewController( + mComplicationContainer, mMediaHost); + + controller.init(); + + controller.onViewAttached(); + verify(mComplicationContainer).addView(eq(mView)); + + controller.onViewDetached(); + verify(mComplicationContainer).removeView(eq(mView)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java new file mode 100644 index 000000000000..114fc90e8590 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.media.MediaData; +import com.android.systemui.media.MediaDataManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class MediaDreamSentinelTest extends SysuiTestCase { + @Mock + MediaDataManager mMediaDataManager; + + @Mock + DreamOverlayStateController mDreamOverlayStateController; + + @Mock + MediaDreamComplication mComplication; + + final String mKey = "key"; + final String mOldKey = "old_key"; + + @Mock + MediaData mData; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testComplicationAddition() { + final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager, + mDreamOverlayStateController, mComplication); + + sentinel.start(); + + ArgumentCaptor<MediaDataManager.Listener> listenerCaptor = + ArgumentCaptor.forClass(MediaDataManager.Listener.class); + verify(mMediaDataManager).addListener(listenerCaptor.capture()); + + final MediaDataManager.Listener listener = listenerCaptor.getValue(); + + when(mMediaDataManager.hasActiveMedia()).thenReturn(false); + listener.onMediaDataLoaded(mKey, mOldKey, mData, true, 0); + verify(mDreamOverlayStateController, never()).addComplication(any()); + + when(mMediaDataManager.hasActiveMedia()).thenReturn(true); + listener.onMediaDataLoaded(mKey, mOldKey, mData, true, 0); + verify(mDreamOverlayStateController).addComplication(eq(mComplication)); + + listener.onMediaDataRemoved(mKey); + verify(mDreamOverlayStateController, never()).removeComplication(any()); + + when(mMediaDataManager.hasActiveMedia()).thenReturn(false); + listener.onMediaDataRemoved(mKey); + verify(mDreamOverlayStateController).removeComplication(eq(mComplication)); + } + +} |