From f8f0eddd07d22ab815d97dd32ae6ed52dc31a80c Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Tue, 11 Sep 2012 17:05:11 -0700 Subject: [PATCH] Improve reporting of wifi connection state. We should only report that the wifi display is connected after the RTSP connection has been fully established. Change-Id: Ifc6bc5d5cebd42d551026885b31cbc74b7ece2b1 --- .../server/display/WifiDisplayAdapter.java | 126 +++-------------- .../server/display/WifiDisplayController.java | 128 ++++++++++++++---- 2 files changed, 123 insertions(+), 131 deletions(-) diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index ee82050d5e8be..b75940e36982b 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -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; - } - } - } } diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java index 144b3913e6268..6e0be5526fbd5 100644 --- a/services/java/com/android/server/display/WifiDisplayController.java +++ b/services/java/com/android/server/display/WifiDisplayController.java @@ -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) { - Slog.i(TAG, "Failed to initiate connection to Wifi display: " - + newDevice.deviceName + ", reason=" + reason); if (mConnectingDevice == newDevice) { + Slog.i(TAG, "Failed to initiate connection to Wifi display: " + + newDevice.deviceName + ", reason=" + reason); 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,17 +512,57 @@ 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; - mHandler.post(new Runnable() { + Slog.i(TAG, "Listening for RTSP connection on " + iface + + " from Wifi display: " + mConnectedDevice.deviceName); + + mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() { @Override - public void run() { - mListener.onDisplayConnected(display, iface); + 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, + 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); } } @@ -591,17 +651,30 @@ 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) { + Slog.i(TAG, "Wifi display connection failed!"); + + mHandler.post(new Runnable() { + @Override + public void run() { + mListener.onDisplayConnectionFailed(); + } + }); + if (mDesiredDevice != null) { - Slog.i(TAG, "Wifi display connection failed!"); - - mHandler.post(new Runnable() { - @Override - public void run() { - mListener.onDisplayConnectionFailed(); - } - }); - 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(); } }