From bc335457462a12434a9df6955de1dd693cdccac7 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Wed, 26 Sep 2012 18:34:47 -0700 Subject: Allow applications to connect to known wifi displays. Bug: 7177920 Change-Id: I9d8406e1016988e2cd267dfa52d78a829f1b385e --- .../android/hardware/display/DisplayManager.java | 11 ++++-- .../android/hardware/display/IDisplayManager.aidl | 9 +++-- .../server/display/DisplayManagerService.java | 43 ++++++++-------------- .../android/server/display/WifiDisplayAdapter.java | 28 +++++++++++--- 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 58a0f13..28e320b 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -46,9 +46,7 @@ public final class DisplayManager { * The status is provided as a {@link WifiDisplayStatus} object in the * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra. *

- * This broadcast is only sent to registered receivers with the - * {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} permission and can - * only be sent by the system. + * This broadcast is only sent to registered receivers and can only be sent by the system. *

* @hide */ @@ -163,6 +161,9 @@ public final class DisplayManager { *

* Automatically remembers the display after a successful connection, if not * already remembered. + *

+ * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect + * to unknown displays. No permissions are required to connect to already known displays. *

* * @param deviceAddress The MAC address of the device to which we should connect. @@ -187,6 +188,8 @@ public final class DisplayManager { * The display must already be remembered for this call to succeed. In other words, * we must already have successfully connected to the display at least once and then * not forgotten it. + *

+ * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. *

* * @param deviceAddress The MAC address of the device to rename. @@ -202,6 +205,8 @@ public final class DisplayManager { * Forgets a previously remembered Wifi display. *

* Automatically disconnects from the display if currently connected to it. + *

+ * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. *

* * @param deviceAddress The MAC address of the device to forget. diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 4b6fb53..79aad78 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -28,13 +28,14 @@ interface IDisplayManager { void registerCallback(in IDisplayManagerCallback callback); - // Requires CONFIGURE_WIFI_DISPLAY permission. + // No permissions required. void scanWifiDisplays(); - // Requires CONFIGURE_WIFI_DISPLAY permission. + // Requires CONFIGURE_WIFI_DISPLAY permission to connect to an unknown device. + // No permissions required to connect to a known device. void connectWifiDisplay(String address); - // Requires CONFIGURE_WIFI_DISPLAY permission. + // No permissions required. void disconnectWifiDisplay(); // Requires CONFIGURE_WIFI_DISPLAY permission. @@ -43,6 +44,6 @@ interface IDisplayManager { // Requires CONFIGURE_WIFI_DISPLAY permission. void forgetWifiDisplay(String address); - // Requires CONFIGURE_WIFI_DISPLAY permission. + // No permissions required. WifiDisplayStatus getWifiDisplayStatus(); } diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 85f3b56..f348cb6 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -352,11 +352,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public void scanWifiDisplays() { - if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission"); - } - final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { @@ -371,19 +366,16 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public void connectWifiDisplay(String address) { - if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission"); - } if (address == null) { throw new IllegalArgumentException("address must not be null"); } + final boolean trusted = canCallerConfigureWifiDisplay(); final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestConnectLocked(address); + mWifiDisplayAdapter.requestConnectLocked(address, trusted); } } } finally { @@ -393,11 +385,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public void disconnectWifiDisplay() { - if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission"); - } - final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { @@ -412,13 +399,13 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public void renameWifiDisplay(String address, String alias) { - if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission"); - } 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."); + } final long token = Binder.clearCallingIdentity(); try { @@ -434,13 +421,13 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public void forgetWifiDisplay(String address) { - if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission"); - } 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."); + } final long token = Binder.clearCallingIdentity(); try { @@ -456,11 +443,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public WifiDisplayStatus getWifiDisplayStatus() { - if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission"); - } - final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { @@ -475,6 +457,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } + private boolean canCallerConfigureWifiDisplay() { + return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) + == PackageManager.PERMISSION_GRANTED; + } + private void registerDefaultDisplayAdapter() { // Register default display adapter. synchronized (mSyncRoot) { diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index 1d50ded..4a89be7 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -27,6 +27,7 @@ import android.hardware.display.WifiDisplayStatus; import android.media.RemoteDisplay; import android.os.Handler; import android.os.IBinder; +import android.util.Slog; import android.view.Surface; import java.io.PrintWriter; @@ -121,7 +122,17 @@ final class WifiDisplayAdapter extends DisplayAdapter { }); } - public void requestConnectLocked(final String address) { + public void requestConnectLocked(final String address, final boolean 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; + } + } + } + getHandler().post(new Runnable() { @Override public void run() { @@ -132,6 +143,15 @@ final class WifiDisplayAdapter extends DisplayAdapter { }); } + private boolean isRememberedDisplayLocked(String address) { + for (WifiDisplay display : mRememberedDisplays) { + if (display.getDeviceAddress().equals(address)) { + return true; + } + } + return false; + } + public void requestDisconnectLocked() { getHandler().post(new Runnable() { @Override @@ -241,10 +261,8 @@ final class WifiDisplayAdapter extends DisplayAdapter { getWifiDisplayStatusLocked()); } - // Send protected broadcast about wifi display status to receivers that - // have the required permission. - getContext().sendBroadcast(intent, - android.Manifest.permission.CONFIGURE_WIFI_DISPLAY); + // Send protected broadcast about wifi display status to registered receivers. + getContext().sendBroadcast(intent); } }; -- cgit v1.1