Merge "Media: Add group id for media router to sync" into qt-dev am: 5644a46b3c

am: 4156ab2d82

Change-Id: I51aa513912e425c5bc4d9f660f4caf39a1727573
This commit is contained in:
Kyunglyul Hyun
2019-05-23 22:52:06 -07:00
committed by android-build-merger
4 changed files with 186 additions and 1 deletions

View File

@@ -22,4 +22,5 @@ package android.media;
oneway interface IMediaRouterClient {
void onStateChanged();
void onRestoreRoute();
void onSelectedRouteChanged(String routeId);
}

View File

@@ -26,6 +26,8 @@ interface IMediaRouterService {
void registerClientAsUser(IMediaRouterClient client, String packageName, int userId);
void unregisterClient(IMediaRouterClient client);
void registerClientGroupId(IMediaRouterClient client, String groupId);
MediaRouterClientState getState(IMediaRouterClient client);
boolean isPlaybackActive(IMediaRouterClient client);

View File

@@ -20,6 +20,7 @@ import android.Manifest;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
@@ -343,6 +344,16 @@ public class MediaRouter {
updatePresentationDisplays(displayId);
}
public void setRouterGroupId(String groupId) {
if (mClient != null) {
try {
mMediaRouterService.registerClientGroupId(mClient, groupId);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to register group ID of the client.", ex);
}
}
}
public Display[] getAllPresentationDisplays() {
return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
}
@@ -358,6 +369,21 @@ public class MediaRouter {
}
}
void updateSelectedRouteForId(String routeId) {
RouteInfo selectedRoute = isBluetoothA2dpOn()
? mBluetoothA2dpRoute : mDefaultAudioVideo;
final int count = mRoutes.size();
for (int i = 0; i < count; i++) {
final RouteInfo route = mRoutes.get(i);
if (TextUtils.equals(route.mGlobalRouteId, routeId)) {
selectedRoute = route;
}
}
if (selectedRoute != mSelectedRoute) {
selectRouteStatic(selectedRoute.mSupportedTypes, selectedRoute, false);
}
}
void setSelectedRoute(RouteInfo info, boolean explicit) {
// Must be non-reentrant.
mSelectedRoute = info;
@@ -619,6 +645,15 @@ public class MediaRouter {
}
});
}
@Override
public void onSelectedRouteChanged(String routeId) {
mHandler.post(() -> {
if (Client.this == mClient) {
updateSelectedRouteForId(routeId);
}
});
}
}
}
@@ -728,6 +763,13 @@ public class MediaRouter {
*/
public static final int AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE = 1 << 0;
/**
* The route group id used for sharing the selected mirroring device.
* System UI and Settings use this to synchronize their mirroring status.
* @hide
*/
public static final String MIRRORING_GROUP_ID = "android.media.mirroring_group";
// Maps application contexts
static final HashMap<Context, MediaRouter> sRouters = new HashMap<Context, MediaRouter>();
@@ -847,6 +889,25 @@ public class MediaRouter {
return false;
}
/**
* Sets the group ID of the router.
* Media routers with the same ID acts as if they were a single media router.
* For example, if a media router selects a route, the selected route of routers
* with the same group ID will be changed automatically.
*
* Two routers in a group are supposed to use the same route types.
*
* System UI and Settings use this to synchronize their mirroring status.
* Do not set the router group id unless it's necessary.
*
* {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} permission is required to
* call this method.
* @hide
*/
public void setRouterGroupId(@Nullable String groupId) {
sStatic.setRouterGroupId(groupId);
}
/**
* Add a callback to listen to events about specific kinds of media routes.
* If the specified callback is already registered, its registration will be updated for any

View File

@@ -246,6 +246,29 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
// Binder call
@Override
public void registerClientGroupId(IMediaRouterClient client, String groupId) {
if (client == null) {
throw new NullPointerException("client must not be null");
}
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
!= PackageManager.PERMISSION_GRANTED) {
Log.w(TAG, "Ignoring client group request because "
+ "the client doesn't have the CONFIGURE_WIFI_DISPLAY permission.");
return;
}
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
registerClientGroupIdLocked(client, groupId);
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
// Binder call
@Override
public void unregisterClient(IMediaRouterClient client) {
@@ -502,11 +525,37 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
private void registerClientGroupIdLocked(IMediaRouterClient client, String groupId) {
final IBinder binder = client.asBinder();
ClientRecord clientRecord = mAllClientRecords.get(binder);
if (clientRecord == null) {
Log.w(TAG, "Ignoring group id register request of a unregistered client.");
return;
}
if (TextUtils.equals(clientRecord.mGroupId, groupId)) {
return;
}
UserRecord userRecord = clientRecord.mUserRecord;
if (clientRecord.mGroupId != null) {
userRecord.removeFromGroup(clientRecord.mGroupId, clientRecord);
}
clientRecord.mGroupId = groupId;
if (groupId != null) {
userRecord.addToGroup(groupId, clientRecord);
userRecord.mHandler.obtainMessage(UserHandler.MSG_UPDATE_SELECTED_ROUTE, groupId)
.sendToTarget();
}
}
private void unregisterClientLocked(IMediaRouterClient client, boolean died) {
ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder());
if (clientRecord != null) {
UserRecord userRecord = clientRecord.mUserRecord;
userRecord.mClientRecords.remove(clientRecord);
if (clientRecord.mGroupId != null) {
userRecord.removeFromGroup(clientRecord.mGroupId, clientRecord);
clientRecord.mGroupId = null;
}
disposeClientLocked(clientRecord, died);
disposeUserIfNeededLocked(userRecord); // since client removed from user
}
@@ -568,6 +617,16 @@ public final class MediaRouterService extends IMediaRouterService.Stub
clientRecord.mUserRecord.mHandler.obtainMessage(
UserHandler.MSG_SELECT_ROUTE, routeId).sendToTarget();
}
if (clientRecord.mGroupId != null) {
ClientGroup group =
clientRecord.mUserRecord.mClientGroupMap.get(clientRecord.mGroupId);
if (group != null) {
group.mSelectedRouteId = routeId;
clientRecord.mUserRecord.mHandler.obtainMessage(
UserHandler.MSG_UPDATE_SELECTED_ROUTE, clientRecord.mGroupId)
.sendToTarget();
}
}
}
}
}
@@ -680,6 +739,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
public int mRouteTypes;
public boolean mActiveScan;
public String mSelectedRouteId;
public String mGroupId;
public ClientRecord(UserRecord userRecord, IMediaRouterClient client,
int uid, int pid, String packageName, boolean trusted) {
@@ -720,6 +780,11 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
final class ClientGroup {
public String mSelectedRouteId;
public final List<ClientRecord> mClientRecords = new ArrayList<>();
}
/**
* Information about a particular user.
* The contents of this object is guarded by mLock.
@@ -729,6 +794,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
public final ArrayList<ClientRecord> mClientRecords = new ArrayList<ClientRecord>();
public final UserHandler mHandler;
public MediaRouterClientState mRouterState;
private final ArrayMap<String, ClientGroup> mClientGroupMap = new ArrayMap<>();
public UserRecord(int userId) {
mUserId = userId;
@@ -759,7 +825,26 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}, 1000)) {
pw.println(indent + "<could not dump handler state>");
}
}
}
public void addToGroup(String groupId, ClientRecord clientRecord) {
ClientGroup group = mClientGroupMap.get(groupId);
if (group == null) {
group = new ClientGroup();
mClientGroupMap.put(groupId, group);
}
group.mClientRecords.add(clientRecord);
}
public void removeFromGroup(String groupId, ClientRecord clientRecord) {
ClientGroup group = mClientGroupMap.get(groupId);
if (group != null) {
group.mClientRecords.remove(clientRecord);
if (group.mClientRecords.size() == 0) {
mClientGroupMap.remove(groupId);
}
}
}
@Override
public String toString() {
@@ -791,6 +876,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
public static final int MSG_REQUEST_UPDATE_VOLUME = 7;
private static final int MSG_UPDATE_CLIENT_STATE = 8;
private static final int MSG_CONNECTION_TIMED_OUT = 9;
private static final int MSG_UPDATE_SELECTED_ROUTE = 10;
private static final int TIMEOUT_REASON_NOT_AVAILABLE = 1;
private static final int TIMEOUT_REASON_CONNECTION_LOST = 2;
@@ -867,6 +953,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
connectionTimedOut();
break;
}
case MSG_UPDATE_SELECTED_ROUTE: {
updateSelectedRoute((String) msg.obj);
break;
}
}
}
@@ -1191,6 +1281,37 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
private void updateSelectedRoute(String groupId) {
try {
String selectedRouteId = null;
synchronized (mService.mLock) {
ClientGroup group = mUserRecord.mClientGroupMap.get(groupId);
if (group == null) {
return;
}
selectedRouteId = group.mSelectedRouteId;
final int count = group.mClientRecords.size();
for (int i = 0; i < count; i++) {
ClientRecord clientRecord = group.mClientRecords.get(i);
if (!TextUtils.equals(selectedRouteId, clientRecord.mSelectedRouteId)) {
mTempClients.add(clientRecord.mClient);
}
}
}
final int count = mTempClients.size();
for (int i = 0; i < count; i++) {
try {
mTempClients.get(i).onSelectedRouteChanged(selectedRouteId);
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to call onSelectedRouteChanged. Client probably died.");
}
}
} finally {
mTempClients.clear();
}
}
private int findProviderRecord(RemoteDisplayProviderProxy provider) {
final int count = mProviderRecords.size();
for (int i = 0; i < count; i++) {