Loading core/java/android/hardware/display/DisplayManager.java +5 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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. Loading media/java/android/media/MediaRouter.java +65 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -82,6 +85,7 @@ public class MediaRouter { RouteInfo mSelectedRoute; final boolean mCanConfigureWifiDisplays; boolean mActivelyScanningWifiDisplays; int mDiscoveryRequestRouteTypes; Loading Loading @@ -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 Loading Loading @@ -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; } } Loading @@ -268,7 +279,7 @@ public class MediaRouter { } // Update wifi display scanning. if (activeScanWifiDisplay) { if (activeScanWifiDisplay && mCanConfigureWifiDisplays) { if (!mActivelyScanningWifiDisplays) { mActivelyScanningWifiDisplays = true; mHandler.post(mScanWifiDisplays); Loading Loading @@ -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; } Loading Loading @@ -536,7 +548,7 @@ public class MediaRouter { } if (changed) { dispatchRouteChanged(route); dispatchRouteChanged(route, oldSupportedTypes); } if (volumeChanged) { dispatchRouteVolumeChanged(route); Loading Loading @@ -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)) { 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(); } Loading Loading @@ -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); } } } Loading Loading @@ -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; Loading Loading @@ -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(); } } Loading Loading @@ -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; } } Loading media/java/android/media/MediaRouterClientState.java +17 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading packages/SystemUI/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -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" Loading services/java/com/android/server/display/DisplayManagerService.java +22 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 { Loading @@ -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 { Loading @@ -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 { Loading @@ -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) { Loading @@ -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 { Loading @@ -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 { Loading @@ -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) { Loading @@ -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) { Loading Loading
core/java/android/hardware/display/DisplayManager.java +5 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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. Loading
media/java/android/media/MediaRouter.java +65 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -82,6 +85,7 @@ public class MediaRouter { RouteInfo mSelectedRoute; final boolean mCanConfigureWifiDisplays; boolean mActivelyScanningWifiDisplays; int mDiscoveryRequestRouteTypes; Loading Loading @@ -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 Loading Loading @@ -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; } } Loading @@ -268,7 +279,7 @@ public class MediaRouter { } // Update wifi display scanning. if (activeScanWifiDisplay) { if (activeScanWifiDisplay && mCanConfigureWifiDisplays) { if (!mActivelyScanningWifiDisplays) { mActivelyScanningWifiDisplays = true; mHandler.post(mScanWifiDisplays); Loading Loading @@ -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; } Loading Loading @@ -536,7 +548,7 @@ public class MediaRouter { } if (changed) { dispatchRouteChanged(route); dispatchRouteChanged(route, oldSupportedTypes); } if (volumeChanged) { dispatchRouteVolumeChanged(route); Loading Loading @@ -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)) { 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(); } Loading Loading @@ -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); } } } Loading Loading @@ -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; Loading Loading @@ -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(); } } Loading Loading @@ -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; } } Loading
media/java/android/media/MediaRouterClientState.java +17 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading
packages/SystemUI/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -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" Loading
services/java/com/android/server/display/DisplayManagerService.java +22 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 { Loading @@ -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 { Loading @@ -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 { Loading @@ -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) { Loading @@ -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 { Loading @@ -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 { Loading @@ -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) { Loading @@ -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) { Loading