diff options
author | Jeff Brown <jeffbrown@google.com> | 2013-11-14 18:16:08 -0800 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2013-11-15 00:29:43 -0800 |
commit | af574183c274f51d04487a9c8355e9f34a1150f2 (patch) | |
tree | c325b02a379f86bc9d8eb42b0bb5d8b700cc80bb /services | |
parent | 1907c0d280d97776708810c9d24931aa6f818790 (diff) | |
download | frameworks_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
Diffstat (limited to 'services')
3 files changed, 71 insertions, 53 deletions
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(); |