Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc335457 authored by Jeff Brown's avatar Jeff Brown
Browse files

Allow applications to connect to known wifi displays.

Bug: 7177920
Change-Id: I9d8406e1016988e2cd267dfa52d78a829f1b385e
parent 62c82e4d
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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.
     * </p><p>
     * 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.
     * </p>
     * @hide
     */
@@ -163,6 +161,9 @@ public final class DisplayManager {
     * <p>
     * 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.
     * </p>
     *
     * @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.
     * </p><p>
     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
     * </p>
     *
     * @param deviceAddress The MAC address of the device to rename.
@@ -202,6 +205,8 @@ public final class DisplayManager {
     * Forgets a previously remembered Wifi display.
     * <p>
     * Automatically disconnects from the display if currently connected to it.
     * </p><p>
     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
     * </p>
     *
     * @param deviceAddress The MAC address of the device to forget.
+5 −4
Original line number Diff line number Diff line
@@ -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();
}
+15 −28
Original line number Diff line number Diff line
@@ -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) {
+23 −5
Original line number Diff line number Diff line
@@ -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);
        }
    };