summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2013-11-14 18:16:08 -0800
committerJeff Brown <jeffbrown@google.com>2013-11-15 00:29:43 -0800
commitaf574183c274f51d04487a9c8355e9f34a1150f2 (patch)
treec325b02a379f86bc9d8eb42b0bb5d8b700cc80bb
parent1907c0d280d97776708810c9d24931aa6f818790 (diff)
downloadframeworks_base-af574183c274f51d04487a9c8355e9f34a1150f2.zip
frameworks_base-af574183c274f51d04487a9c8355e9f34a1150f2.tar.gz
frameworks_base-af574183c274f51d04487a9c8355e9f34a1150f2.tar.bz2
Disallow applications from initiating cast screen.
Only allow the system ui and settings to connect to a remote display. To do this, we essentially hide the remote displays from applications by using the ROUTE_TYPE_REMOTE_DISPLAY then add permission checks around the operations that connect to them. As a bonus, this may actually save power on devices since applications that use MediaRouter will not longer be performing discover on remote display routes at all. Bug: 11257292 Change-Id: I9ea8c568df4df5a0f0cf3d0f11b39c87e2110795
-rw-r--r--core/java/android/hardware/display/DisplayManager.java7
-rw-r--r--media/java/android/media/MediaRouter.java73
-rw-r--r--media/java/android/media/MediaRouterClientState.java17
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--services/java/com/android/server/display/DisplayManagerService.java49
-rw-r--r--services/java/com/android/server/display/WifiDisplayAdapter.java14
-rw-r--r--services/java/com/android/server/media/MediaRouterService.java61
7 files changed, 161 insertions, 63 deletions
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index f12be5f..d5208d9 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -299,6 +299,10 @@ public final class DisplayManager {
/**
* Initiates a fresh scan of availble Wifi displays.
* The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
+ * <p>
+ * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
+ * </p>
+ *
* @hide
*/
public void scanWifiDisplays() {
@@ -312,8 +316,7 @@ public final class DisplayManager {
* Automatically remembers the display after a successful connection, if not
* already remembered.
* </p><p>
- * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect
- * to unknown displays. No permissions are required to connect to already known displays.
+ * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
* </p>
*
* @param deviceAddress The MAC address of the device to which we should connect.
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 3d10158..525dc4f 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -18,11 +18,13 @@ package android.media;
import com.android.internal.util.Objects;
+import android.Manifest;
import android.app.ActivityThread;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
@@ -30,6 +32,7 @@ import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -82,6 +85,7 @@ public class MediaRouter {
RouteInfo mSelectedRoute;
+ final boolean mCanConfigureWifiDisplays;
boolean mActivelyScanningWifiDisplays;
int mDiscoveryRequestRouteTypes;
@@ -129,6 +133,13 @@ public class MediaRouter {
com.android.internal.R.string.default_audio_route_category_name,
ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO, false);
mSystemCategory.mIsSystem = true;
+
+ // Only the system can configure wifi displays. The display manager
+ // enforces this with a permission check. Set a flag here so that we
+ // know whether this process is actually allowed to scan and connect.
+ mCanConfigureWifiDisplays = appContext.checkPermission(
+ Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED;
}
// Called after sStatic is initialized
@@ -255,7 +266,7 @@ public class MediaRouter {
}
if ((cbi.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) {
activeScan = true;
- if ((cbi.type & (ROUTE_TYPE_LIVE_VIDEO | ROUTE_TYPE_REMOTE_DISPLAY)) != 0) {
+ if ((cbi.type & ROUTE_TYPE_REMOTE_DISPLAY) != 0) {
activeScanWifiDisplay = true;
}
}
@@ -268,7 +279,7 @@ public class MediaRouter {
}
// Update wifi display scanning.
- if (activeScanWifiDisplay) {
+ if (activeScanWifiDisplay && mCanConfigureWifiDisplays) {
if (!mActivelyScanningWifiDisplays) {
mActivelyScanningWifiDisplays = true;
mHandler.post(mScanWifiDisplays);
@@ -493,7 +504,8 @@ public class MediaRouter {
route.mDescription = globalRoute.description;
changed = true;
}
- if (route.mSupportedTypes != globalRoute.supportedTypes) {
+ final int oldSupportedTypes = route.mSupportedTypes;
+ if (oldSupportedTypes != globalRoute.supportedTypes) {
route.mSupportedTypes = globalRoute.supportedTypes;
changed = true;
}
@@ -536,7 +548,7 @@ public class MediaRouter {
}
if (changed) {
- dispatchRouteChanged(route);
+ dispatchRouteChanged(route, oldSupportedTypes);
}
if (volumeChanged) {
dispatchRouteVolumeChanged(route);
@@ -908,7 +920,12 @@ public class MediaRouter {
final boolean newRouteHasAddress = route != null && route.mDeviceAddress != null;
if (activeDisplay != null || oldRouteHasAddress || newRouteHasAddress) {
if (newRouteHasAddress && !matchesDeviceAddress(activeDisplay, route)) {
- sStatic.mDisplayService.connectWifiDisplay(route.mDeviceAddress);
+ if (sStatic.mCanConfigureWifiDisplays) {
+ sStatic.mDisplayService.connectWifiDisplay(route.mDeviceAddress);
+ } else {
+ Log.e(TAG, "Cannot connect to wifi displays because this process "
+ + "is not allowed to do so.");
+ }
} else if (activeDisplay != null && !newRouteHasAddress) {
sStatic.mDisplayService.disconnectWifiDisplay();
}
@@ -1175,10 +1192,34 @@ public class MediaRouter {
}
static void dispatchRouteChanged(RouteInfo info) {
+ dispatchRouteChanged(info, info.mSupportedTypes);
+ }
+
+ static void dispatchRouteChanged(RouteInfo info, int oldSupportedTypes) {
+ final int newSupportedTypes = info.mSupportedTypes;
for (CallbackInfo cbi : sStatic.mCallbacks) {
- if (cbi.filterRouteEvent(info)) {
+ // Reconstruct some of the history for callbacks that may not have observed
+ // all of the events needed to correctly interpret the current state.
+ // FIXME: This is a strong signal that we should deprecate route type filtering
+ // completely in the future because it can lead to inconsistencies in
+ // applications.
+ final boolean oldVisibility = cbi.filterRouteEvent(oldSupportedTypes);
+ final boolean newVisibility = cbi.filterRouteEvent(newSupportedTypes);
+ if (!oldVisibility && newVisibility) {
+ cbi.cb.onRouteAdded(cbi.router, info);
+ if (info.isSelected()) {
+ cbi.cb.onRouteSelected(cbi.router, newSupportedTypes, info);
+ }
+ }
+ if (oldVisibility || newVisibility) {
cbi.cb.onRouteChanged(cbi.router, info);
}
+ if (oldVisibility && !newVisibility) {
+ if (info.isSelected()) {
+ cbi.cb.onRouteUnselected(cbi.router, oldSupportedTypes, info);
+ }
+ cbi.cb.onRouteRemoved(cbi.router, info);
+ }
}
}
@@ -1257,6 +1298,18 @@ public class MediaRouter {
if (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
displays = status.getDisplays();
activeDisplay = status.getActiveDisplay();
+
+ // Only the system is able to connect to wifi display routes.
+ // The display manager will enforce this with a permission check but it
+ // still publishes information about all available displays.
+ // Filter the list down to just the active display.
+ if (!sStatic.mCanConfigureWifiDisplays) {
+ if (activeDisplay != null) {
+ displays = new WifiDisplay[] { activeDisplay };
+ } else {
+ displays = WifiDisplay.EMPTY_ARRAY;
+ }
+ }
} else {
displays = WifiDisplay.EMPTY_ARRAY;
activeDisplay = null;
@@ -1293,7 +1346,7 @@ public class MediaRouter {
// Don't scan if we're already connected to a wifi display,
// the scanning process can cause a hiccup with some configurations.
- if (wantScan && activeDisplay != null) {
+ if (wantScan && activeDisplay != null && sStatic.mCanConfigureWifiDisplays) {
sStatic.mDisplayService.scanWifiDisplays();
}
}
@@ -2547,8 +2600,12 @@ public class MediaRouter {
}
public boolean filterRouteEvent(RouteInfo route) {
+ return filterRouteEvent(route.mSupportedTypes);
+ }
+
+ public boolean filterRouteEvent(int supportedTypes) {
return (flags & CALLBACK_FLAG_UNFILTERED_EVENTS) != 0
- || (type & route.mSupportedTypes) != 0;
+ || (type & supportedTypes) != 0;
}
}
diff --git a/media/java/android/media/MediaRouterClientState.java b/media/java/android/media/MediaRouterClientState.java
index 0847503..54b8276 100644
--- a/media/java/android/media/MediaRouterClientState.java
+++ b/media/java/android/media/MediaRouterClientState.java
@@ -50,6 +50,17 @@ public final class MediaRouterClientState implements Parcelable {
globallySelectedRouteId = src.readString();
}
+ public RouteInfo getRoute(String id) {
+ final int count = routes.size();
+ for (int i = 0; i < count; i++) {
+ final RouteInfo route = routes.get(i);
+ if (route.id.equals(id)) {
+ return route;
+ }
+ }
+ return null;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -61,6 +72,12 @@ public final class MediaRouterClientState implements Parcelable {
dest.writeString(globallySelectedRouteId);
}
+ @Override
+ public String toString() {
+ return "MediaRouterClientState{ globallySelectedRouteId="
+ + globallySelectedRouteId + ", routes=" + routes.toString() + " }";
+ }
+
public static final Parcelable.Creator<MediaRouterClientState> CREATOR =
new Parcelable.Creator<MediaRouterClientState>() {
@Override
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 09ac2da..8d6fe41 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -71,6 +71,9 @@
<!-- Keyguard -->
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+ <!-- Wifi Display -->
+ <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
+
<application
android:persistent="true"
android:allowClearUserData="false"
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index 249c8b0..02f26b3 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -466,6 +466,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
@Override // Binder call
public void scanWifiDisplays() {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to scan wifi displays");
+
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
@@ -483,13 +486,14 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
if (address == null) {
throw new IllegalArgumentException("address must not be null");
}
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to connect to a wifi display");
- final boolean trusted = canCallerConfigureWifiDisplay();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
if (mWifiDisplayAdapter != null) {
- mWifiDisplayAdapter.requestConnectLocked(address, trusted);
+ mWifiDisplayAdapter.requestConnectLocked(address);
}
}
} finally {
@@ -499,12 +503,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
@Override
public void pauseWifiDisplay() {
- if (mContext.checkCallingPermission(
- android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY"
- + "permission to pause a wifi display session.");
- }
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to pause a wifi display session");
final long token = Binder.clearCallingIdentity();
try {
@@ -520,12 +520,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
@Override
public void resumeWifiDisplay() {
- if (mContext.checkCallingPermission(
- android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY"
- + "permission to resume a wifi display session.");
- }
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to resume a wifi display session");
final long token = Binder.clearCallingIdentity();
try {
@@ -541,6 +537,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
@Override // Binder call
public void disconnectWifiDisplay() {
+ // This request does not require special permissions.
+ // Any app can request disconnection from the currently active wifi display.
+ // This exception should no longer be needed once wifi display control moves
+ // to the media router service.
+
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
@@ -558,10 +559,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
if (address == null) {
throw new IllegalArgumentException("address must not be null");
}
- if (!canCallerConfigureWifiDisplay()) {
- throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
- + "rename a wifi display.");
- }
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to rename to a wifi display");
final long token = Binder.clearCallingIdentity();
try {
@@ -580,10 +579,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
if (address == null) {
throw new IllegalArgumentException("address must not be null");
}
- if (!canCallerConfigureWifiDisplay()) {
- throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
- + "forget a wifi display.");
- }
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to forget to a wifi display");
final long token = Binder.clearCallingIdentity();
try {
@@ -599,6 +596,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
@Override // Binder call
public WifiDisplayStatus getWifiDisplayStatus() {
+ // This request does not require special permissions.
+ // Any app can get information about available wifi displays.
+
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
@@ -612,11 +612,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
}
}
- private boolean canCallerConfigureWifiDisplay() {
- return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
- == PackageManager.PERMISSION_GRANTED;
- }
-
@Override // Binder call
public int createVirtualDisplay(IBinder appToken, String packageName,
String name, int width, int height, int densityDpi, Surface surface, int flags) {
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index 11558a3..fdef039 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -172,19 +172,9 @@ final class WifiDisplayAdapter extends DisplayAdapter {
});
}
- public void requestConnectLocked(final String address, final boolean trusted) {
+ public void requestConnectLocked(final String address) {
if (DEBUG) {
- Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted);
- }
-
- if (!trusted) {
- synchronized (getSyncRoot()) {
- if (!isRememberedDisplayLocked(address)) {
- Slog.w(TAG, "Ignoring request by an untrusted client to connect to "
- + "an unknown wifi display: " + address);
- return;
- }
- }
+ Slog.d(TAG, "requestConnectLocked: address=" + address);
}
getHandler().post(new Runnable() {
diff --git a/services/java/com/android/server/media/MediaRouterService.java b/services/java/com/android/server/media/MediaRouterService.java
index 1491eb6..a31695b 100644
--- a/services/java/com/android/server/media/MediaRouterService.java
+++ b/services/java/com/android/server/media/MediaRouterService.java
@@ -128,10 +128,13 @@ public final class MediaRouterService extends IMediaRouterService.Stub
final int pid = Binder.getCallingPid();
final int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
false /*allowAll*/, true /*requireFull*/, "registerClientAsUser", packageName);
+ final boolean trusted = mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) ==
+ PackageManager.PERMISSION_GRANTED;
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- registerClientLocked(client, pid, packageName, resolvedUserId);
+ registerClientLocked(client, pid, packageName, resolvedUserId, trusted);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -306,7 +309,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
private void registerClientLocked(IMediaRouterClient client,
- int pid, String packageName, int userId) {
+ int pid, String packageName, int userId, boolean trusted) {
final IBinder binder = client.asBinder();
ClientRecord clientRecord = mAllClientRecords.get(binder);
if (clientRecord == null) {
@@ -316,7 +319,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
userRecord = new UserRecord(userId);
newUser = true;
}
- clientRecord = new ClientRecord(userRecord, client, pid, packageName);
+ clientRecord = new ClientRecord(userRecord, client, pid, packageName, trusted);
try {
binder.linkToDeath(clientRecord, 0);
} catch (RemoteException ex) {
@@ -347,7 +350,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private MediaRouterClientState getStateLocked(IMediaRouterClient client) {
ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
if (clientRecord != null) {
- return clientRecord.mUserRecord.mState;
+ return clientRecord.getState();
}
return null;
}
@@ -357,6 +360,11 @@ public final class MediaRouterService extends IMediaRouterService.Stub
final IBinder binder = client.asBinder();
ClientRecord clientRecord = mAllClientRecords.get(binder);
if (clientRecord != null) {
+ // Only let the system discover remote display routes for now.
+ if (!clientRecord.mTrusted) {
+ routeTypes &= ~MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
+ }
+
if (clientRecord.mRouteTypes != routeTypes
|| clientRecord.mActiveScan != activeScan) {
if (DEBUG) {
@@ -385,11 +393,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub
clientRecord.mSelectedRouteId = routeId;
if (explicit) {
+ // Any app can disconnect from the globally selected route.
if (oldRouteId != null) {
clientRecord.mUserRecord.mHandler.obtainMessage(
UserHandler.MSG_UNSELECT_ROUTE, oldRouteId).sendToTarget();
}
- if (routeId != null) {
+ // Only let the system connect to new global routes for now.
+ // A similar check exists in the display manager for wifi display.
+ if (routeId != null && clientRecord.mTrusted) {
clientRecord.mUserRecord.mHandler.obtainMessage(
UserHandler.MSG_SELECT_ROUTE, routeId).sendToTarget();
}
@@ -486,17 +497,19 @@ public final class MediaRouterService extends IMediaRouterService.Stub
public final IMediaRouterClient mClient;
public final int mPid;
public final String mPackageName;
+ public final boolean mTrusted;
public int mRouteTypes;
public boolean mActiveScan;
public String mSelectedRouteId;
public ClientRecord(UserRecord userRecord, IMediaRouterClient client,
- int pid, String packageName) {
+ int pid, String packageName, boolean trusted) {
mUserRecord = userRecord;
mClient = client;
mPid = pid;
mPackageName = packageName;
+ mTrusted = trusted;
}
public void dispose() {
@@ -508,10 +521,15 @@ public final class MediaRouterService extends IMediaRouterService.Stub
clientDied(this);
}
+ MediaRouterClientState getState() {
+ return mTrusted ? mUserRecord.mTrustedState : mUserRecord.mUntrustedState;
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + this);
final String indent = prefix + " ";
+ pw.println(indent + "mTrusted=" + mTrusted);
pw.println(indent + "mRouteTypes=0x" + Integer.toHexString(mRouteTypes));
pw.println(indent + "mActiveScan=" + mActiveScan);
pw.println(indent + "mSelectedRouteId=" + mSelectedRouteId);
@@ -531,7 +549,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
public final int mUserId;
public final ArrayList<ClientRecord> mClientRecords = new ArrayList<ClientRecord>();
public final UserHandler mHandler;
- public MediaRouterClientState mState;
+ public MediaRouterClientState mTrustedState;
+ public MediaRouterClientState mUntrustedState;
public UserRecord(int userId) {
mUserId = userId;
@@ -551,6 +570,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
pw.println(indent + "<no clients>");
}
+ pw.println(indent + "State");
+ pw.println(indent + "mTrustedState=" + mTrustedState);
+ pw.println(indent + "mUntrustedState=" + mUntrustedState);
+
if (!mHandler.runWithScissors(new Runnable() {
@Override
public void run() {
@@ -729,8 +752,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
final int newDiscoveryMode;
- if ((routeTypes & (MediaRouter.ROUTE_TYPE_LIVE_VIDEO
- | MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) != 0) {
+ if ((routeTypes & MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY) != 0) {
if (activeScan) {
newDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_ACTIVE;
} else {
@@ -968,19 +990,30 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private void updateClientState() {
mClientStateUpdateScheduled = false;
- // Build a new client state.
- MediaRouterClientState state = new MediaRouterClientState();
- state.globallySelectedRouteId = mGloballySelectedRouteRecord != null ?
+ final String globallySelectedRouteId = mGloballySelectedRouteRecord != null ?
mGloballySelectedRouteRecord.getUniqueId() : null;
+
+ // Build a new client state for trusted clients.
+ MediaRouterClientState trustedState = new MediaRouterClientState();
+ trustedState.globallySelectedRouteId = globallySelectedRouteId;
final int providerCount = mProviderRecords.size();
for (int i = 0; i < providerCount; i++) {
- mProviderRecords.get(i).appendClientState(state);
+ mProviderRecords.get(i).appendClientState(trustedState);
+ }
+
+ // Build a new client state for untrusted clients that can only see
+ // the currently selected route.
+ MediaRouterClientState untrustedState = new MediaRouterClientState();
+ untrustedState.globallySelectedRouteId = globallySelectedRouteId;
+ if (globallySelectedRouteId != null) {
+ untrustedState.routes.add(trustedState.getRoute(globallySelectedRouteId));
}
try {
synchronized (mService.mLock) {
// Update the UserRecord.
- mUserRecord.mState = state;
+ mUserRecord.mTrustedState = trustedState;
+ mUserRecord.mUntrustedState = untrustedState;
// Collect all clients.
final int count = mUserRecord.mClientRecords.size();