summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kyunglyul Hyun <klhyun@google.com> 2019-08-23 04:08:01 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2019-08-23 04:08:01 +0000
commitb958337115e2b4256619d728f7fda30b8beca27b (patch)
treeae914e8d94505afd6d84813f86d1ba4c3d1ba682
parent1613d4b92a2419863aa6931cd7cf8316af8ff484 (diff)
parent23b3aaa464f78814e34b3b7b5220eccb433af6ac (diff)
Merge "Media: add MediaRouter2.getRoutes()"
-rw-r--r--media/java/android/media/IMediaRoute2ProviderClient.aidl2
-rw-r--r--media/java/android/media/IMediaRouter2Client.aidl4
-rw-r--r--media/java/android/media/IMediaRouterService.aidl5
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java2
-rw-r--r--media/java/android/media/MediaRouter2.java148
-rw-r--r--media/java/android/media/MediaRouter2Manager.java41
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java69
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java26
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java108
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java9
10 files changed, 283 insertions, 131 deletions
diff --git a/media/java/android/media/IMediaRoute2ProviderClient.aidl b/media/java/android/media/IMediaRoute2ProviderClient.aidl
index 8d08beb4a72c..6f44d45c0a12 100644
--- a/media/java/android/media/IMediaRoute2ProviderClient.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderClient.aidl
@@ -22,5 +22,5 @@ import android.media.MediaRoute2ProviderInfo;
* @hide
*/
oneway interface IMediaRoute2ProviderClient {
- void notifyProviderInfoUpdated(in MediaRoute2ProviderInfo info);
+ void updateProviderInfo(in MediaRoute2ProviderInfo info);
}
diff --git a/media/java/android/media/IMediaRouter2Client.aidl b/media/java/android/media/IMediaRouter2Client.aidl
index 774d6a764f32..26184af699db 100644
--- a/media/java/android/media/IMediaRouter2Client.aidl
+++ b/media/java/android/media/IMediaRouter2Client.aidl
@@ -16,10 +16,12 @@
package android.media;
+import android.media.MediaRoute2ProviderInfo;
+
/**
* @hide
*/
oneway interface IMediaRouter2Client {
- void notifyStateChanged();
void notifyRestoreRoute();
+ void notifyProviderInfosUpdated(in List<MediaRoute2ProviderInfo> providers);
}
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 08266a5a2051..1b713b6ab74b 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -42,7 +42,7 @@ interface IMediaRouterService {
void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction);
// Methods for media router 2
- void registerClient2AsUser(IMediaRouter2Client client, String packageName, int userId);
+ void registerClient2(IMediaRouter2Client client, String packageName);
void unregisterClient2(IMediaRouter2Client client);
void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, in Intent request);
/**
@@ -54,8 +54,7 @@ interface IMediaRouterService {
void selectRoute2(IMediaRouter2Client client, in @nullable MediaRoute2Info route);
void setControlCategories(IMediaRouter2Client client, in List<String> categories);
- void registerManagerAsUser(IMediaRouter2Manager manager,
- String packageName, int userId);
+ void registerManager(IMediaRouter2Manager manager, String packageName);
void unregisterManager(IMediaRouter2Manager manager);
/**
* Changes the selected route of an application.
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index b89b0b1a5f02..e8e0f826e6b6 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -98,7 +98,7 @@ public abstract class MediaRoute2ProviderService extends Service {
return;
}
try {
- mClient.notifyProviderInfoUpdated(mProviderInfo);
+ mClient.updateProviderInfo(mProviderInfo);
} catch (RemoteException ex) {
Log.w(TAG, "Failed to send onProviderInfoUpdated");
}
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index f4dffa28f133..8e29e34caa14 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -16,13 +16,16 @@
package android.media;
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.content.Context;
import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -58,6 +61,12 @@ public class MediaRouter2 {
private Client mClient;
private final String mPackageName;
+ final Handler mHandler;
+
+ List<MediaRoute2ProviderInfo> mProviders = Collections.emptyList();
+ volatile List<MediaRoute2Info> mRoutes = Collections.emptyList();
+
+ MediaRoute2Info mSelectedRoute;
/**
* Gets an instance of the media router associated with the context.
@@ -78,6 +87,7 @@ public class MediaRouter2 {
ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
mPackageName = mContext.getPackageName();
//TODO: read control categories from the manifest
+ mHandler = new Handler(Looper.getMainLooper());
}
/**
@@ -100,25 +110,10 @@ public class MediaRouter2 {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(callback, "callback must not be null");
+ CallbackRecord record;
// This is required to prevent adding the same callback twice.
synchronized (mCallbackRecords) {
- if (mCallbackRecords.size() == 0) {
- synchronized (sLock) {
- Client client = new Client();
- try {
- mMediaRouterService.registerClient2AsUser(client, mPackageName,
- UserHandle.myUserId());
- //TODO: We should merge control categories of callbacks.
- mMediaRouterService.setControlCategories(client, mControlCategories);
- mClient = client;
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to register media router.", ex);
- }
- }
- }
-
final int index = findCallbackRecordIndexLocked(callback);
- CallbackRecord record;
if (index < 0) {
record = new CallbackRecord(callback);
mCallbackRecords.add(record);
@@ -129,6 +124,20 @@ public class MediaRouter2 {
record.mFlags = flags;
}
+ synchronized (sLock) {
+ if (mClient == null) {
+ Client client = new Client();
+ try {
+ mMediaRouterService.registerClient2(client, mPackageName);
+ mMediaRouterService.setControlCategories(client, mControlCategories);
+ mClient = client;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to register media router.", ex);
+ }
+ }
+ }
+ record.notifyRoutes();
+
//TODO: Update discovery request here.
}
@@ -172,10 +181,9 @@ public class MediaRouter2 {
Objects.requireNonNull(controlCategories, "control categories must not be null");
Client client;
- List<String> newControlCategories;
+ List<String> newControlCategories = new ArrayList<>(controlCategories);
synchronized (sLock) {
- mControlCategories = new ArrayList<>(controlCategories);
- newControlCategories = mControlCategories;
+ mControlCategories = newControlCategories;
client = mClient;
}
if (client != null) {
@@ -185,8 +193,29 @@ public class MediaRouter2 {
Log.e(TAG, "Unable to set control categories.", ex);
}
}
+ mHandler.sendMessage(obtainMessage(MediaRouter2::refreshAndNotifyRoutes, this));
}
+ /**
+ * Gets the list of {@link MediaRoute2Info routes} currently known to the media router.
+ *
+ * @return the list of routes that support at least one of the control categories set by
+ * the application
+ */
+ @NonNull
+ public List<MediaRoute2Info> getRoutes() {
+ return mRoutes;
+ }
+
+ /**
+ * Gets the currently selected route.
+ *
+ * @return the selected route
+ */
+ @NonNull
+ public MediaRoute2Info getSelectedRoute() {
+ return mSelectedRoute;
+ }
/**
* Selects the specified route.
@@ -199,6 +228,7 @@ public class MediaRouter2 {
Client client;
synchronized (sLock) {
+ mSelectedRoute = route;
client = mClient;
}
if (client != null) {
@@ -247,6 +277,61 @@ public class MediaRouter2 {
return -1;
}
+ void onProviderInfosUpdated(List<MediaRoute2ProviderInfo> providers) {
+ if (providers == null) {
+ Log.w(TAG, "Providers info is null.");
+ return;
+ }
+
+ mProviders = providers;
+ refreshAndNotifyRoutes();
+ }
+
+ void refreshAndNotifyRoutes() {
+ ArrayList<MediaRoute2Info> routes = new ArrayList<>();
+
+ List<String> controlCategories;
+ synchronized (sLock) {
+ controlCategories = mControlCategories;
+ }
+
+ for (MediaRoute2ProviderInfo provider : mProviders) {
+ updateProvider(provider, controlCategories, routes);
+ }
+
+ //TODO: Can orders be changed?
+ if (!Objects.equals(mRoutes, routes)) {
+ mRoutes = Collections.unmodifiableList(routes);
+ notifyRouteListChanged(mRoutes);
+ }
+ }
+
+ void updateProvider(MediaRoute2ProviderInfo provider, List<String> controlCategories,
+ List<MediaRoute2Info> outRoutes) {
+ if (provider == null || !provider.isValid()) {
+ Log.w(TAG, "Ignoring invalid provider : " + provider);
+ }
+
+ final Collection<MediaRoute2Info> routes = provider.getRoutes();
+ for (MediaRoute2Info route : routes) {
+ if (!route.isValid()) {
+ Log.w(TAG, "Ignoring invalid route : " + route);
+ continue;
+ }
+ if (!route.supportsControlCategory(controlCategories)) {
+ continue;
+ }
+ outRoutes.add(route);
+ }
+ }
+
+ void notifyRouteListChanged(List<MediaRoute2Info> routes) {
+ for (CallbackRecord record: mCallbackRecords) {
+ record.mExecutor.execute(
+ () -> record.mCallback.onRoutesChanged(routes));
+ }
+ }
+
/**
* Interface for receiving events about media routing changes.
*/
@@ -265,9 +350,14 @@ public class MediaRouter2 {
* Called when a route is removed.
*/
public void onRouteRemoved(MediaRoute2Info routeInfo) {}
+
+ /**
+ * Called when the list of routes is changed.
+ */
+ public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {}
}
- static final class CallbackRecord {
+ final class CallbackRecord {
public final Callback mCallback;
public Executor mExecutor;
public int mFlags;
@@ -275,13 +365,25 @@ public class MediaRouter2 {
CallbackRecord(@NonNull Callback callback) {
mCallback = callback;
}
+
+ void notifyRoutes() {
+ final List<MediaRoute2Info> routes = mRoutes;
+ // notify only when bound to media router service.
+ //TODO: Correct the condition when control category, default rotue, .. are finalized.
+ if (routes.size() > 0) {
+ mExecutor.execute(() -> mCallback.onRoutesChanged(routes));
+ }
+ }
}
class Client extends IMediaRouter2Client.Stub {
@Override
- public void notifyStateChanged() throws RemoteException {}
+ public void notifyRestoreRoute() throws RemoteException {}
@Override
- public void notifyRestoreRoute() throws RemoteException {}
+ public void notifyProviderInfosUpdated(List<MediaRoute2ProviderInfo> info) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2::onProviderInfosUpdated,
+ MediaRouter2.this, info));
+ }
}
}
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 6c53f7d6d73f..0b645691ea3b 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -25,7 +25,6 @@ import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
@@ -104,26 +103,28 @@ public class MediaRouter2Manager {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(callback, "callback must not be null");
+ CallbackRecord callbackRecord;
synchronized (mCallbacks) {
if (findCallbackRecordIndexLocked(callback) >= 0) {
Log.w(TAG, "Ignoring to add the same callback twice.");
return;
}
- synchronized (sLock) {
- if (mCallbacks.size() == 0) {
- Client client = new Client();
- try {
- mMediaRouterService.registerManagerAsUser(client, mPackageName,
- UserHandle.myUserId());
- mClient = client;
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to register media router manager.", ex);
- }
+ callbackRecord = new CallbackRecord(executor, callback);
+ mCallbacks.add(callbackRecord);
+ }
+
+ synchronized (sLock) {
+ if (mClient == null) {
+ Client client = new Client();
+ try {
+ mMediaRouterService.registerManager(client, mPackageName);
+ mClient = client;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to register media router manager.", ex);
}
+ } else {
+ callbackRecord.notifyRoutes();
}
- CallbackRecord record = new CallbackRecord(executor, callback);
- mCallbacks.add(record);
- record.notifyRoutes();
}
}
@@ -149,6 +150,7 @@ public class MediaRouter2Manager {
} catch (RemoteException ex) {
Log.e(TAG, "Unable to unregister media router manager", ex);
}
+ mClient.notifyProviderInfosUpdated(Collections.emptyList());
mClient = null;
}
}
@@ -255,6 +257,10 @@ public class MediaRouter2Manager {
final MediaRoute2ProviderInfo prevProvider = mProviders.get(index);
final Set<String> updatedRouteIds = new HashSet<>();
for (MediaRoute2Info routeInfo : routes) {
+ if (!routeInfo.isValid()) {
+ Log.w(TAG, "Ignoring invalid route : " + routeInfo);
+ continue;
+ }
final MediaRoute2Info prevRoute = prevProvider.getRoute(routeInfo.getId());
if (prevRoute == null) {
notifyRouteAdded(routeInfo);
@@ -303,7 +309,7 @@ public class MediaRouter2Manager {
void notifyRouteListChanged() {
for (CallbackRecord record: mCallbacks) {
record.mExecutor.execute(
- () -> record.mCallback.onRouteListChanged(mRoutes));
+ () -> record.mCallback.onRoutesChanged(mRoutes));
}
}
@@ -369,10 +375,10 @@ public class MediaRouter2Manager {
public void onRouteSelected(@NonNull String packageName, @Nullable MediaRoute2Info route) {}
/**
- * Called when the list of routes are changed.
+ * Called when the list of routes is changed.
* A client may refresh available routes for each application.
*/
- public void onRouteListChanged(@NonNull List<MediaRoute2Info> routes) {}
+ public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {}
}
final class CallbackRecord {
@@ -385,6 +391,7 @@ public class MediaRouter2Manager {
}
void notifyRoutes() {
+ mExecutor.execute(() -> mCallback.onRoutesChanged(mRoutes));
for (MediaRoute2Info routeInfo : mRoutes) {
mExecutor.execute(
() -> mCallback.onRouteAdded(routeInfo));
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 946fb5e0e0ec..3abf0a4941e6 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -18,6 +18,7 @@ package com.android.mediaroutertest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
@@ -42,10 +43,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -96,6 +95,7 @@ public class MediaRouterManagerTest {
mPackageName = mContext.getPackageName();
}
+ //TODO: Move to a seperate file
@Test
public void testMediaRoute2Info() {
MediaRoute2Info routeInfo1 = new MediaRoute2Info.Builder("id", "name")
@@ -159,7 +159,7 @@ public class MediaRouterManagerTest {
mRouter.unregisterCallback(mockRouterCallback);
verify(mockCallback, timeout(TIMEOUT_MS))
- .onRouteListChanged(argThat(routes -> routes.size() > 0));
+ .onRoutesChanged(argThat(routes -> routes.size() > 0));
Map<String, MediaRoute2Info> routes =
createRouteMap(mManager.getAvailableRoutes(mPackageName));
@@ -170,40 +170,48 @@ public class MediaRouterManagerTest {
mManager.unregisterCallback(mockCallback);
}
+ /**
+ * Tests if we get proper routes for application that has special control category.
+ */
@Test
- public void onRouteSelectedTest() throws Exception {
- CountDownLatch latch = new CountDownLatch(1);
+ public void testGetRoutes() throws Exception {
+ MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
+ mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
+ mRouter.registerCallback(mExecutor, mockCallback);
+ verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+ .onRoutesChanged(argThat(routes -> routes.size() > 0));
+ Map<String, MediaRoute2Info> routes = createRouteMap(mRouter.getRoutes());
+ Assert.assertEquals(1, routes.size());
+ Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
+
+ mRouter.unregisterCallback(mockCallback);
+ }
+
+ @Test
+ public void testOnRouteSelected() throws Exception {
MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
+ MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
+
+ mManager.registerCallback(mExecutor, managerCallback);
+ mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
mRouter.registerCallback(mExecutor, mockRouterCallback);
- MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() {
- MediaRoute2Info mSelectedRoute = null;
-
- @Override
- public void onRouteAdded(MediaRoute2Info routeInfo) {
- if (mSelectedRoute == null) {
- mSelectedRoute = routeInfo;
- mManager.selectRoute(mPackageName, mSelectedRoute);
- }
- }
-
- @Override
- public void onRouteSelected(String packageName, MediaRoute2Info route) {
- if (TextUtils.equals(packageName, mPackageName)
- && mSelectedRoute != null
- && route != null
- && TextUtils.equals(route.getId(), mSelectedRoute.getId())) {
- latch.countDown();
- }
- }
- };
+ verify(managerCallback, timeout(TIMEOUT_MS))
+ .onRoutesChanged(argThat(routes -> routes.size() > 0));
- mManager.registerCallback(mExecutor, managerCallback);
+ Map<String, MediaRoute2Info> routes =
+ createRouteMap(mManager.getAvailableRoutes(mPackageName));
- Assert.assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
+ mManager.selectRoute(mPackageName, routeToSelect);
+
+ assertNotNull(routeToSelect);
+ verify(managerCallback, timeout(TIMEOUT_MS))
+ .onRouteAdded(argThat(route -> route.equals(routeToSelect)));
mManager.unregisterCallback(managerCallback);
+ mRouter.unregisterCallback(mockRouterCallback);
}
/**
@@ -219,7 +227,7 @@ public class MediaRouterManagerTest {
mRouter.registerCallback(mExecutor, routerCallback);
verify(managerCallback, timeout(TIMEOUT_MS))
- .onRouteListChanged(argThat(routes -> routes.size() > 0));
+ .onRoutesChanged(argThat(routes -> routes.size() > 0));
Map<String, MediaRoute2Info> routes =
createRouteMap(mManager.getAvailableRoutes(mPackageName));
@@ -244,7 +252,8 @@ public class MediaRouterManagerTest {
mManager.unregisterCallback(managerCallback);
}
- Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
+ // Helper for getting routes easily
+ static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
Map<String, MediaRoute2Info> routeMap = new HashMap<>();
for (MediaRoute2Info route : routes) {
routeMap.put(route.getId(), route);
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index 9e3401882f45..e753a7be99f6 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -43,7 +43,7 @@ import java.util.Objects;
* Maintains a connection to a particular media route provider service.
*/
final class MediaRoute2ProviderProxy implements ServiceConnection {
- private static final String TAG = "MediaRoute2ProviderProxy";
+ private static final String TAG = "MediaRoute2Provider";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final Context mContext;
@@ -54,7 +54,6 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
private Callback mCallback;
- //TODO: make it nonnull
private MediaRoute2ProviderInfo mProviderInfo;
// Connection state
@@ -246,13 +245,21 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
if (mActiveConnection != connection) {
return;
}
- // Set a unique provider id for identifying providers.
- mProviderInfo = new MediaRoute2ProviderInfo.Builder(info)
- .setUniqueId(mUniqueId)
- .build();
if (DEBUG) {
Slog.d(TAG, this + ": State changed ");
}
+ setAndNotifyProviderInfo(info);
+ }
+
+ private void setAndNotifyProviderInfo(MediaRoute2ProviderInfo info) {
+ //TODO: check if info is not updated
+ if (info == null) {
+ mProviderInfo = null;
+ } else {
+ mProviderInfo = new MediaRoute2ProviderInfo.Builder(info)
+ .setUniqueId(mUniqueId)
+ .build();
+ }
mHandler.post(mStateChanged);
}
@@ -261,6 +268,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
mConnectionReady = false;
mActiveConnection.dispose();
mActiveConnection = null;
+ setAndNotifyProviderInfo(null);
}
}
@@ -337,7 +345,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
mHandler.post(() -> onConnectionDied(Connection.this));
}
- void postProviderUpdated(MediaRoute2ProviderInfo info) {
+ void postProviderInfoUpdated(MediaRoute2ProviderInfo info) {
mHandler.post(() -> onProviderInfoUpdated(Connection.this, info));
}
}
@@ -354,10 +362,10 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
}
@Override
- public void notifyProviderInfoUpdated(MediaRoute2ProviderInfo info) {
+ public void updateProviderInfo(MediaRoute2ProviderInfo info) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postProviderUpdated(info);
+ connection.postProviderInfoUpdated(info);
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 12137fe8d841..043c834230d1 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -33,6 +33,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -72,21 +73,20 @@ class MediaRouter2ServiceImpl {
mContext = context;
}
- public void registerClientAsUser(@NonNull IMediaRouter2Client client,
- @NonNull String packageName, int userId) {
+ public void registerClient(@NonNull IMediaRouter2Client client,
+ @NonNull String packageName) {
Objects.requireNonNull(client, "client must not be null");
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
- final int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- false /*allowAll*/, true /*requireFull*/, "registerClientAsUser", packageName);
+ final int userId = UserHandle.getUserId(uid);
final boolean trusted = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
== PackageManager.PERMISSION_GRANTED;
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- registerClientLocked(client, uid, pid, packageName, resolvedUserId, trusted);
+ registerClientLocked(client, uid, pid, packageName, userId, trusted);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -106,20 +106,20 @@ class MediaRouter2ServiceImpl {
}
}
- public void registerManagerAsUser(@NonNull IMediaRouter2Manager manager,
- @NonNull String packageName, int userId) {
+ public void registerManager(@NonNull IMediaRouter2Manager manager,
+ @NonNull String packageName) {
Objects.requireNonNull(manager, "manager must not be null");
//TODO: should check permission
final boolean trusted = true;
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
- final int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- false /*allowAll*/, true /*requireFull*/, "registerManagerAsUser", packageName);
+ final int userId = UserHandle.getUserId(uid);
+
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- registerManagerLocked(manager, uid, pid, packageName, resolvedUserId, trusted);
+ registerManagerLocked(manager, uid, pid, packageName, userId, trusted);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -254,6 +254,10 @@ class MediaRouter2ServiceImpl {
userRecord.mClientRecords.add(clientRecord);
mAllClientRecords.put(binder, clientRecord);
+
+ userRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::notifyProviderInfosUpdatedToClient,
+ userRecord.mHandler, client));
}
}
@@ -341,9 +345,9 @@ class MediaRouter2ServiceImpl {
userRecord.mManagerRecords.add(managerRecord);
mAllManagerRecords.put(binder, managerRecord);
- //TODO: remove this when it's unnecessary
- // Sends published routes to newly added manager.
- userRecord.mHandler.scheduleUpdateManagerState();
+ userRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::notifyProviderInfosUpdatedToManager,
+ userRecord.mHandler, manager));
final int count = userRecord.mClientRecords.size();
for (int i = 0; i < count; i++) {
@@ -504,14 +508,14 @@ class MediaRouter2ServiceImpl {
private final WeakReference<MediaRouter2ServiceImpl> mServiceRef;
private final UserRecord mUserRecord;
private final MediaRoute2ProviderWatcher mWatcher;
- private final ArrayList<IMediaRouter2Manager> mTempManagers = new ArrayList<>();
//TODO: Make this thread-safe.
private final ArrayList<MediaRoute2ProviderProxy> mMediaProviders =
new ArrayList<>();
+ private List<MediaRoute2ProviderInfo> mProviderInfos;
private boolean mRunning;
- private boolean mManagerStateUpdateScheduled;
+ private boolean mProviderInfosUpdateScheduled;
UserHandler(MediaRouter2ServiceImpl service, UserRecord userRecord) {
super(Looper.getMainLooper(), null, true);
@@ -553,14 +557,14 @@ class MediaRouter2ServiceImpl {
}
private void updateProvider(MediaRoute2ProviderProxy provider) {
- scheduleUpdateManagerState();
+ scheduleUpdateProviderInfos();
}
private void selectRoute(ClientRecord clientRecord, MediaRoute2Info route) {
if (route != null) {
MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
if (provider == null) {
- Log.w(TAG, "Ignoring to select route of unknown provider " + route);
+ Slog.w(TAG, "Ignoring to select route of unknown provider " + route);
} else {
provider.selectRoute(clientRecord.mPackageName, route.getId());
}
@@ -571,7 +575,7 @@ class MediaRouter2ServiceImpl {
if (route != null) {
MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
if (provider == null) {
- Log.w(TAG, "Ignoring to unselect route of unknown provider " + route);
+ Slog.w(TAG, "Ignoring to unselect route of unknown provider " + route);
} else {
provider.unselectRoute(clientRecord.mPackageName, route.getId());
}
@@ -585,49 +589,71 @@ class MediaRouter2ServiceImpl {
}
}
- private void scheduleUpdateManagerState() {
- if (!mManagerStateUpdateScheduled) {
- mManagerStateUpdateScheduled = true;
- sendMessage(PooledLambda.obtainMessage(UserHandler::updateManagerState, this));
+ private void scheduleUpdateProviderInfos() {
+ if (!mProviderInfosUpdateScheduled) {
+ mProviderInfosUpdateScheduled = true;
+ sendMessage(PooledLambda.obtainMessage(UserHandler::updateProviderInfos, this));
}
}
- private void updateManagerState() {
- mManagerStateUpdateScheduled = false;
+ private void updateProviderInfos() {
+ mProviderInfosUpdateScheduled = false;
MediaRouter2ServiceImpl service = mServiceRef.get();
if (service == null) {
return;
}
- //TODO: Consider using a member variable (like mTempManagers).
+ final List<IMediaRouter2Manager> managers = new ArrayList<>();
+ final List<IMediaRouter2Client> clients = new ArrayList<>();
final List<MediaRoute2ProviderInfo> providers = new ArrayList<>();
for (MediaRoute2ProviderProxy mediaProvider : mMediaProviders) {
final MediaRoute2ProviderInfo providerInfo =
mediaProvider.getProviderInfo();
if (providerInfo == null || !providerInfo.isValid()) {
- Log.w(TAG, "Ignoring invalid provider info : " + providerInfo);
+ Slog.w(TAG, "Ignoring invalid provider info : " + providerInfo);
} else {
providers.add(providerInfo);
}
}
+ mProviderInfos = providers;
- try {
- synchronized (service.mLock) {
- final int count = mUserRecord.mManagerRecords.size();
- for (int i = 0; i < count; i++) {
- mTempManagers.add(mUserRecord.mManagerRecords.get(i).mManager);
- }
+ synchronized (service.mLock) {
+ for (ManagerRecord managerRecord : mUserRecord.mManagerRecords) {
+ managers.add(managerRecord.mManager);
}
- for (IMediaRouter2Manager tempManager : mTempManagers) {
- try {
- tempManager.notifyProviderInfosUpdated(providers);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to update manager state. Manager probably died.", ex);
- }
+ for (ClientRecord clientRecord : mUserRecord.mClientRecords) {
+ clients.add(clientRecord.mClient);
}
- } finally {
- // Clear the list in preparation for the next time.
- mTempManagers.clear();
+ }
+ for (IMediaRouter2Manager manager : managers) {
+ notifyProviderInfosUpdatedToManager(manager);
+ }
+ for (IMediaRouter2Client client : clients) {
+ notifyProviderInfosUpdatedToClient(client);
+ }
+ }
+
+ private void notifyProviderInfosUpdatedToClient(IMediaRouter2Client client) {
+ if (mProviderInfos == null) {
+ scheduleUpdateProviderInfos();
+ return;
+ }
+ try {
+ client.notifyProviderInfosUpdated(mProviderInfos);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify provider infos updated. Client probably died.");
+ }
+ }
+
+ private void notifyProviderInfosUpdatedToManager(IMediaRouter2Manager manager) {
+ if (mProviderInfos == null) {
+ scheduleUpdateProviderInfos();
+ return;
+ }
+ try {
+ manager.notifyProviderInfosUpdated(mProviderInfos);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify provider infos updated. Manager probably died.");
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index a43068b87c06..2670cd8247ac 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -435,12 +435,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
- public void registerClient2AsUser(IMediaRouter2Client client, String packageName, int userId) {
+ public void registerClient2(IMediaRouter2Client client, String packageName) {
final int uid = Binder.getCallingUid();
if (!validatePackageName(uid, packageName)) {
throw new SecurityException("packageName must match the calling uid");
}
- mService2.registerClientAsUser(client, packageName, userId);
+ mService2.registerClient(client, packageName);
}
// Binder call
@@ -464,13 +464,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
- public void registerManagerAsUser(IMediaRouter2Manager manager,
- String packageName, int userId) {
+ public void registerManager(IMediaRouter2Manager manager, String packageName) {
final int uid = Binder.getCallingUid();
if (!validatePackageName(uid, packageName)) {
throw new SecurityException("packageName must match the calling uid");
}
- mService2.registerManagerAsUser(manager, packageName, userId);
+ mService2.registerManager(manager, packageName);
}
// Binder call