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

Commit eda63986 authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 81da4c77: am c7b6ec7a: Merge "Improve reporting of wifi connection state." into jb-mr1-dev

* commit '81da4c77':
  Improve reporting of wifi connection state.
parents 3acdb339 81da4c77
Loading
Loading
Loading
Loading
+22 −104
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ 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;
@@ -50,8 +49,8 @@ import java.util.Arrays;
final class WifiDisplayAdapter extends DisplayAdapter {
    private static final String TAG = "WifiDisplayAdapter";

    private WifiDisplayHandle mDisplayHandle;
    private WifiDisplayController mDisplayController;
    private WifiDisplayDevice mDisplayDevice;

    private WifiDisplayStatus mCurrentStatus;
    private boolean mEnabled;
@@ -71,13 +70,6 @@ final class WifiDisplayAdapter extends DisplayAdapter {
    public void dumpLocked(PrintWriter pw) {
        super.dumpLocked(pw);

        if (mDisplayHandle == null) {
            pw.println("mDisplayHandle=null");
        } else {
            pw.println("mDisplayHandle:");
            mDisplayHandle.dumpLocked(pw);
        }

        pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
        pw.println("mEnabled=" + mEnabled);
        pw.println("mScanState=" + mScanState);
@@ -151,16 +143,29 @@ final class WifiDisplayAdapter extends DisplayAdapter {
        return mCurrentStatus;
    }

    private void handleConnectLocked(WifiDisplay display, String iface) {
    private void handleConnectLocked(WifiDisplay display,
            Surface surface, int width, int height, int flags) {
        handleDisconnectLocked();

        mDisplayHandle = new WifiDisplayHandle(display.getDeviceName(), iface);
        int deviceFlags = 0;
        if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
            deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
        }

        float refreshRate = 60.0f; // TODO: get this for real

        String name = display.getDeviceName();
        IBinder displayToken = Surface.createDisplay(name);
        mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
                refreshRate, deviceFlags, surface);
        sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
    }

    private void handleDisconnectLocked() {
        if (mDisplayHandle != null) {
            mDisplayHandle.disposeLocked();
            mDisplayHandle = null;
        if (mDisplayDevice != null) {
            mDisplayDevice.clearSurfaceLocked();
            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
            mDisplayDevice = null;
        }
    }

@@ -258,9 +263,10 @@ final class WifiDisplayAdapter extends DisplayAdapter {
        }

        @Override
        public void onDisplayConnected(WifiDisplay display, String iface) {
        public void onDisplayConnected(WifiDisplay display, Surface surface,
                int width, int height, int flags) {
            synchronized (getSyncRoot()) {
                handleConnectLocked(display, iface);
                handleConnectLocked(display, surface, width, height, flags);

                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
                        || mActiveDisplay == null
@@ -337,92 +343,4 @@ final class WifiDisplayAdapter extends DisplayAdapter {
            return mInfo;
        }
    }

    private final class WifiDisplayHandle implements RemoteDisplay.Listener {
        private final String mName;
        private final String mIface;
        private final RemoteDisplay mRemoteDisplay;

        private WifiDisplayDevice mDevice;
        private int mLastError;

        public WifiDisplayHandle(String name, String iface) {
            mName = name;
            mIface = iface;
            mRemoteDisplay = RemoteDisplay.listen(iface, this, getHandler());

            Slog.i(TAG, "Listening for Wifi display connections on " + iface
                    + " from " + mName);
        }

        public void disposeLocked() {
            Slog.i(TAG, "Stopped listening for Wifi display connections on " + mIface
                    + " from " + mName);

            removeDisplayLocked();
            mRemoteDisplay.dispose();
        }

        public void dumpLocked(PrintWriter pw) {
            pw.println("  " + mName + ": " + (mDevice != null ? "connected" : "disconnected"));
            pw.println("    mIface=" + mIface);
            pw.println("    mLastError=" + mLastError);
        }

        // Called on the handler thread.
        @Override
        public void onDisplayConnected(Surface surface, int width, int height, int flags) {
            synchronized (getSyncRoot()) {
                mLastError = 0;
                removeDisplayLocked();
                addDisplayLocked(surface, width, height, flags);

                Slog.i(TAG, "Wifi display connected: " + mName);
            }
        }

        // Called on the handler thread.
        @Override
        public void onDisplayDisconnected() {
            synchronized (getSyncRoot()) {
                mLastError = 0;
                removeDisplayLocked();

                Slog.i(TAG, "Wifi display disconnected: " + mName);
            }
        }

        // Called on the handler thread.
        @Override
        public void onDisplayError(int error) {
            synchronized (getSyncRoot()) {
                mLastError = error;
                removeDisplayLocked();

                Slog.i(TAG, "Wifi display disconnected due to error " + error + ": " + mName);
            }
        }

        private void addDisplayLocked(Surface surface, int width, int height, int flags) {
            int deviceFlags = 0;
            if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
                deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
            }

            float refreshRate = 60.0f; // TODO: get this for real

            IBinder displayToken = Surface.createDisplay(mName);
            mDevice = new WifiDisplayDevice(displayToken, mName, width, height,
                    refreshRate, deviceFlags, surface);
            sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
        }

        private void removeDisplayLocked() {
            if (mDevice != null) {
                mDevice.clearSurfaceLocked();
                sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED);
                mDevice = null;
            }
        }
    }
}
+100 −26
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.display.WifiDisplay;
import android.media.RemoteDisplay;
import android.net.NetworkInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
@@ -36,6 +37,7 @@ import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.os.Handler;
import android.util.Slog;
import android.view.Surface;

import java.io.PrintWriter;
import java.net.Inet4Address;
@@ -64,6 +66,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
    private static final int DEFAULT_CONTROL_PORT = 7236;
    private static final int MAX_THROUGHPUT = 50;
    private static final int CONNECTION_TIMEOUT_SECONDS = 30;
    private static final int RTSP_TIMEOUT_SECONDS = 15;

    private static final int DISCOVER_PEERS_MAX_RETRIES = 10;
    private static final int DISCOVER_PEERS_RETRY_DELAY_MILLIS = 500;
@@ -104,12 +107,19 @@ final class WifiDisplayController implements DumpUtils.Dump {
    // The group info obtained after connecting.
    private WifiP2pGroup mConnectedDeviceGroupInfo;

    // The device that we announced to the rest of the system.
    private WifiP2pDevice mPublishedDevice;

    // Number of connection retries remaining.
    private int mConnectionRetriesLeft;

    // The remote display that is listening on the connection.
    // Created after the Wifi P2P network is connected.
    private RemoteDisplay mRemoteDisplay;

    // The remote display interface.
    private String mRemoteDisplayInterface;

    // True if RTSP has connected.
    private boolean mRemoteDisplayConnected;

    public WifiDisplayController(Context context, Handler handler, Listener listener) {
        mContext = context;
        mHandler = handler;
@@ -135,8 +145,10 @@ final class WifiDisplayController implements DumpUtils.Dump {
        pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice));
        pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice));
        pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice));
        pw.println("mPublishedDevice=" + describeWifiP2pDevice(mPublishedDevice));
        pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft);
        pw.println("mRemoteDisplay=" + mRemoteDisplay);
        pw.println("mRemoteDisplayInterface=" + mRemoteDisplayInterface);
        pw.println("mRemoteDisplayConnected=" + mRemoteDisplayConnected);

        pw.println("mKnownWifiDisplayPeers: size=" + mKnownWifiDisplayPeers.size());
        for (WifiP2pDevice device : mKnownWifiDisplayPeers) {
@@ -341,7 +353,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
    }

    private void retryConnection() {
        if (mDesiredDevice != null && mPublishedDevice != mDesiredDevice
        if (mDesiredDevice != null && mConnectedDevice != mDesiredDevice
                && mConnectionRetriesLeft > 0) {
            mConnectionRetriesLeft -= 1;
            Slog.i(TAG, "Retrying Wifi display connection.  Retries left: "
@@ -363,14 +375,22 @@ final class WifiDisplayController implements DumpUtils.Dump {
    private void updateConnection() {
        // Step 1. Before we try to connect to a new device, tell the system we
        // have disconnected from the old one.
        if (mPublishedDevice != null && mPublishedDevice != mDesiredDevice) {
        if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) {
            Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface
                    + " from Wifi display: " + mConnectedDevice.deviceName);

            mRemoteDisplay.dispose();
            mRemoteDisplay = null;
            mRemoteDisplayInterface = null;
            mRemoteDisplayConnected = false;
            mHandler.removeCallbacks(mRtspTimeout);

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mListener.onDisplayDisconnected();
                }
            });
            mPublishedDevice = null;

            // continue to next step
        }
@@ -471,9 +491,9 @@ final class WifiDisplayController implements DumpUtils.Dump {

                @Override
                public void onFailure(int reason) {
                    if (mConnectingDevice == newDevice) {
                        Slog.i(TAG, "Failed to initiate connection to Wifi display: "
                                + newDevice.deviceName + ", reason=" + reason);
                    if (mConnectingDevice == newDevice) {
                        mConnectingDevice = null;
                        handleConnectionFailure(false);
                    }
@@ -482,8 +502,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
            return; // wait for asynchronous callback
        }

        // Step 6. Publish the new connection.
        if (mConnectedDevice != null && mPublishedDevice == null) {
        // Step 6. Listen for incoming connections.
        if (mConnectedDevice != null && mRemoteDisplay == null) {
            Inet4Address addr = getInterfaceAddress(mConnectedDeviceGroupInfo);
            if (addr == null) {
                Slog.i(TAG, "Failed to get local interface address for communicating "
@@ -492,20 +512,60 @@ final class WifiDisplayController implements DumpUtils.Dump {
                return; // done
            }

            final WifiDisplay display = createWifiDisplay(mConnectedDevice);
            final WifiP2pDevice oldDevice = mConnectedDevice;
            final int port = getPortNumber(mConnectedDevice);
            final String iface = addr.getHostAddress() + ":" + port;
            mRemoteDisplayInterface = iface;

            mPublishedDevice = mConnectedDevice;
            Slog.i(TAG, "Listening for RTSP connection on " + iface
                    + " from Wifi display: " + mConnectedDevice.deviceName);

            mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() {
                @Override
                public void onDisplayConnected(final Surface surface,
                        final int width, final int height, final int flags) {
                    if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) {
                        Slog.i(TAG, "Opened RTSP connection with Wifi display: "
                                + mConnectedDevice.deviceName);
                        mRemoteDisplayConnected = true;
                        mHandler.removeCallbacks(mRtspTimeout);

                        final WifiDisplay display = createWifiDisplay(mConnectedDevice);
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                    mListener.onDisplayConnected(display, iface);
                                mListener.onDisplayConnected(display,
                                        surface, width, height, flags);
                            }
                        });
                    }
                }

                @Override
                public void onDisplayDisconnected() {
                    if (mConnectedDevice == oldDevice) {
                        Slog.i(TAG, "Closed RTSP connection with Wifi display: "
                                + mConnectedDevice.deviceName);
                        mHandler.removeCallbacks(mRtspTimeout);
                        disconnect();
                    }
                }

                @Override
                public void onDisplayError(int error) {
                    if (mConnectedDevice == oldDevice) {
                        Slog.i(TAG, "Lost RTSP connection with Wifi display due to error "
                                + error + ": " + mConnectedDevice.deviceName);
                        mHandler.removeCallbacks(mRtspTimeout);
                        handleConnectionFailure(false);
                    }
                }
            }, mHandler);

            mHandler.postDelayed(mRtspTimeout, RTSP_TIMEOUT_SECONDS * 1000);
        }
    }

    private void handleStateChanged(boolean enabled) {
        if (mWifiP2pEnabled != enabled) {
            mWifiP2pEnabled = enabled;
@@ -591,8 +651,20 @@ final class WifiDisplayController implements DumpUtils.Dump {
        }
    };

    private final Runnable mRtspTimeout = new Runnable() {
        @Override
        public void run() {
            if (mConnectedDevice != null
                    && mRemoteDisplay != null && !mRemoteDisplayConnected) {
                Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after "
                        + RTSP_TIMEOUT_SECONDS + " seconds: "
                        + mConnectedDevice.deviceName);
                handleConnectionFailure(true);
            }
        }
    };

    private void handleConnectionFailure(boolean timeoutOccurred) {
        if (mDesiredDevice != null) {
        Slog.i(TAG, "Wifi display connection failed!");

        mHandler.post(new Runnable() {
@@ -602,6 +674,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
            }
        });

        if (mDesiredDevice != null) {
            if (mConnectionRetriesLeft > 0) {
                mHandler.postDelayed(new Runnable() {
                    @Override
@@ -714,7 +787,8 @@ final class WifiDisplayController implements DumpUtils.Dump {

        void onDisplayConnecting(WifiDisplay display);
        void onDisplayConnectionFailed();
        void onDisplayConnected(WifiDisplay display, String iface);
        void onDisplayConnected(WifiDisplay display,
                Surface surface, int width, int height, int flags);
        void onDisplayDisconnected();
    }
}