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:
@@ -22,4 +22,5 @@ package android.media;
|
||||
oneway interface IMediaRouterClient {
|
||||
void onStateChanged();
|
||||
void onRestoreRoute();
|
||||
void onSelectedRouteChanged(String routeId);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user