diff --git a/media/audio-ui-model/api/current.api b/media/audio-ui-model/api/current.api index eb64445475..e7f1ffd576 100644 --- a/media/audio-ui-model/api/current.api +++ b/media/audio-ui-model/api/current.api @@ -28,7 +28,7 @@ package com.google.android.horologist.audio.ui { method public final kotlinx.coroutines.flow.StateFlow getVolumeUiState(); method public final void increaseVolume(); method public final void increaseVolumeWithHaptics(); - method public final void launchOutputSelection(); + method public final void launchOutputSelection(optional String? clientPackageName); method public final void onVolumeChangeByScroll(float pixels); method public final void setVolume(int volume); property public final kotlinx.coroutines.flow.StateFlow audioOutput; diff --git a/media/audio-ui-model/src/main/java/com/google/android/horologist/audio/ui/VolumeViewModel.kt b/media/audio-ui-model/src/main/java/com/google/android/horologist/audio/ui/VolumeViewModel.kt index 89d699ab59..829b3e5141 100644 --- a/media/audio-ui-model/src/main/java/com/google/android/horologist/audio/ui/VolumeViewModel.kt +++ b/media/audio-ui-model/src/main/java/com/google/android/horologist/audio/ui/VolumeViewModel.kt @@ -95,8 +95,11 @@ public open class VolumeViewModel( volumeRepository.decreaseVolume() } - public fun launchOutputSelection() { - audioOutputRepository.launchOutputSelection(closeOnConnect = false) + public fun launchOutputSelection(clientPackageName: String? = null) { + audioOutputRepository.launchOutputSelection( + closeOnConnect = false, + clientPackageName = clientPackageName, + ) } override fun onCleared() { diff --git a/media/audio-ui/src/test/kotlin/com/google/android/horologist/audio/ui/FakeAudioOutputRepository.kt b/media/audio-ui/src/test/kotlin/com/google/android/horologist/audio/ui/FakeAudioOutputRepository.kt index f5180a8d80..93e4044cc8 100644 --- a/media/audio-ui/src/test/kotlin/com/google/android/horologist/audio/ui/FakeAudioOutputRepository.kt +++ b/media/audio-ui/src/test/kotlin/com/google/android/horologist/audio/ui/FakeAudioOutputRepository.kt @@ -23,7 +23,7 @@ class FakeAudioOutputRepository : AudioOutputRepository { override val audioOutput: MutableStateFlow = MutableStateFlow(AudioOutput.None) override val available: MutableStateFlow> = MutableStateFlow(listOf()) - override fun launchOutputSelection(closeOnConnect: Boolean) { + override fun launchOutputSelection(closeOnConnect: Boolean, clientPackageName: String?) { } override fun close() { diff --git a/media/audio/api/current.api b/media/audio/api/current.api index 0729673911..6457708e09 100644 --- a/media/audio/api/current.api +++ b/media/audio/api/current.api @@ -80,7 +80,7 @@ package com.google.android.horologist.audio { public interface AudioOutputRepository extends java.lang.AutoCloseable { method public kotlinx.coroutines.flow.StateFlow getAudioOutput(); method public kotlinx.coroutines.flow.StateFlow> getAvailable(); - method public void launchOutputSelection(boolean closeOnConnect); + method public void launchOutputSelection(boolean closeOnConnect, optional String? clientPackageName); property public abstract kotlinx.coroutines.flow.StateFlow audioOutput; property public abstract kotlinx.coroutines.flow.StateFlow> available; } @@ -91,7 +91,7 @@ package com.google.android.horologist.audio { } public final class OutputSwitcher { - method public boolean launchSystemMediaOutputSwitcherUi(android.content.Context); + method public boolean launchSystemMediaOutputSwitcherUi(android.content.Context, optional String? callingPkgName); field public static final com.google.android.horologist.audio.OutputSwitcher INSTANCE; } @@ -103,7 +103,7 @@ package com.google.android.horologist.audio { method public kotlinx.coroutines.flow.StateFlow> getAvailable(); method public kotlinx.coroutines.flow.StateFlow getVolumeState(); method public void increaseVolume(); - method public void launchOutputSelection(boolean closeOnConnect); + method public void launchOutputSelection(boolean closeOnConnect, String? clientPackageName); method public void setVolume(int volume); property public kotlinx.coroutines.flow.StateFlow audioOutput; property public kotlinx.coroutines.flow.StateFlow> available; diff --git a/media/audio/src/main/java/com/google/android/horologist/audio/AudioOutputRepository.kt b/media/audio/src/main/java/com/google/android/horologist/audio/AudioOutputRepository.kt index e376f1231b..d00ad3d1d2 100644 --- a/media/audio/src/main/java/com/google/android/horologist/audio/AudioOutputRepository.kt +++ b/media/audio/src/main/java/com/google/android/horologist/audio/AudioOutputRepository.kt @@ -35,5 +35,5 @@ public interface AudioOutputRepository : AutoCloseable { /** * Action to launch output selection by the user. */ - public fun launchOutputSelection(closeOnConnect: Boolean) + public fun launchOutputSelection(closeOnConnect: Boolean, clientPackageName: String? = null) } diff --git a/media/audio/src/main/java/com/google/android/horologist/audio/OutputSwitcher.kt b/media/audio/src/main/java/com/google/android/horologist/audio/OutputSwitcher.kt index ab2733db17..c0cc181856 100644 --- a/media/audio/src/main/java/com/google/android/horologist/audio/OutputSwitcher.kt +++ b/media/audio/src/main/java/com/google/android/horologist/audio/OutputSwitcher.kt @@ -31,10 +31,10 @@ public object OutputSwitcher { /** * Open the Output Switcher Dialog. */ - public fun Context.launchSystemMediaOutputSwitcherUi(): Boolean { + public fun Context.launchSystemMediaOutputSwitcherUi(callingPkgName: String? = null): Boolean { val outputSwitcherLaunchIntent: Intent = Intent(OUTPUT_SWITCHER_INTENT_ACTION_NAME) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .putExtra(EXTRA_OUTPUT_SWITCHER_PACKAGE_NAME, packageName) + .putExtra(EXTRA_OUTPUT_SWITCHER_PACKAGE_NAME, callingPkgName ?: packageName) val outputSwitcherSystemComponentName = getSystemOrSystemUpdatedAppComponent(outputSwitcherLaunchIntent) if (outputSwitcherSystemComponentName != null) { diff --git a/media/audio/src/main/java/com/google/android/horologist/audio/SystemAudioRepository.kt b/media/audio/src/main/java/com/google/android/horologist/audio/SystemAudioRepository.kt index 68d546eddd..b6945f3316 100644 --- a/media/audio/src/main/java/com/google/android/horologist/audio/SystemAudioRepository.kt +++ b/media/audio/src/main/java/com/google/android/horologist/audio/SystemAudioRepository.kt @@ -135,8 +135,8 @@ public class SystemAudioRepository( } } - override fun launchOutputSelection(closeOnConnect: Boolean) { - if (!application.launchSystemMediaOutputSwitcherUi()) { + override fun launchOutputSelection(closeOnConnect: Boolean, clientPackageName: String?) { + if (!application.launchSystemMediaOutputSwitcherUi(clientPackageName)) { application.launchBluetoothSettings(closeOnConnect) } } diff --git a/media/backend-media3/src/test/java/com/google/android/horologist/media3/FakeAudioOutputRepository.kt b/media/backend-media3/src/test/java/com/google/android/horologist/media3/FakeAudioOutputRepository.kt index 4eae1e19ee..65d0971c0b 100644 --- a/media/backend-media3/src/test/java/com/google/android/horologist/media3/FakeAudioOutputRepository.kt +++ b/media/backend-media3/src/test/java/com/google/android/horologist/media3/FakeAudioOutputRepository.kt @@ -24,7 +24,7 @@ open class FakeAudioOutputRepository : AudioOutputRepository { override val audioOutput: MutableStateFlow = MutableStateFlow(AudioOutput.None) override val available: MutableStateFlow> = MutableStateFlow(listOf()) - override fun launchOutputSelection(closeOnConnect: Boolean) { + override fun launchOutputSelection(closeOnConnect: Boolean, clientPackageName: String?) { } override fun close() { diff --git a/media/core/api/current.api b/media/core/api/current.api index 17d7cdb77f..d237672c71 100644 --- a/media/core/api/current.api +++ b/media/core/api/current.api @@ -25,19 +25,21 @@ package com.google.android.horologist.media.model { } public final class Media { - ctor public Media(String id, String uri, String title, String artist, optional String? artworkUri, optional Integer? artworkColor, optional java.util.Map extras); + ctor public Media(String id, String uri, String title, String artist, optional String? clientPackageName, optional String? artworkUri, optional Integer? artworkColor, optional java.util.Map extras); method public String component1(); method public String component2(); method public String component3(); method public String component4(); method public String? component5(); - method public Integer? component6(); - method public java.util.Map component7(); - method public com.google.android.horologist.media.model.Media copy(String id, String uri, String title, String artist, String? artworkUri, Integer? artworkColor, java.util.Map extras); + method public String? component6(); + method public Integer? component7(); + method public java.util.Map component8(); + method public com.google.android.horologist.media.model.Media copy(String id, String uri, String title, String artist, String? clientPackageName, String? artworkUri, Integer? artworkColor, java.util.Map extras); method public boolean equals(Object? other); method public String getArtist(); method public Integer? getArtworkColor(); method public String? getArtworkUri(); + method public String? getClientPackageName(); method public java.util.Map getExtras(); method public String getId(); method public String getTitle(); @@ -47,6 +49,7 @@ package com.google.android.horologist.media.model { property public final String artist; property public final Integer? artworkColor; property public final String? artworkUri; + property public final String? clientPackageName; property public final java.util.Map extras; property public final String id; property public final String title; diff --git a/media/core/src/main/java/com/google/android/horologist/media/model/Media.kt b/media/core/src/main/java/com/google/android/horologist/media/model/Media.kt index 82359fcacb..1be16e585d 100644 --- a/media/core/src/main/java/com/google/android/horologist/media/model/Media.kt +++ b/media/core/src/main/java/com/google/android/horologist/media/model/Media.kt @@ -27,6 +27,7 @@ public data class Media( val uri: String, val title: String, val artist: String, + val clientPackageName: String? = null, val artworkUri: String? = null, val artworkColor: Int? = null, val extras: Map = emptyMap(), diff --git a/media/ui-model/api/current.api b/media/ui-model/api/current.api index d9ad7a3cb1..cdbf246982 100644 --- a/media/ui-model/api/current.api +++ b/media/ui-model/api/current.api @@ -270,22 +270,25 @@ package com.google.android.horologist.media.ui.state.model { } public static final class MediaUiModel.Ready extends com.google.android.horologist.media.ui.state.model.MediaUiModel { - ctor public MediaUiModel.Ready(String id, String title, optional String subtitle, optional com.google.android.horologist.images.base.paintable.Paintable? artwork, optional androidx.compose.ui.graphics.Color? artworkColor, optional com.google.android.horologist.images.base.paintable.Paintable? titleIcon); + ctor public MediaUiModel.Ready(String id, String title, optional String subtitle, optional String? clientPackageName, optional com.google.android.horologist.images.base.paintable.Paintable? artwork, optional androidx.compose.ui.graphics.Color? artworkColor, optional com.google.android.horologist.images.base.paintable.Paintable? titleIcon); method public String component1(); method public String component2(); method public String component3(); - method public com.google.android.horologist.images.base.paintable.Paintable? component4(); - method public androidx.compose.ui.graphics.Color? component5-QN2ZGVo(); - method public com.google.android.horologist.images.base.paintable.Paintable? component6(); - method public com.google.android.horologist.media.ui.state.model.MediaUiModel.Ready copy-gCxFOHY(String id, String title, String subtitle, com.google.android.horologist.images.base.paintable.Paintable? artwork, androidx.compose.ui.graphics.Color? artworkColor, com.google.android.horologist.images.base.paintable.Paintable? titleIcon); + method public String? component4(); + method public com.google.android.horologist.images.base.paintable.Paintable? component5(); + method public androidx.compose.ui.graphics.Color? component6-QN2ZGVo(); + method public com.google.android.horologist.images.base.paintable.Paintable? component7(); + method public com.google.android.horologist.media.ui.state.model.MediaUiModel.Ready copy-lMAxDYE(String id, String title, String subtitle, String? clientPackageName, com.google.android.horologist.images.base.paintable.Paintable? artwork, androidx.compose.ui.graphics.Color? artworkColor, com.google.android.horologist.images.base.paintable.Paintable? titleIcon); method public com.google.android.horologist.images.base.paintable.Paintable? getArtwork(); method public androidx.compose.ui.graphics.Color? getArtworkColor(); + method public String? getClientPackageName(); method public String getId(); method public String getSubtitle(); method public String getTitle(); method public com.google.android.horologist.images.base.paintable.Paintable? getTitleIcon(); property public final com.google.android.horologist.images.base.paintable.Paintable? artwork; property public final androidx.compose.ui.graphics.Color? artworkColor; + property public final String? clientPackageName; property public final String id; property public final String subtitle; property public final String title; diff --git a/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/mapper/MediaUiModelMapper.kt b/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/mapper/MediaUiModelMapper.kt index b81caf6787..46ad902542 100644 --- a/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/mapper/MediaUiModelMapper.kt +++ b/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/mapper/MediaUiModelMapper.kt @@ -39,6 +39,7 @@ public object MediaUiModelMapper { id = media.id, title = title, subtitle = artist, + clientPackageName = media.clientPackageName, artwork = media.artworkUri?.let { CoilPaintable(it) }, artworkColor = media.artworkColor?.let { Color(it) }, ) diff --git a/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/model/MediaUiModel.kt b/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/model/MediaUiModel.kt index 555b92cd9d..3d0db5f09a 100644 --- a/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/model/MediaUiModel.kt +++ b/media/ui-model/src/main/java/com/google/android/horologist/media/ui/state/model/MediaUiModel.kt @@ -26,6 +26,7 @@ public sealed class MediaUiModel { val id: String, val title: String, val subtitle: String = "", + val clientPackageName: String? = null, val artwork: Paintable? = null, val artworkColor: Color? = null, val titleIcon: Paintable? = null, diff --git a/media/ui/src/test/java/com/google/android/horologist/test/toolbox/testdoubles/FakeAudioOutputRepository.kt b/media/ui/src/test/java/com/google/android/horologist/test/toolbox/testdoubles/FakeAudioOutputRepository.kt index 18c3e66f87..b2763cddc6 100644 --- a/media/ui/src/test/java/com/google/android/horologist/test/toolbox/testdoubles/FakeAudioOutputRepository.kt +++ b/media/ui/src/test/java/com/google/android/horologist/test/toolbox/testdoubles/FakeAudioOutputRepository.kt @@ -24,7 +24,7 @@ class FakeAudioOutputRepository : AudioOutputRepository { override val audioOutput: MutableStateFlow = MutableStateFlow(AudioOutput.None) override val available: MutableStateFlow> = MutableStateFlow(listOf()) - override fun launchOutputSelection(closeOnConnect: Boolean) { + override fun launchOutputSelection(closeOnConnect: Boolean, clientPackageName: String?) { } override fun close() {