Merge "Media: Add group id for media router to sync" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
5644a46b3c
@@ -22,4 +22,5 @@ package android.media;
|
|||||||
oneway interface IMediaRouterClient {
|
oneway interface IMediaRouterClient {
|
||||||
void onStateChanged();
|
void onStateChanged();
|
||||||
void onRestoreRoute();
|
void onRestoreRoute();
|
||||||
|
void onSelectedRouteChanged(String routeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ interface IMediaRouterService {
|
|||||||
void registerClientAsUser(IMediaRouterClient client, String packageName, int userId);
|
void registerClientAsUser(IMediaRouterClient client, String packageName, int userId);
|
||||||
void unregisterClient(IMediaRouterClient client);
|
void unregisterClient(IMediaRouterClient client);
|
||||||
|
|
||||||
|
void registerClientGroupId(IMediaRouterClient client, String groupId);
|
||||||
|
|
||||||
MediaRouterClientState getState(IMediaRouterClient client);
|
MediaRouterClientState getState(IMediaRouterClient client);
|
||||||
boolean isPlaybackActive(IMediaRouterClient client);
|
boolean isPlaybackActive(IMediaRouterClient client);
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.Manifest;
|
|||||||
import android.annotation.DrawableRes;
|
import android.annotation.DrawableRes;
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.annotation.SystemService;
|
import android.annotation.SystemService;
|
||||||
import android.annotation.UnsupportedAppUsage;
|
import android.annotation.UnsupportedAppUsage;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
@@ -343,6 +344,16 @@ public class MediaRouter {
|
|||||||
updatePresentationDisplays(displayId);
|
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() {
|
public Display[] getAllPresentationDisplays() {
|
||||||
return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
|
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) {
|
void setSelectedRoute(RouteInfo info, boolean explicit) {
|
||||||
// Must be non-reentrant.
|
// Must be non-reentrant.
|
||||||
mSelectedRoute = info;
|
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;
|
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
|
// Maps application contexts
|
||||||
static final HashMap<Context, MediaRouter> sRouters = new HashMap<Context, MediaRouter>();
|
static final HashMap<Context, MediaRouter> sRouters = new HashMap<Context, MediaRouter>();
|
||||||
|
|
||||||
@@ -847,6 +889,25 @@ public class MediaRouter {
|
|||||||
return false;
|
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.
|
* 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
|
* 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
|
// Binder call
|
||||||
@Override
|
@Override
|
||||||
public void unregisterClient(IMediaRouterClient client) {
|
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) {
|
private void unregisterClientLocked(IMediaRouterClient client, boolean died) {
|
||||||
ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder());
|
ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder());
|
||||||
if (clientRecord != null) {
|
if (clientRecord != null) {
|
||||||
UserRecord userRecord = clientRecord.mUserRecord;
|
UserRecord userRecord = clientRecord.mUserRecord;
|
||||||
userRecord.mClientRecords.remove(clientRecord);
|
userRecord.mClientRecords.remove(clientRecord);
|
||||||
|
if (clientRecord.mGroupId != null) {
|
||||||
|
userRecord.removeFromGroup(clientRecord.mGroupId, clientRecord);
|
||||||
|
clientRecord.mGroupId = null;
|
||||||
|
}
|
||||||
disposeClientLocked(clientRecord, died);
|
disposeClientLocked(clientRecord, died);
|
||||||
disposeUserIfNeededLocked(userRecord); // since client removed from user
|
disposeUserIfNeededLocked(userRecord); // since client removed from user
|
||||||
}
|
}
|
||||||
@@ -568,6 +617,16 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
|||||||
clientRecord.mUserRecord.mHandler.obtainMessage(
|
clientRecord.mUserRecord.mHandler.obtainMessage(
|
||||||
UserHandler.MSG_SELECT_ROUTE, routeId).sendToTarget();
|
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 int mRouteTypes;
|
||||||
public boolean mActiveScan;
|
public boolean mActiveScan;
|
||||||
public String mSelectedRouteId;
|
public String mSelectedRouteId;
|
||||||
|
public String mGroupId;
|
||||||
|
|
||||||
public ClientRecord(UserRecord userRecord, IMediaRouterClient client,
|
public ClientRecord(UserRecord userRecord, IMediaRouterClient client,
|
||||||
int uid, int pid, String packageName, boolean trusted) {
|
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.
|
* Information about a particular user.
|
||||||
* The contents of this object is guarded by mLock.
|
* 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 ArrayList<ClientRecord> mClientRecords = new ArrayList<ClientRecord>();
|
||||||
public final UserHandler mHandler;
|
public final UserHandler mHandler;
|
||||||
public MediaRouterClientState mRouterState;
|
public MediaRouterClientState mRouterState;
|
||||||
|
private final ArrayMap<String, ClientGroup> mClientGroupMap = new ArrayMap<>();
|
||||||
|
|
||||||
public UserRecord(int userId) {
|
public UserRecord(int userId) {
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
@@ -759,7 +825,26 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
|||||||
}, 1000)) {
|
}, 1000)) {
|
||||||
pw.println(indent + "<could not dump handler state>");
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -791,6 +876,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
|||||||
public static final int MSG_REQUEST_UPDATE_VOLUME = 7;
|
public static final int MSG_REQUEST_UPDATE_VOLUME = 7;
|
||||||
private static final int MSG_UPDATE_CLIENT_STATE = 8;
|
private static final int MSG_UPDATE_CLIENT_STATE = 8;
|
||||||
private static final int MSG_CONNECTION_TIMED_OUT = 9;
|
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_NOT_AVAILABLE = 1;
|
||||||
private static final int TIMEOUT_REASON_CONNECTION_LOST = 2;
|
private static final int TIMEOUT_REASON_CONNECTION_LOST = 2;
|
||||||
@@ -867,6 +953,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
|||||||
connectionTimedOut();
|
connectionTimedOut();
|
||||||
break;
|
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) {
|
private int findProviderRecord(RemoteDisplayProviderProxy provider) {
|
||||||
final int count = mProviderRecords.size();
|
final int count = mProviderRecords.size();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user