Expose an Output Switcher dialog for system routing
The new dialog will hide app and playback related metadata and will
only control system routing.
Test: adb shell am broadcast -a com.android.systemui.action.LAUNCH_SYSTEM_MEDIA_OUTPUT_DIALOG com.android.systemui
Bug: 284227163
Flag: NA
Change-Id: I13bbcfe9c5446e41f722a154b7740d2c472afad4
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 5dacba5..52b51d7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -413,12 +413,8 @@
*/
@NonNull
List<MediaDevice> getSelectedMediaDevices() {
- if (TextUtils.isEmpty(mPackageName)) {
- Log.w(TAG, "getSelectedMediaDevices() package name is null or empty!");
- return Collections.emptyList();
- }
+ RoutingSessionInfo info = getRoutingSessionInfo();
- final RoutingSessionInfo info = getRoutingSessionInfo();
if (info == null) {
Log.w(TAG, "getSelectedMediaDevices() cannot find selectable MediaDevice from : "
+ mPackageName);
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
index 3514932..02ec90d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
@@ -48,6 +48,17 @@
"com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG";
/**
+ * An intent action to launch a media output dialog without any app or playback metadata, which
+ * only controls system routing.
+ *
+ * <p>System routes are those provided by the system, such as built-in speakers, wired headsets,
+ * bluetooth devices, and other outputs that require the app to feed media samples to the
+ * framework.
+ */
+ public static final String ACTION_LAUNCH_SYSTEM_MEDIA_OUTPUT_DIALOG =
+ "com.android.systemui.action.LAUNCH_SYSTEM_MEDIA_OUTPUT_DIALOG";
+
+ /**
* An intent action to launch media output broadcast dialog.
*/
public static final String ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG =
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e218308..0a71cda 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1044,6 +1044,7 @@
android:exported="true">
<intent-filter android:priority="1">
<action android:name="com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG" />
+ <action android:name="com.android.systemui.action.LAUNCH_SYSTEM_MEDIA_OUTPUT_DIALOG" />
<action android:name="com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG" />
<action android:name="com.android.systemui.action.DISMISS_MEDIA_OUTPUT_DIALOG" />
</intent-filter>
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 0c5a14f..48f432e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -58,8 +58,8 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.systemui.res.R;
import com.android.systemui.broadcast.BroadcastSender;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.util.concurrent.Executor;
@@ -85,6 +85,13 @@
final MediaOutputController mMediaOutputController;
final BroadcastSender mBroadcastSender;
+ /**
+ * Signals whether the dialog should NOT show app-related metadata.
+ *
+ * <p>A metadata-less dialog hides the title, subtitle, and app icon in the header.
+ */
+ private final boolean mIncludePlaybackAndAppMetadata;
+
@VisibleForTesting
View mDialogView;
private TextView mHeaderTitle;
@@ -210,8 +217,11 @@
}
}
- public MediaOutputBaseDialog(Context context, BroadcastSender broadcastSender,
- MediaOutputController mediaOutputController) {
+ public MediaOutputBaseDialog(
+ Context context,
+ BroadcastSender broadcastSender,
+ MediaOutputController mediaOutputController,
+ boolean includePlaybackAndAppMetadata) {
super(context, R.style.Theme_SystemUI_Dialog_Media);
// Save the context that is wrapped with our theme.
@@ -226,6 +236,7 @@
mListPaddingTop = mContext.getResources().getDimensionPixelSize(
R.dimen.media_output_dialog_list_padding_top);
mExecutor = Executors.newSingleThreadExecutor();
+ mIncludePlaybackAndAppMetadata = includePlaybackAndAppMetadata;
}
@Override
@@ -354,7 +365,10 @@
updateDialogBackgroundColor();
mHeaderIcon.setVisibility(View.GONE);
}
- if (appSourceIcon != null) {
+
+ if (!mIncludePlaybackAndAppMetadata) {
+ mAppResourceIcon.setVisibility(View.GONE);
+ } else if (appSourceIcon != null) {
Icon appIcon = appSourceIcon.toIcon(mContext);
mAppResourceIcon.setColorFilter(mMediaOutputController.getColorItemContent());
mAppResourceIcon.setImageIcon(appIcon);
@@ -373,17 +387,24 @@
mHeaderIcon.setLayoutParams(new LinearLayout.LayoutParams(size + padding, size));
}
mAppButton.setText(mMediaOutputController.getAppSourceName());
- // Update title and subtitle
- mHeaderTitle.setText(getHeaderText());
- final CharSequence subTitle = getHeaderSubtitle();
- if (TextUtils.isEmpty(subTitle)) {
+
+ if (!mIncludePlaybackAndAppMetadata) {
+ mHeaderTitle.setVisibility(View.GONE);
mHeaderSubtitle.setVisibility(View.GONE);
- mHeaderTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
} else {
- mHeaderSubtitle.setVisibility(View.VISIBLE);
- mHeaderSubtitle.setText(subTitle);
- mHeaderTitle.setGravity(Gravity.NO_GRAVITY);
+ // Update title and subtitle
+ mHeaderTitle.setText(getHeaderText());
+ final CharSequence subTitle = getHeaderSubtitle();
+ if (TextUtils.isEmpty(subTitle)) {
+ mHeaderSubtitle.setVisibility(View.GONE);
+ mHeaderTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
+ } else {
+ mHeaderSubtitle.setVisibility(View.VISIBLE);
+ mHeaderSubtitle.setText(subTitle);
+ mHeaderTitle.setGravity(Gravity.NO_GRAVITY);
+ }
}
+
// Show when remote media session is available or
// when the device supports BT LE audio + media is playing
mStopButton.setVisibility(getStopButtonVisibility());
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
index ac64300..8e0191e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
@@ -42,12 +42,10 @@
import androidx.core.graphics.drawable.IconCompat;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.settingslib.media.BluetoothMediaDevice;
-import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.qrcode.QrCodeGenerator;
-import com.android.systemui.res.R;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.google.zxing.WriterException;
@@ -237,7 +235,11 @@
MediaOutputBroadcastDialog(Context context, boolean aboveStatusbar,
BroadcastSender broadcastSender, MediaOutputController mediaOutputController) {
- super(context, broadcastSender, mediaOutputController);
+ super(
+ context,
+ broadcastSender,
+ mediaOutputController, /* includePlaybackAndAppMetadata */
+ true);
mAdapter = new MediaOutputAdapter(mMediaOutputController);
// TODO(b/226710953): Move the part to MediaOutputBaseDialog for every class
// that extends MediaOutputBaseDialog
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 426a497..375a0ce 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -78,7 +78,6 @@
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.utils.ThreadUtils;
-import com.android.systemui.res.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastSender;
@@ -86,6 +85,7 @@
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
import com.android.systemui.monet.ColorScheme;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -358,7 +358,7 @@
}
Drawable getAppSourceIconFromPackage() {
- if (mPackageName.isEmpty()) {
+ if (TextUtils.isEmpty(mPackageName)) {
return null;
}
try {
@@ -372,7 +372,7 @@
}
String getAppSourceName() {
- if (mPackageName.isEmpty()) {
+ if (TextUtils.isEmpty(mPackageName)) {
return null;
}
final PackageManager packageManager = mContext.getPackageManager();
@@ -391,7 +391,7 @@
}
Intent getAppLaunchIntent() {
- if (mPackageName.isEmpty()) {
+ if (TextUtils.isEmpty(mPackageName)) {
return null;
}
return mContext.getPackageManager().getLaunchIntentForPackage(mPackageName);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
index 4640a5d..d40699c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
@@ -27,10 +27,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.res.R;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
/**
* Dialog for media output transferring.
@@ -40,10 +40,15 @@
private final DialogLaunchAnimator mDialogLaunchAnimator;
private final UiEventLogger mUiEventLogger;
- MediaOutputDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender,
- MediaOutputController mediaOutputController, DialogLaunchAnimator dialogLaunchAnimator,
- UiEventLogger uiEventLogger) {
- super(context, broadcastSender, mediaOutputController);
+ MediaOutputDialog(
+ Context context,
+ boolean aboveStatusbar,
+ BroadcastSender broadcastSender,
+ MediaOutputController mediaOutputController,
+ DialogLaunchAnimator dialogLaunchAnimator,
+ UiEventLogger uiEventLogger,
+ boolean includePlaybackAndAppMetadata) {
+ super(context, broadcastSender, mediaOutputController, includePlaybackAndAppMetadata);
mDialogLaunchAnimator = dialogLaunchAnimator;
mUiEventLogger = uiEventLogger;
mAdapter = new MediaOutputAdapter(mMediaOutputController);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index 2b38edb..b04a7a4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -61,6 +61,19 @@
/** Creates a [MediaOutputDialog] for the given package. */
open fun create(packageName: String, aboveStatusBar: Boolean, view: View? = null) {
+ create(packageName, aboveStatusBar, view, includePlaybackAndAppMetadata = true)
+ }
+
+ open fun createDialogForSystemRouting() {
+ create(packageName = null, aboveStatusBar = false, includePlaybackAndAppMetadata = false)
+ }
+
+ private fun create(
+ packageName: String?,
+ aboveStatusBar: Boolean,
+ view: View? = null,
+ includePlaybackAndAppMetadata: Boolean = true
+ ) {
// Dismiss the previous dialog, if any.
mediaOutputDialog?.dismiss()
@@ -71,7 +84,7 @@
powerExemptionManager, keyGuardManager, featureFlags, userTracker)
val dialog =
MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller,
- dialogLaunchAnimator, uiEventLogger)
+ dialogLaunchAnimator, uiEventLogger, includePlaybackAndAppMetadata)
mediaOutputDialog = dialog
// Show the dialog.
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
index 132bf99..1002cc3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
@@ -19,7 +19,6 @@
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
-import android.text.TextUtils
import android.util.Log
import com.android.settingslib.media.MediaOutputConstants
import javax.inject.Inject
@@ -35,16 +34,16 @@
private val mediaOutputBroadcastDialogFactory: MediaOutputBroadcastDialogFactory
) : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- when {
- TextUtils.equals(
- MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG, intent.action) -> {
+ when (intent.action) {
+ MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG -> {
val packageName: String? =
intent.getStringExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME)
launchMediaOutputDialogIfPossible(packageName)
}
- TextUtils.equals(
- MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG,
- intent.action) -> {
+ MediaOutputConstants.ACTION_LAUNCH_SYSTEM_MEDIA_OUTPUT_DIALOG -> {
+ mediaOutputDialogFactory.createDialogForSystemRouting()
+ }
+ MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG -> {
val packageName: String? =
intent.getStringExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME)
launchMediaOutputBroadcastDialogIfPossible(packageName)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 9dfb5a5..e082ca8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -47,13 +47,13 @@
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -305,7 +305,11 @@
MediaOutputBaseDialogImpl(Context context, BroadcastSender broadcastSender,
MediaOutputController mediaOutputController) {
- super(context, broadcastSender, mediaOutputController);
+ super(
+ context,
+ broadcastSender,
+ mediaOutputController, /* includePlaybackAndAppMetadata */
+ true);
mAdapter = mMediaOutputBaseAdapter;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index 379136b..d5dc502 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -49,13 +49,13 @@
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -394,8 +394,14 @@
@NonNull
private MediaOutputDialog makeTestDialog(MediaOutputController controller) {
- return new MediaOutputDialog(mContext, false, mBroadcastSender,
- controller, mDialogLaunchAnimator, mUiEventLogger);
+ return new MediaOutputDialog(
+ mContext,
+ false,
+ mBroadcastSender,
+ controller,
+ mDialogLaunchAnimator,
+ mUiEventLogger,
+ true);
}
private void withTestDialog(MediaOutputController controller, Consumer<MediaOutputDialog> c) {