Allow applications to connect to known wifi displays.

Bug: 7177920
Change-Id: I9d8406e1016988e2cd267dfa52d78a829f1b385e
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 @@
 
     @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 @@
 
     @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 @@
 
     @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 @@
 
     @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 @@
 
     @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 @@
 
     @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 @@
         }
     }
 
+    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.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 @@
         });
     }
 
-    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 @@
         });
     }
 
+    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 @@
                         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);
         }
     };