Skip to content

Commit 56bc779

Browse files
committed
MediaRouterService binds services when necessary
MediaRouterService maintained bindings to provider services once those are established. With this CL, it only binds services when there is a non-empty discovery preference set by a foreground app or an app is casting. This change may break output switcher, which enables transfer media of background apps. To alleviate that MediaRouter2Manager#startScan and #stopScan are added so that system UI can force the service bind to the services and find remote devices to cast. Bug: 169575701 Bug: 172920557 Test: manually and CTS Change-Id: I4a47fdb1c9fe05a04d26950485833c9cbfb91a69 (cherry picked from commit 9f889ca4e62044900004cb7ce4e85415d2b019e2) (cherry picked from commit 602b168f99b00c037191234a85190d845680aa64)
1 parent 6592972 commit 56bc779

13 files changed

Lines changed: 206 additions & 19 deletions

File tree

media/java/android/media/IMediaRouterService.aidl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ interface IMediaRouterService {
7373
void unregisterManager(IMediaRouter2Manager manager);
7474
void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId,
7575
in MediaRoute2Info route, int volume);
76+
void startScan(IMediaRouter2Manager manager);
77+
void stopScan(IMediaRouter2Manager manager);
7678

7779
void requestCreateSessionWithManager(IMediaRouter2Manager manager, int requestId,
7880
in RoutingSessionInfo oldSession, in @nullable MediaRoute2Info route);

media/java/android/media/MediaRouter2Manager.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,36 @@ public void unregisterCallback(@NonNull Callback callback) {
146146
}
147147
}
148148

149+
/**
150+
* Starts scanning remote routes.
151+
* @see #stopScan(String)
152+
*/
153+
public void startScan() {
154+
Client client = getOrCreateClient();
155+
if (client != null) {
156+
try {
157+
mMediaRouterService.startScan(client);
158+
} catch (RemoteException ex) {
159+
Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
160+
}
161+
}
162+
}
163+
164+
/**
165+
* Stops scanning remote routes to reduce resource consumption.
166+
* @see #startScan(String)
167+
*/
168+
public void stopScan() {
169+
Client client = getOrCreateClient();
170+
if (client != null) {
171+
try {
172+
mMediaRouterService.stopScan(client);
173+
} catch (RemoteException ex) {
174+
Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
175+
}
176+
}
177+
}
178+
149179
/**
150180
* Gets a {@link android.media.session.MediaController} associated with the
151181
* given routing session.

media/java/android/media/RouteDiscoveryPreference.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ public boolean equals(Object o) {
153153
return false;
154154
}
155155
RouteDiscoveryPreference other = (RouteDiscoveryPreference) o;
156+
//TODO: Make this order-free
156157
return Objects.equals(mPreferredFeatures, other.mPreferredFeatures)
157158
&& mShouldPerformActiveScan == other.mShouldPerformActiveScan;
158159
}

packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.graphics.drawable.Icon;
2525
import android.media.MediaMetadata;
2626
import android.media.MediaRoute2Info;
27+
import android.media.MediaRouter2Manager;
2728
import android.media.RoutingSessionInfo;
2829
import android.media.session.MediaController;
2930
import android.media.session.MediaSessionManager;
@@ -76,6 +77,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
7677
private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
7778
private final boolean mAboveStatusbar;
7879
private final NotificationEntryManager mNotificationEntryManager;
80+
private final MediaRouter2Manager mRouterManager;
7981
@VisibleForTesting
8082
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
8183

@@ -92,7 +94,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
9294
public MediaOutputController(@NonNull Context context, String packageName,
9395
boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
9496
lbm, ShadeController shadeController, ActivityStarter starter,
95-
NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger) {
97+
NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger,
98+
MediaRouter2Manager routerManager) {
9699
mContext = context;
97100
mPackageName = packageName;
98101
mMediaSessionManager = mediaSessionManager;
@@ -104,6 +107,7 @@ public MediaOutputController(@NonNull Context context, String packageName,
104107
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
105108
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
106109
mUiEventLogger = uiEventLogger;
110+
mRouterManager = routerManager;
107111
}
108112

109113
void start(@NonNull Callback cb) {
@@ -134,6 +138,9 @@ void start(@NonNull Callback cb) {
134138
mLocalMediaManager.stopScan();
135139
mLocalMediaManager.registerCallback(this);
136140
mLocalMediaManager.startScan();
141+
if (mRouterManager != null) {
142+
mRouterManager.startScan();
143+
}
137144
}
138145

139146
void stop() {
@@ -144,6 +151,9 @@ void stop() {
144151
mLocalMediaManager.unregisterCallback(this);
145152
mLocalMediaManager.stopScan();
146153
}
154+
if (mRouterManager != null) {
155+
mRouterManager.stopScan();
156+
}
147157
mMediaDevices.clear();
148158
}
149159

packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.android.systemui.media.dialog
1818

1919
import android.content.Context
2020
import android.media.session.MediaSessionManager
21+
import android.media.MediaRouter2Manager
2122
import com.android.internal.logging.UiEventLogger
2223
import com.android.settingslib.bluetooth.LocalBluetoothManager
2324
import com.android.systemui.plugins.ActivityStarter
@@ -35,7 +36,8 @@ class MediaOutputDialogFactory @Inject constructor(
3536
private val shadeController: ShadeController,
3637
private val starter: ActivityStarter,
3738
private val notificationEntryManager: NotificationEntryManager,
38-
private val uiEventLogger: UiEventLogger
39+
private val uiEventLogger: UiEventLogger,
40+
private val routerManager: MediaRouter2Manager
3941
) {
4042
companion object {
4143
var mediaOutputDialog: MediaOutputDialog? = null
@@ -46,7 +48,7 @@ class MediaOutputDialogFactory @Inject constructor(
4648
mediaOutputDialog?.dismiss()
4749
mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar,
4850
mediaSessionManager, lbm, shadeController, starter, notificationEntryManager,
49-
uiEventLogger).run {
51+
uiEventLogger, routerManager).run {
5052
MediaOutputDialog(context, aboveStatusBar, this, uiEventLogger)
5153
}
5254
}

packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static org.mockito.Mockito.when;
2525

2626
import android.content.Context;
27+
import android.media.MediaRouter2Manager;
2728
import android.media.session.MediaSessionManager;
2829
import android.os.Bundle;
2930
import android.testing.AndroidTestingRunner;
@@ -63,6 +64,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
6364
private NotificationEntryManager mNotificationEntryManager =
6465
mock(NotificationEntryManager.class);
6566
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
67+
private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
6668

6769
private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
6870
private MediaOutputController mMediaOutputController;
@@ -75,7 +77,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
7577
public void setUp() {
7678
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
7779
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
78-
mNotificationEntryManager, mUiEventLogger);
80+
mNotificationEntryManager, mUiEventLogger, mRouterManager);
7981
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
8082
mMediaOutputController);
8183
mMediaOutputBaseDialogImpl.onCreate(new Bundle());

packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import android.graphics.drawable.Icon;
3333
import android.media.MediaDescription;
3434
import android.media.MediaMetadata;
35+
import android.media.MediaRouter2Manager;
3536
import android.media.RoutingSessionInfo;
3637
import android.media.session.MediaController;
3738
import android.media.session.MediaSessionManager;
@@ -91,6 +92,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
9192
private NotificationEntryManager mNotificationEntryManager =
9293
mock(NotificationEntryManager.class);
9394
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
95+
private final MediaRouter2Manager mRouter2Manager = mock(MediaRouter2Manager.class);
9496

9597
private Context mSpyContext;
9698
private MediaOutputController mMediaOutputController;
@@ -113,7 +115,7 @@ public void setUp() {
113115

114116
mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
115117
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
116-
mNotificationEntryManager, mUiEventLogger);
118+
mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
117119
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
118120
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
119121
MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -157,7 +159,7 @@ public void start_withPackageName_verifyMediaControllerInit() {
157159
public void start_withoutPackageName_verifyMediaControllerInit() {
158160
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
159161
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
160-
mNotificationEntryManager, mUiEventLogger);
162+
mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
161163

162164
mMediaOutputController.start(mCb);
163165

@@ -178,7 +180,7 @@ public void stop_withPackageName_verifyMediaControllerDeinit() {
178180
public void stop_withoutPackageName_verifyMediaControllerDeinit() {
179181
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
180182
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
181-
mNotificationEntryManager, mUiEventLogger);
183+
mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
182184

183185
mMediaOutputController.start(mCb);
184186

@@ -449,7 +451,7 @@ public void getGroupMediaDevices_newDevice_verifyDeviceOrder() {
449451
public void getNotificationLargeIcon_withoutPackageName_returnsNull() {
450452
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
451453
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
452-
mNotificationEntryManager, mUiEventLogger);
454+
mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
453455

454456
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
455457
}

packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static org.mockito.Mockito.when;
2525

2626
import android.media.MediaRoute2Info;
27+
import android.media.MediaRouter2Manager;
2728
import android.media.session.MediaSessionManager;
2829
import android.testing.AndroidTestingRunner;
2930
import android.testing.TestableLooper;
@@ -64,6 +65,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
6465
private final NotificationEntryManager mNotificationEntryManager =
6566
mock(NotificationEntryManager.class);
6667
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
68+
private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
6769

6870
private MediaOutputDialog mMediaOutputDialog;
6971
private MediaOutputController mMediaOutputController;
@@ -73,7 +75,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
7375
public void setUp() {
7476
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
7577
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
76-
mNotificationEntryManager, mUiEventLogger);
78+
mNotificationEntryManager, mUiEventLogger, mRouterManager);
7779
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
7880
mMediaOutputDialog = new MediaOutputDialog(mContext, false,
7981
mMediaOutputController, mUiEventLogger);

packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.mockito.Mockito.mock;
2222
import static org.mockito.Mockito.when;
2323

24+
import android.media.MediaRouter2Manager;
2425
import android.media.session.MediaSessionManager;
2526
import android.testing.AndroidTestingRunner;
2627
import android.testing.TestableLooper;
@@ -64,6 +65,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase {
6465
private NotificationEntryManager mNotificationEntryManager =
6566
mock(NotificationEntryManager.class);
6667
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
68+
private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
6769

6870
private MediaOutputGroupDialog mMediaOutputGroupDialog;
6971
private MediaOutputController mMediaOutputController;
@@ -73,7 +75,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase {
7375
public void setUp() {
7476
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
7577
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
76-
mNotificationEntryManager, mUiEventLogger);
78+
mNotificationEntryManager, mUiEventLogger, mRouterManager);
7779
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
7880
mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false,
7981
mMediaOutputController);

services/core/java/com/android/server/media/MediaRoute2Provider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public MediaRoute2ProviderInfo getProviderInfo() {
7777
@NonNull
7878
public List<RoutingSessionInfo> getSessionInfos() {
7979
synchronized (mLock) {
80-
return mSessionInfos;
80+
return new ArrayList<>(mSessionInfos);
8181
}
8282
}
8383

0 commit comments

Comments
 (0)