Get media devices for each media application
Each player, with a separate pacakge name, needs to register a listener with its own LocalMediaManager object constructed with that package name. An issue with this change is that it assumes that the app package for the player never changes, which is a bad assumption for the mini player. Luckily, the mini player doesn't show an output switcher, currently. Fixes: 152469562 Test: manual -- play demo app and switch output to cast device. Verify that media player shows name of cast device. Test: manual -- while casting, play music from another app. Verify that the media player shows phone speaker while the cast app shows cast device. Change-Id: Ica508d1b2f1dc51a28027604418c2a4f8d64aa13
This commit is contained in:
@@ -44,9 +44,11 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||
|
||||
import com.android.settingslib.media.LocalMediaManager;
|
||||
import com.android.settingslib.media.MediaDevice;
|
||||
import com.android.settingslib.media.MediaOutputSliceConstants;
|
||||
import com.android.settingslib.widget.AdaptiveIcon;
|
||||
@@ -66,6 +68,7 @@ import java.util.concurrent.Executor;
|
||||
public class MediaControlPanel {
|
||||
private static final String TAG = "MediaControlPanel";
|
||||
private final NotificationMediaManager mMediaManager;
|
||||
@Nullable private final LocalMediaManager mLocalMediaManager;
|
||||
private final Executor mForegroundExecutor;
|
||||
private final Executor mBackgroundExecutor;
|
||||
|
||||
@@ -77,6 +80,7 @@ public class MediaControlPanel {
|
||||
private int mForegroundColor;
|
||||
private int mBackgroundColor;
|
||||
protected ComponentName mRecvComponent;
|
||||
private MediaDevice mDevice;
|
||||
private boolean mIsRegistered = false;
|
||||
|
||||
private final int[] mActionIds;
|
||||
@@ -121,19 +125,44 @@ public class MediaControlPanel {
|
||||
}
|
||||
};
|
||||
|
||||
private final LocalMediaManager.DeviceCallback mDeviceCallback =
|
||||
new LocalMediaManager.DeviceCallback() {
|
||||
@Override
|
||||
public void onDeviceListUpdate(List<MediaDevice> devices) {
|
||||
if (mLocalMediaManager == null) {
|
||||
return;
|
||||
}
|
||||
MediaDevice currentDevice = mLocalMediaManager.getCurrentConnectedDevice();
|
||||
// Check because this can be called several times while changing devices
|
||||
if (mDevice == null || !mDevice.equals(currentDevice)) {
|
||||
mDevice = currentDevice;
|
||||
updateDevice(mDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
|
||||
if (mDevice == null || !mDevice.equals(device)) {
|
||||
mDevice = device;
|
||||
updateDevice(mDevice);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize a new control panel
|
||||
* @param context
|
||||
* @param parent
|
||||
* @param manager
|
||||
* @param routeManager Manager used to listen for device change events.
|
||||
* @param layoutId layout resource to use for this control panel
|
||||
* @param actionIds resource IDs for action buttons in the layout
|
||||
* @param foregroundExecutor foreground executor
|
||||
* @param backgroundExecutor background executor, used for processing artwork
|
||||
*/
|
||||
public MediaControlPanel(Context context, ViewGroup parent, NotificationMediaManager manager,
|
||||
@LayoutRes int layoutId, int[] actionIds, Executor foregroundExecutor,
|
||||
Executor backgroundExecutor) {
|
||||
@Nullable LocalMediaManager routeManager, @LayoutRes int layoutId, int[] actionIds,
|
||||
Executor foregroundExecutor, Executor backgroundExecutor) {
|
||||
mContext = context;
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
mMediaNotifView = (LinearLayout) inflater.inflate(layoutId, parent, false);
|
||||
@@ -144,6 +173,7 @@ public class MediaControlPanel {
|
||||
// mStateListener to be unregistered in detach.
|
||||
mMediaNotifView.addOnAttachStateChangeListener(mStateListener);
|
||||
mMediaManager = manager;
|
||||
mLocalMediaManager = routeManager;
|
||||
mActionIds = actionIds;
|
||||
mForegroundExecutor = foregroundExecutor;
|
||||
mBackgroundExecutor = backgroundExecutor;
|
||||
@@ -176,7 +206,7 @@ public class MediaControlPanel {
|
||||
* @param device
|
||||
*/
|
||||
public void setMediaSession(MediaSession.Token token, Icon icon, int iconColor,
|
||||
int bgColor, PendingIntent contentIntent, String appNameString, MediaDevice device) {
|
||||
int bgColor, PendingIntent contentIntent, String appNameString) {
|
||||
mToken = token;
|
||||
mForegroundColor = iconColor;
|
||||
mBackgroundColor = bgColor;
|
||||
@@ -253,9 +283,9 @@ public class MediaControlPanel {
|
||||
|
||||
// Transfer chip
|
||||
mSeamless = mMediaNotifView.findViewById(R.id.media_seamless);
|
||||
if (mSeamless != null) {
|
||||
if (mSeamless != null && mLocalMediaManager != null) {
|
||||
mSeamless.setVisibility(View.VISIBLE);
|
||||
updateDevice(device);
|
||||
updateDevice(mLocalMediaManager.getCurrentConnectedDevice());
|
||||
ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
|
||||
mSeamless.setOnClickListener(v -> {
|
||||
final Intent intent = new Intent()
|
||||
@@ -366,7 +396,7 @@ public class MediaControlPanel {
|
||||
* Update the current device information
|
||||
* @param device device information to display
|
||||
*/
|
||||
public void updateDevice(MediaDevice device) {
|
||||
private void updateDevice(MediaDevice device) {
|
||||
if (mSeamless == null) {
|
||||
return;
|
||||
}
|
||||
@@ -456,6 +486,10 @@ public class MediaControlPanel {
|
||||
Assert.isMainThread();
|
||||
if (!mIsRegistered) {
|
||||
mMediaManager.addCallback(mMediaListener);
|
||||
if (mLocalMediaManager != null) {
|
||||
mLocalMediaManager.registerCallback(mDeviceCallback);
|
||||
mLocalMediaManager.startScan();
|
||||
}
|
||||
mIsRegistered = true;
|
||||
}
|
||||
}
|
||||
@@ -463,6 +497,10 @@ public class MediaControlPanel {
|
||||
private void makeInactive() {
|
||||
Assert.isMainThread();
|
||||
if (mIsRegistered) {
|
||||
if (mLocalMediaManager != null) {
|
||||
mLocalMediaManager.stopScan();
|
||||
mLocalMediaManager.unregisterCallback(mDeviceCallback);
|
||||
}
|
||||
mMediaManager.removeCallback(mMediaListener);
|
||||
mIsRegistered = false;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settingslib.media.MediaDevice;
|
||||
import com.android.settingslib.media.LocalMediaManager;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.media.MediaControlPanel;
|
||||
import com.android.systemui.media.SeekBarObserver;
|
||||
@@ -74,9 +74,10 @@ public class QSMediaPlayer extends MediaControlPanel {
|
||||
* @param backgroundExecutor
|
||||
*/
|
||||
public QSMediaPlayer(Context context, ViewGroup parent, NotificationMediaManager manager,
|
||||
Executor foregroundExecutor, DelayableExecutor backgroundExecutor) {
|
||||
super(context, parent, manager, R.layout.qs_media_panel, QS_ACTION_IDS, foregroundExecutor,
|
||||
backgroundExecutor);
|
||||
LocalMediaManager routeManager, Executor foregroundExecutor,
|
||||
DelayableExecutor backgroundExecutor) {
|
||||
super(context, parent, manager, routeManager, R.layout.qs_media_panel, QS_ACTION_IDS,
|
||||
foregroundExecutor, backgroundExecutor);
|
||||
mParent = (QSPanel) parent;
|
||||
mBackgroundExecutor = backgroundExecutor;
|
||||
mSeekBarViewModel = new SeekBarViewModel(backgroundExecutor);
|
||||
@@ -101,12 +102,12 @@ public class QSMediaPlayer extends MediaControlPanel {
|
||||
* @param device current playback device
|
||||
*/
|
||||
public void setMediaSession(MediaSession.Token token, Icon icon, int iconColor,
|
||||
int bgColor, View actionsContainer, Notification notif, MediaDevice device) {
|
||||
int bgColor, View actionsContainer, Notification notif) {
|
||||
|
||||
String appName = Notification.Builder.recoverBuilder(getContext(), notif)
|
||||
.loadHeaderAppName();
|
||||
super.setMediaSession(token, icon, iconColor, bgColor, notif.contentIntent,
|
||||
appName, device);
|
||||
appName);
|
||||
|
||||
// Media controls
|
||||
LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
|
||||
|
||||
@@ -47,7 +47,6 @@ import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.media.InfoMediaManager;
|
||||
import com.android.settingslib.media.LocalMediaManager;
|
||||
import com.android.settingslib.media.MediaDevice;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.R;
|
||||
@@ -75,7 +74,6 @@ import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -105,8 +103,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
private final LocalBluetoothManager mLocalBluetoothManager;
|
||||
private final Executor mForegroundExecutor;
|
||||
private final DelayableExecutor mBackgroundExecutor;
|
||||
private LocalMediaManager mLocalMediaManager;
|
||||
private MediaDevice mDevice;
|
||||
private boolean mUpdateCarousel = false;
|
||||
|
||||
protected boolean mExpanded;
|
||||
@@ -130,34 +126,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
private BrightnessMirrorController mBrightnessMirrorController;
|
||||
private View mDivider;
|
||||
|
||||
private final LocalMediaManager.DeviceCallback mDeviceCallback =
|
||||
new LocalMediaManager.DeviceCallback() {
|
||||
@Override
|
||||
public void onDeviceListUpdate(List<MediaDevice> devices) {
|
||||
if (mLocalMediaManager == null) {
|
||||
return;
|
||||
}
|
||||
MediaDevice currentDevice = mLocalMediaManager.getCurrentConnectedDevice();
|
||||
// Check because this can be called several times while changing devices
|
||||
if (mDevice == null || !mDevice.equals(currentDevice)) {
|
||||
mDevice = currentDevice;
|
||||
for (QSMediaPlayer p : mMediaPlayers) {
|
||||
p.updateDevice(mDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
|
||||
if (mDevice == null || !mDevice.equals(device)) {
|
||||
mDevice = device;
|
||||
for (QSMediaPlayer p : mMediaPlayers) {
|
||||
p.updateDevice(mDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public QSPanel(
|
||||
@Named(VIEW_CONTEXT) Context context,
|
||||
@@ -277,7 +245,14 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
|
||||
if (player == null) {
|
||||
Log.d(TAG, "creating new player");
|
||||
player = new QSMediaPlayer(mContext, this, mNotificationMediaManager,
|
||||
// Set up listener for device changes
|
||||
// TODO: integrate with MediaTransferManager?
|
||||
InfoMediaManager imm = new InfoMediaManager(mContext, notif.getPackageName(),
|
||||
notif.getNotification(), mLocalBluetoothManager);
|
||||
LocalMediaManager routeManager = new LocalMediaManager(mContext, mLocalBluetoothManager,
|
||||
imm, notif.getPackageName());
|
||||
|
||||
player = new QSMediaPlayer(mContext, this, mNotificationMediaManager, routeManager,
|
||||
mForegroundExecutor, mBackgroundExecutor);
|
||||
player.setListening(mListening);
|
||||
if (player.isPlaying()) {
|
||||
@@ -292,22 +267,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
|
||||
Log.d(TAG, "setting player session");
|
||||
player.setMediaSession(token, icon, iconColor, bgColor, actionsContainer,
|
||||
notif.getNotification(), mDevice);
|
||||
notif.getNotification());
|
||||
|
||||
if (mMediaPlayers.size() > 0) {
|
||||
((View) mMediaCarousel.getParent()).setVisibility(View.VISIBLE);
|
||||
|
||||
if (mLocalMediaManager == null) {
|
||||
// Set up listener for device changes
|
||||
// TODO: integrate with MediaTransferManager?
|
||||
InfoMediaManager imm =
|
||||
new InfoMediaManager(mContext, null, null, mLocalBluetoothManager);
|
||||
mLocalMediaManager = new LocalMediaManager(mContext, mLocalBluetoothManager, imm,
|
||||
null);
|
||||
mLocalMediaManager.startScan();
|
||||
mDevice = mLocalMediaManager.getCurrentConnectedDevice();
|
||||
mLocalMediaManager.registerCallback(mDeviceCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,11 +293,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
mMediaCarousel.removeView(player.getView());
|
||||
if (mMediaPlayers.size() == 0) {
|
||||
((View) mMediaCarousel.getParent()).setVisibility(View.GONE);
|
||||
if (mLocalMediaManager != null) {
|
||||
mLocalMediaManager.stopScan();
|
||||
mLocalMediaManager.unregisterCallback(mDeviceCallback);
|
||||
mLocalMediaManager = null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -404,11 +362,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
mBrightnessMirrorController.removeCallback(this);
|
||||
}
|
||||
mDumpManager.unregisterDumpable(getDumpableTag());
|
||||
if (mLocalMediaManager != null) {
|
||||
mLocalMediaManager.stopScan();
|
||||
mLocalMediaManager.unregisterCallback(mDeviceCallback);
|
||||
mLocalMediaManager = null;
|
||||
}
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public class QuickQSMediaPlayer extends MediaControlPanel {
|
||||
*/
|
||||
public QuickQSMediaPlayer(Context context, ViewGroup parent, NotificationMediaManager manager,
|
||||
Executor foregroundExecutor, Executor backgroundExecutor) {
|
||||
super(context, parent, manager, R.layout.qqs_media_panel, QQS_ACTION_IDS,
|
||||
super(context, parent, manager, null, R.layout.qqs_media_panel, QQS_ACTION_IDS,
|
||||
foregroundExecutor, backgroundExecutor);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class QuickQSMediaPlayer extends MediaControlPanel {
|
||||
return;
|
||||
}
|
||||
|
||||
super.setMediaSession(token, icon, iconColor, bgColor, contentIntent, null, null);
|
||||
super.setMediaSession(token, icon, iconColor, bgColor, contentIntent, null);
|
||||
|
||||
LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
|
||||
int i = 0;
|
||||
|
||||
Reference in New Issue
Block a user