Merge changes I363dc391,I84786697,I8d80872d,I4d6aa4d7,I396d376a into tm-qpr-dev
* changes: Simplify MediaRouter2Manager.Client's lifecycle Remove unnecessary if checks Manage scan requests in MediaRouter2Manager Merge tests calling onStart and onStop Fix MediaOutputController resource management
This commit is contained in:
committed by
Android (Google) Code Review
commit
5926e155a3
@@ -48,6 +48,7 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -118,6 +119,7 @@ public final class MediaRouter2 {
|
||||
private final Map<String, RoutingController> mNonSystemRoutingControllers = new ArrayMap<>();
|
||||
|
||||
private final AtomicInteger mNextRequestId = new AtomicInteger(1);
|
||||
private final AtomicBoolean mIsScanning = new AtomicBoolean(/* initialValue= */ false);
|
||||
|
||||
final Handler mHandler;
|
||||
|
||||
@@ -234,7 +236,9 @@ public final class MediaRouter2 {
|
||||
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
|
||||
public void startScan() {
|
||||
if (isSystemRouter()) {
|
||||
sManager.startScan();
|
||||
if (!mIsScanning.getAndSet(true)) {
|
||||
sManager.registerScanRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +264,9 @@ public final class MediaRouter2 {
|
||||
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
|
||||
public void stopScan() {
|
||||
if (isSystemRouter()) {
|
||||
sManager.stopScan();
|
||||
if (mIsScanning.getAndSet(false)) {
|
||||
sManager.unregisterScanRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,9 +79,11 @@ public final class MediaRouter2Manager {
|
||||
final String mPackageName;
|
||||
|
||||
private final Context mContext;
|
||||
@GuardedBy("sLock")
|
||||
private Client mClient;
|
||||
|
||||
private final Client mClient;
|
||||
|
||||
private final IMediaRouterService mMediaRouterService;
|
||||
private final AtomicInteger mScanRequestCount = new AtomicInteger(/* initialValue= */ 0);
|
||||
final Handler mHandler;
|
||||
final CopyOnWriteArrayList<CallbackRecord> mCallbackRecords = new CopyOnWriteArrayList<>();
|
||||
|
||||
@@ -119,7 +121,12 @@ public final class MediaRouter2Manager {
|
||||
.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
||||
mPackageName = mContext.getPackageName();
|
||||
mHandler = new Handler(context.getMainLooper());
|
||||
mHandler.post(this::getOrCreateClient);
|
||||
mClient = new Client();
|
||||
try {
|
||||
mMediaRouterService.registerManager(mClient, mPackageName);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,22 +162,18 @@ public final class MediaRouter2Manager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts scanning remote routes.
|
||||
* <p>
|
||||
* Route discovery can happen even when the {@link #startScan()} is not called.
|
||||
* This is because the scanning could be started before by other apps.
|
||||
* Therefore, calling this method after calling {@link #stopScan()} does not necessarily mean
|
||||
* that the routes found before are removed and added again.
|
||||
* <p>
|
||||
* Use {@link Callback} to get the route related events.
|
||||
* <p>
|
||||
* @see #stopScan()
|
||||
* Registers a request to scan for remote routes.
|
||||
*
|
||||
* <p>Increases the count of active scanning requests. When the count transitions from zero to
|
||||
* one, sends a request to the system server to start scanning.
|
||||
*
|
||||
* <p>Clients must {@link #unregisterScanRequest() unregister their scan requests} when scanning
|
||||
* is no longer needed, to avoid unnecessary resource usage.
|
||||
*/
|
||||
public void startScan() {
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
public void registerScanRequest() {
|
||||
if (mScanRequestCount.getAndIncrement() == 0) {
|
||||
try {
|
||||
mMediaRouterService.startScan(client);
|
||||
mMediaRouterService.startScan(mClient);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -178,23 +181,26 @@ public final class MediaRouter2Manager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops scanning remote routes to reduce resource consumption.
|
||||
* <p>
|
||||
* Route discovery can be continued even after this method is called.
|
||||
* This is because the scanning is only turned off when all the apps stop scanning.
|
||||
* Therefore, calling this method does not necessarily mean the routes are removed.
|
||||
* Also, for the same reason it does not mean that {@link Callback#onRoutesAdded(List)}
|
||||
* is not called afterwards.
|
||||
* <p>
|
||||
* Use {@link Callback} to get the route related events.
|
||||
* Unregisters a scan request made by {@link #registerScanRequest()}.
|
||||
*
|
||||
* @see #startScan()
|
||||
* <p>Decreases the count of active scanning requests. When the count transitions from one to
|
||||
* zero, sends a request to the system server to stop scanning.
|
||||
*
|
||||
* @throws IllegalStateException If called while there are no active scan requests.
|
||||
*/
|
||||
public void stopScan() {
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
public void unregisterScanRequest() {
|
||||
if (mScanRequestCount.updateAndGet(
|
||||
count -> {
|
||||
if (count == 0) {
|
||||
throw new IllegalStateException(
|
||||
"No active scan requests to unregister.");
|
||||
} else {
|
||||
return --count;
|
||||
}
|
||||
})
|
||||
== 0) {
|
||||
try {
|
||||
mMediaRouterService.stopScan(client);
|
||||
mMediaRouterService.stopScan(mClient);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -358,8 +364,7 @@ public final class MediaRouter2Manager {
|
||||
@Nullable
|
||||
public RoutingSessionInfo getSystemRoutingSession(@Nullable String packageName) {
|
||||
try {
|
||||
return mMediaRouterService.getSystemSessionInfoForPackage(
|
||||
getOrCreateClient(), packageName);
|
||||
return mMediaRouterService.getSystemSessionInfoForPackage(mClient, packageName);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -423,15 +428,11 @@ public final class MediaRouter2Manager {
|
||||
*/
|
||||
@NonNull
|
||||
public List<RoutingSessionInfo> getRemoteSessions() {
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
return mMediaRouterService.getRemoteSessions(client);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
return mMediaRouterService.getRemoteSessions(mClient);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,14 +515,11 @@ public final class MediaRouter2Manager {
|
||||
return;
|
||||
}
|
||||
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.setRouteVolumeWithManager(client, requestId, route, volume);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.setRouteVolumeWithManager(mClient, requestId, route, volume);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,15 +541,12 @@ public final class MediaRouter2Manager {
|
||||
return;
|
||||
}
|
||||
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.setSessionVolumeWithManager(
|
||||
client, requestId, sessionInfo.getId(), volume);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.setSessionVolumeWithManager(
|
||||
mClient, requestId, sessionInfo.getId(), volume);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,15 +803,12 @@ public final class MediaRouter2Manager {
|
||||
return;
|
||||
}
|
||||
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.selectRouteWithManager(
|
||||
client, requestId, sessionInfo.getId(), route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.selectRouteWithManager(
|
||||
mClient, requestId, sessionInfo.getId(), route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -850,15 +842,12 @@ public final class MediaRouter2Manager {
|
||||
return;
|
||||
}
|
||||
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.deselectRouteWithManager(
|
||||
client, requestId, sessionInfo.getId(), route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.deselectRouteWithManager(
|
||||
mClient, requestId, sessionInfo.getId(), route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,15 +864,11 @@ public final class MediaRouter2Manager {
|
||||
public void releaseSession(@NonNull RoutingSessionInfo sessionInfo) {
|
||||
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
|
||||
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.releaseSessionWithManager(
|
||||
client, requestId, sessionInfo.getId());
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
int requestId = mNextRequestId.getAndIncrement();
|
||||
mMediaRouterService.releaseSessionWithManager(mClient, requestId, sessionInfo.getId());
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -896,14 +881,11 @@ public final class MediaRouter2Manager {
|
||||
@NonNull MediaRoute2Info route) {
|
||||
int requestId = createTransferRequest(session, route);
|
||||
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
mMediaRouterService.transferToRouteWithManager(
|
||||
client, requestId, session.getId(), route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
mMediaRouterService.transferToRouteWithManager(
|
||||
mClient, requestId, session.getId(), route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,14 +898,11 @@ public final class MediaRouter2Manager {
|
||||
|
||||
int requestId = createTransferRequest(oldSession, route);
|
||||
|
||||
Client client = getOrCreateClient();
|
||||
if (client != null) {
|
||||
try {
|
||||
mMediaRouterService.requestCreateSessionWithManager(
|
||||
client, requestId, oldSession, route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
try {
|
||||
mMediaRouterService.requestCreateSessionWithManager(
|
||||
mClient, requestId, oldSession, route);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -967,22 +946,6 @@ public final class MediaRouter2Manager {
|
||||
sessionInfo.getOwnerPackageName());
|
||||
}
|
||||
|
||||
private Client getOrCreateClient() {
|
||||
synchronized (sLock) {
|
||||
if (mClient != null) {
|
||||
return mClient;
|
||||
}
|
||||
Client client = new Client();
|
||||
try {
|
||||
mMediaRouterService.registerManager(client, mPackageName);
|
||||
mClient = client;
|
||||
return client;
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for receiving events about media routing changes.
|
||||
*/
|
||||
|
||||
@@ -39,6 +39,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.Manifest;
|
||||
@@ -121,7 +122,7 @@ public class MediaRouter2ManagerTest {
|
||||
MediaRouter2ManagerTestActivity.startActivity(mContext);
|
||||
|
||||
mManager = MediaRouter2Manager.getInstance(mContext);
|
||||
mManager.startScan();
|
||||
mManager.registerScanRequest();
|
||||
mRouter2 = MediaRouter2.getInstance(mContext);
|
||||
|
||||
// If we need to support thread pool executors, change this to thread pool executor.
|
||||
@@ -152,7 +153,7 @@ public class MediaRouter2ManagerTest {
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mManager.stopScan();
|
||||
mManager.unregisterScanRequest();
|
||||
|
||||
// order matters (callbacks should be cleared at the last)
|
||||
releaseAllSessions();
|
||||
@@ -818,6 +819,13 @@ public class MediaRouter2ManagerTest {
|
||||
assertFalse(failureLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregisterScanRequest_enforcesANonNegativeCount() {
|
||||
mManager.unregisterScanRequest(); // One request was made in the test setup.
|
||||
assertThrows(IllegalStateException.class, () -> mManager.unregisterScanRequest());
|
||||
mManager.registerScanRequest(); // So that the cleanup doesn't fail.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if getSelectableRoutes and getDeselectableRoutes filter routes based on
|
||||
* selected routes
|
||||
|
||||
@@ -96,14 +96,14 @@ public class InfoMediaManager extends MediaManager {
|
||||
public void startScan() {
|
||||
mMediaDevices.clear();
|
||||
mRouterManager.registerCallback(mExecutor, mMediaRouterCallback);
|
||||
mRouterManager.startScan();
|
||||
mRouterManager.registerScanRequest();
|
||||
refreshDevices();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopScan() {
|
||||
mRouterManager.unregisterCallback(mMediaRouterCallback);
|
||||
mRouterManager.stopScan();
|
||||
mRouterManager.unregisterScanRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -224,15 +224,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
||||
Log.d(TAG, "No media controller for " + mPackageName);
|
||||
}
|
||||
}
|
||||
if (mLocalMediaManager == null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "No local media manager " + mPackageName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
mCallback = cb;
|
||||
mLocalMediaManager.unregisterCallback(this);
|
||||
mLocalMediaManager.stopScan();
|
||||
mLocalMediaManager.registerCallback(this);
|
||||
mLocalMediaManager.startScan();
|
||||
}
|
||||
@@ -254,10 +246,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
||||
if (mMediaController != null) {
|
||||
mMediaController.unregisterCallback(mCb);
|
||||
}
|
||||
if (mLocalMediaManager != null) {
|
||||
mLocalMediaManager.unregisterCallback(this);
|
||||
mLocalMediaManager.stopScan();
|
||||
}
|
||||
mLocalMediaManager.unregisterCallback(this);
|
||||
mLocalMediaManager.stopScan();
|
||||
synchronized (mMediaDevicesLock) {
|
||||
mCachedMediaDevices.clear();
|
||||
mMediaDevices.clear();
|
||||
@@ -661,10 +651,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
||||
return mLocalMediaManager.getCurrentConnectedDevice();
|
||||
}
|
||||
|
||||
private MediaDevice getMediaDeviceById(String id) {
|
||||
return mLocalMediaManager.getMediaDeviceById(new ArrayList<>(mMediaDevices), id);
|
||||
}
|
||||
|
||||
boolean addDeviceToPlayMedia(MediaDevice device) {
|
||||
mMetricLogger.logInteractionExpansion(device);
|
||||
return mLocalMediaManager.addDeviceToPlayMedia(device);
|
||||
@@ -686,10 +672,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
||||
return mLocalMediaManager.getDeselectableMediaDevice();
|
||||
}
|
||||
|
||||
void adjustSessionVolume(String sessionId, int volume) {
|
||||
mLocalMediaManager.adjustSessionVolume(sessionId, volume);
|
||||
}
|
||||
|
||||
void adjustSessionVolume(int volume) {
|
||||
mLocalMediaManager.adjustSessionVolume(volume);
|
||||
}
|
||||
|
||||
@@ -241,46 +241,29 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_isBroadcasting_verifyRegisterLeBroadcastServiceCallBack() {
|
||||
public void whenBroadcasting_verifyLeBroadcastServiceCallBackIsRegisteredAndUnregistered() {
|
||||
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
|
||||
mLocalBluetoothLeBroadcast);
|
||||
mIsBroadcasting = true;
|
||||
|
||||
mMediaOutputBaseDialogImpl.onStart();
|
||||
|
||||
verify(mLocalBluetoothLeBroadcast).registerServiceCallBack(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_notBroadcasting_noRegisterLeBroadcastServiceCallBack() {
|
||||
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
|
||||
mLocalBluetoothLeBroadcast);
|
||||
mIsBroadcasting = false;
|
||||
|
||||
mMediaOutputBaseDialogImpl.onStart();
|
||||
|
||||
verify(mLocalBluetoothLeBroadcast, never()).registerServiceCallBack(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_isBroadcasting_verifyUnregisterLeBroadcastServiceCallBack() {
|
||||
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
|
||||
mLocalBluetoothLeBroadcast);
|
||||
mIsBroadcasting = true;
|
||||
|
||||
mMediaOutputBaseDialogImpl.onStop();
|
||||
|
||||
verify(mLocalBluetoothLeBroadcast).unregisterServiceCallBack(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_notBroadcasting_noUnregisterLeBroadcastServiceCallBack() {
|
||||
public void
|
||||
whenNotBroadcasting_verifyLeBroadcastServiceCallBackIsNotRegisteredOrUnregistered() {
|
||||
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
|
||||
mLocalBluetoothLeBroadcast);
|
||||
mIsBroadcasting = false;
|
||||
|
||||
mMediaOutputBaseDialogImpl.onStart();
|
||||
mMediaOutputBaseDialogImpl.onStop();
|
||||
|
||||
verify(mLocalBluetoothLeBroadcast, never()).registerServiceCallBack(any(), any());
|
||||
verify(mLocalBluetoothLeBroadcast, never()).unregisterServiceCallBack(any());
|
||||
}
|
||||
|
||||
|
||||
@@ -170,15 +170,6 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
||||
verify(mLocalMediaManager).startScan();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void start_LocalMediaManagerIsNull_verifyNotStartScan() {
|
||||
mMediaOutputController.mLocalMediaManager = null;
|
||||
mMediaOutputController.start(mCb);
|
||||
|
||||
verify(mLocalMediaManager, never()).registerCallback(mMediaOutputController);
|
||||
verify(mLocalMediaManager, never()).startScan();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stop_verifyLocalMediaManagerDeinit() {
|
||||
mMediaOutputController.start(mCb);
|
||||
|
||||
Reference in New Issue
Block a user