diff options
12 files changed, 431 insertions, 17 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt index a1cee8aaac7c..164acdbc49ba 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt @@ -16,10 +16,17 @@ package com.android.systemui.media.controls.domain.interactor +import android.app.PendingIntent +import android.os.Bundle import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase +import com.android.systemui.activityIntentHelper +import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.animation.DialogTransitionAnimator +import com.android.systemui.animation.Expandable +import com.android.systemui.bluetooth.mockBroadcastDialogController import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl @@ -28,13 +35,22 @@ import com.android.systemui.media.controls.domain.pipeline.interactor.mediaContr import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.util.mediaInstanceId +import com.android.systemui.media.mediaOutputDialogManager +import com.android.systemui.mockActivityIntentHelper +import com.android.systemui.plugins.activityStarter import com.android.systemui.statusbar.notificationLockscreenUserManager +import com.android.systemui.statusbar.policy.keyguardStateController import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.never +import org.mockito.Mockito.verify @SmallTest @RunWith(AndroidJUnit4::class) @@ -44,10 +60,16 @@ class MediaControlInteractorTest : SysuiTestCase() { private val testScope = kosmos.testScope private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter + private val activityStarter = kosmos.activityStarter + private val keyguardStateController = kosmos.keyguardStateController private val instanceId: InstanceId = kosmos.mediaInstanceId private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager - private val underTest: MediaControlInteractor = kosmos.mediaControlInteractor + private val underTest: MediaControlInteractor = + with(kosmos) { + activityIntentHelper = mockActivityIntentHelper + kosmos.mediaControlInteractor + } @Test fun onMediaDataUpdated() = @@ -84,9 +106,113 @@ class MediaControlInteractorTest : SysuiTestCase() { assertThat(controlModel?.artistName).isEqualTo(SESSION_ARTIST_2) } + @Test + fun startSettings() { + underTest.startSettings() + + verify(activityStarter).startActivity(any(), eq(true)) + } + + @Test + fun startClickIntent_showOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())) + .thenReturn(true) + + val clickIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + val expandable = mock<Expandable>() + + underTest.startClickIntent(expandable, clickIntent) + + verify(clickIntent).send(any<Bundle>()) + } + + @Test + fun startClickIntent_hideOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(false) + + val clickIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + val expandable = mock<Expandable>() + val activityController = mock<ActivityTransitionAnimator.Controller>() + whenever(expandable.activityTransitionController(any())).thenReturn(activityController) + + underTest.startClickIntent(expandable, clickIntent) + + verify(activityStarter) + .postStartActivityDismissingKeyguard(eq(clickIntent), eq(activityController)) + } + + @Test + fun startDeviceIntent_showOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())) + .thenReturn(true) + + val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + + underTest.startDeviceIntent(deviceIntent) + + verify(deviceIntent).send(any<Bundle>()) + } + + @Test + fun startDeviceIntent_intentNotActivity() { + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())) + .thenReturn(true) + + val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(false) } + + underTest.startDeviceIntent(deviceIntent) + + verify(deviceIntent, never()).send(any<Bundle>()) + } + + @Test + fun startDeviceIntent_hideOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(false) + + val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + + underTest.startDeviceIntent(deviceIntent) + + verify(activityStarter).postStartActivityDismissingKeyguard(eq(deviceIntent)) + } + + @Test + fun startMediaOutputDialog() { + val expandable = mock<Expandable>() + val dialogTransitionController = mock<DialogTransitionAnimator.Controller>() + whenever(expandable.dialogTransitionController(any())) + .thenReturn(dialogTransitionController) + + underTest.startMediaOutputDialog(expandable, PACKAGE_NAME) + + verify(kosmos.mediaOutputDialogManager) + .createAndShowWithController(eq(PACKAGE_NAME), eq(true), eq(dialogTransitionController)) + } + + @Test + fun startBroadcastDialog() { + val expandable = mock<Expandable>() + val dialogTransitionController = mock<DialogTransitionAnimator.Controller>() + whenever(expandable.dialogTransitionController()).thenReturn(dialogTransitionController) + + underTest.startBroadcastDialog(expandable, APP_NAME, PACKAGE_NAME) + + verify(kosmos.mockBroadcastDialogController) + .createBroadcastDialogWithController( + eq(APP_NAME), + eq(PACKAGE_NAME), + eq(dialogTransitionController) + ) + } + companion object { private const val USER_ID = 0 private const val KEY = "key" + private const val PACKAGE_NAME = "com.example.app" + private const val APP_NAME = "app" private const val SESSION_ARTIST = "artist" private const val SESSION_ARTIST_2 = "artist2" } diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java index 161458fdb33e..a90e60d2a8a3 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java @@ -56,4 +56,22 @@ public class BroadcastDialogController { broadcastDialog.show(); } } + + /** Creates a [BroadcastDialog] for the user to switch broadcast or change the output device + * + * @param currentBroadcastAppName Indicates the APP name currently broadcasting + * @param outputPkgName Indicates the output media package name to be switched + * @param controller Indicates the dialog controller of the source view. + */ + public void createBroadcastDialogWithController( + String currentBroadcastAppName, String outputPkgName, + DialogTransitionAnimator.Controller controller) { + SystemUIDialog broadcastDialog = mBroadcastDialogFactory.create( + currentBroadcastAppName, outputPkgName).createDialog(); + if (controller != null) { + mDialogTransitionAnimator.show(broadcastDialog, controller); + } else { + broadcastDialog.show(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt index 7412290e8fc5..1d7c0256b2ef 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt @@ -590,7 +590,7 @@ class MediaDataProcessor( } /** Dismiss a media entry. Returns false if the key was not found. */ - fun dismissMediaData(key: String, delay: Long): Boolean { + fun dismissMediaData(key: String, delayMs: Long): Boolean { val existed = mediaDataRepository.mediaEntries.value[key] != null backgroundExecutor.execute { mediaDataRepository.mediaEntries.value[key]?.let { mediaData -> @@ -602,10 +602,21 @@ class MediaDataProcessor( } } } - foregroundExecutor.executeDelayed({ removeEntry(key) }, delay) + foregroundExecutor.executeDelayed({ removeEntry(key) }, delayMs) return existed } + /** Dismiss a media entry. Returns false if the corresponding key was not found. */ + fun dismissMediaData(instanceId: InstanceId, delayMs: Long): Boolean { + val mediaEntries = mediaDataRepository.mediaEntries.value + val filteredEntries = mediaEntries.filter { (_, data) -> data.instanceId == instanceId } + return if (filteredEntries.isNotEmpty()) { + dismissMediaData(filteredEntries.keys.first(), delayMs) + } else { + false + } + } + /** * Called whenever the recommendation has been expired or removed by the user. This will remove * the recommendation card entirely from the carousel. diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt index 5a0388de444e..f6c51a83e88e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt @@ -16,20 +16,43 @@ package com.android.systemui.media.controls.domain.pipeline.interactor +import android.app.ActivityOptions +import android.app.BroadcastOptions +import android.app.PendingIntent +import android.content.Intent +import android.media.session.MediaSession +import android.provider.Settings +import android.util.Log +import com.android.internal.jank.Cuj import com.android.internal.logging.InstanceId +import com.android.systemui.ActivityIntentHelper +import com.android.systemui.animation.DialogCuj +import com.android.systemui.animation.DialogTransitionAnimator +import com.android.systemui.animation.Expandable +import com.android.systemui.bluetooth.BroadcastDialogController import com.android.systemui.media.controls.data.repository.MediaFilterRepository import com.android.systemui.media.controls.domain.pipeline.MediaDataProcessor import com.android.systemui.media.controls.shared.model.MediaControlModel import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.dialog.MediaOutputDialogManager +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.policy.KeyguardStateController import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map /** Encapsulates business logic for single media control. */ class MediaControlInteractor( - instanceId: InstanceId, + private val instanceId: InstanceId, repository: MediaFilterRepository, private val mediaDataProcessor: MediaDataProcessor, + private val keyguardStateController: KeyguardStateController, + private val activityStarter: ActivityStarter, + private val activityIntentHelper: ActivityIntentHelper, + private val lockscreenUserManager: NotificationLockscreenUserManager, + private val mediaOutputDialogManager: MediaOutputDialogManager, + private val broadcastDialogController: BroadcastDialogController, ) { val mediaControl: Flow<MediaControlModel?> = @@ -37,8 +60,19 @@ class MediaControlInteractor( .map { entries -> entries[instanceId]?.let { toMediaControlModel(it) } } .distinctUntilChanged() - fun removeMediaControl(key: String, delayMs: Long): Boolean { - return mediaDataProcessor.dismissMediaData(key, delayMs) + fun removeMediaControl( + token: MediaSession.Token?, + instanceId: InstanceId, + delayMs: Long + ): Boolean { + val dismissed = mediaDataProcessor.dismissMediaData(instanceId, delayMs) + if (!dismissed) { + Log.w( + TAG, + "Manager failed to dismiss media of instanceId=$instanceId, Token uid=${token?.uid}" + ) + } + return dismissed } private fun toMediaControlModel(data: MediaData): MediaControlModel { @@ -53,14 +87,89 @@ class MediaControlInteractor( appName = app, songName = song, artistName = artist, + showExplicit = isExplicit, artwork = artwork, deviceData = device, semanticActionButtons = semanticActions, notificationActionButtons = actions, actionsToShowInCollapsed = actionsToShowInCompact, + isDismissible = isClearable, isResume = resumption, resumeProgress = resumeProgress, ) } } + + fun startSettings() { + activityStarter.startActivity(SETTINGS_INTENT, /* dismissShade= */ true) + } + + fun startClickIntent(expandable: Expandable, clickIntent: PendingIntent) { + if (!launchOverLockscreen(clickIntent)) { + activityStarter.postStartActivityDismissingKeyguard( + clickIntent, + expandable.activityTransitionController(Cuj.CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER) + ) + } + } + + fun startDeviceIntent(deviceIntent: PendingIntent) { + if (deviceIntent.isActivity) { + if (!launchOverLockscreen(deviceIntent)) { + activityStarter.postStartActivityDismissingKeyguard(deviceIntent) + } + } else { + Log.w(TAG, "Device pending intent of instanceId=$instanceId is not an activity.") + } + } + + private fun launchOverLockscreen(pendingIntent: PendingIntent): Boolean { + val showOverLockscreen = + keyguardStateController.isShowing && + activityIntentHelper.wouldPendingShowOverLockscreen( + pendingIntent, + lockscreenUserManager.currentUserId + ) + if (showOverLockscreen) { + try { + val options = BroadcastOptions.makeBasic() + options.isInteractive = true + options.pendingIntentBackgroundActivityStartMode = + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED + pendingIntent.send(options.toBundle()) + } catch (e: PendingIntent.CanceledException) { + Log.e(TAG, "pending intent of $instanceId was canceled") + } + return true + } + return false + } + + fun startMediaOutputDialog(expandable: Expandable, packageName: String) { + mediaOutputDialogManager.createAndShowWithController( + packageName, + true, + expandable.dialogController() + ) + } + + fun startBroadcastDialog(expandable: Expandable, broadcastApp: String, packageName: String) { + broadcastDialogController.createBroadcastDialogWithController( + broadcastApp, + packageName, + expandable.dialogTransitionController() + ) + } + + private fun Expandable.dialogController(): DialogTransitionAnimator.Controller? { + return dialogTransitionController( + cuj = + DialogCuj(Cuj.CUJ_SHADE_DIALOG_OPEN, MediaOutputDialogManager.INTERACTION_JANK_TAG) + ) + } + + companion object { + private const val TAG = "MediaControlInteractor" + private val SETTINGS_INTENT = Intent(Settings.ACTION_MEDIA_CONTROLS_SETTINGS) + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt index d4e34b5af260..f9134f52b58f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt @@ -33,6 +33,7 @@ data class MediaControlModel( val appName: String?, val songName: CharSequence?, val artistName: CharSequence?, + val showExplicit: Boolean, val artwork: Icon?, val deviceData: MediaDeviceData?, /** [MediaButton] contains [MediaAction] objects which represent specific buttons in the UI */ @@ -43,6 +44,7 @@ data class MediaControlModel( * [Notification.MediaStyle.setShowActionsInCompactView]. */ val actionsToShowInCollapsed: List<Int>, + val isDismissible: Boolean, /** Whether player is in resumption state. */ val isResume: Boolean, /** Track seek bar progress (0 - 1) when [isResume] is true. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java index 899b9ed103cd..c7e602904de3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java @@ -747,18 +747,23 @@ public class MediaControlPanel { boolean showOverLockscreen = mKeyguardStateController.isShowing() && mActivityIntentHelper.wouldPendingShowOverLockscreen( deviceIntent, mLockscreenUserManager.getCurrentUserId()); - if (deviceIntent.isActivity() && !showOverLockscreen) { - mActivityStarter.postStartActivityDismissingKeyguard(deviceIntent); - } else { - try { - BroadcastOptions options = BroadcastOptions.makeBasic(); - options.setInteractive(true); - options.setPendingIntentBackgroundActivityStartMode( + if (deviceIntent.isActivity()) { + if (!showOverLockscreen) { + mActivityStarter.postStartActivityDismissingKeyguard( + deviceIntent); + } else { + try { + BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setInteractive(true); + options.setPendingIntentBackgroundActivityStartMode( ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED); - deviceIntent.send(options.toBundle()); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Device pending intent was canceled"); + deviceIntent.send(options.toBundle()); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "Device pending intent was canceled"); + } } + } else { + Log.w(TAG, "Device pending intent is not an activity."); } } else { mMediaOutputDialogManager.createAndShow(mPackageName, true, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt new file mode 100644 index 000000000000..1e67a77250ee --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 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.controls.ui.viewmodel + +import android.graphics.drawable.Drawable +import androidx.constraintlayout.widget.ConstraintSet + +/** Models UI state of media buttons in media control. */ +data class MediaActionViewModel( + val icon: Drawable?, + val contentDescription: CharSequence?, + val background: Drawable?, + val isVisible: Boolean = true, + val notVisibleValue: Int = ConstraintSet.GONE, + val showInCollapsed: Boolean, + val rebindId: Int? = null, + val buttonId: Int? = null, + val isEnabled: Boolean, + val onClicked: (Int) -> Unit, +) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt new file mode 100644 index 000000000000..9df9bccdf522 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 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.controls.ui.viewmodel + +import com.android.systemui.animation.Expandable +import com.android.systemui.common.shared.model.Icon + +/** Models UI state of output switcher chip. */ +data class MediaOutputSwitcherViewModel( + val isTapEnabled: Boolean, + val deviceString: CharSequence, + val deviceIcon: Icon, + val isCurrentBroadcastApp: Boolean, + val isIntentValid: Boolean, + val alpha: Float, + val isVisible: Boolean, + val onClicked: (Expandable) -> Unit, +) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt new file mode 100644 index 000000000000..9029a65bd9ee --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 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.controls.ui.viewmodel + +import com.android.systemui.animation.Expandable +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.monet.ColorScheme + +/** Models UI state for media player. */ +data class MediaPlayerViewModel( + val contentDescription: (Boolean) -> CharSequence, + val backgroundCover: android.graphics.drawable.Icon?, + val appIcon: Icon, + val useGrayColorFilter: Boolean, + val artistName: CharSequence, + val titleName: CharSequence, + val isExplicitVisible: Boolean, + val colorScheme: ColorScheme, + val isTimeVisible: Boolean, + val playTurbulenceNoise: Boolean, + val useSemanticActions: Boolean, + val actionButtons: List<MediaActionViewModel?>, + val outputSwitcher: MediaOutputSwitcherViewModel, + val gutsMenu: GutsViewModel, + val onClicked: (Expandable) -> Unit, + val onLongClicked: () -> Unit, +) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt index 7185b7cd0ac6..96c4c45dbb91 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt @@ -18,5 +18,7 @@ package com.android.systemui import android.content.applicationContext import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock -val Kosmos.activityIntentHelper by Kosmos.Fixture { ActivityIntentHelper(applicationContext) } +val Kosmos.mockActivityIntentHelper by Kosmos.Fixture { mock<ActivityIntentHelper>() } +var Kosmos.activityIntentHelper by Kosmos.Fixture { ActivityIntentHelper(applicationContext) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt new file mode 100644 index 000000000000..e9d72664c6b0 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 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.bluetooth + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +val Kosmos.mockBroadcastDialogController by Kosmos.Fixture { mock<BroadcastDialogController>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt index 29c5bd5dd1d4..6e650a3c5391 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt @@ -16,10 +16,16 @@ package com.android.systemui.media.controls.domain.pipeline.interactor +import com.android.systemui.activityIntentHelper +import com.android.systemui.bluetooth.mockBroadcastDialogController import com.android.systemui.kosmos.Kosmos import com.android.systemui.media.controls.data.repository.mediaFilterRepository import com.android.systemui.media.controls.domain.pipeline.mediaDataProcessor import com.android.systemui.media.controls.util.mediaInstanceId +import com.android.systemui.media.mediaOutputDialogManager +import com.android.systemui.plugins.activityStarter +import com.android.systemui.statusbar.notificationLockscreenUserManager +import com.android.systemui.statusbar.policy.keyguardStateController val Kosmos.mediaControlInteractor by Kosmos.Fixture { @@ -27,5 +33,11 @@ val Kosmos.mediaControlInteractor by instanceId = mediaInstanceId, repository = mediaFilterRepository, mediaDataProcessor = mediaDataProcessor, + keyguardStateController = keyguardStateController, + activityStarter = activityStarter, + activityIntentHelper = activityIntentHelper, + lockscreenUserManager = notificationLockscreenUserManager, + mediaOutputDialogManager = mediaOutputDialogManager, + broadcastDialogController = mockBroadcastDialogController, ) } |