diff options
author | Jeff Brown <jeffbrown@google.com> | 2013-11-21 23:00:23 -0800 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2013-11-21 23:00:23 -0800 |
commit | 2ab3ec21c0d0b13533434cacf72cc1bc0c81bb32 (patch) | |
tree | 23ebd075131bffc6f90d95cb3d6d2143dbe1a07a | |
parent | 816fe75304f683e044b46aaf135159c0c2e11e21 (diff) | |
parent | 2458681b3ea4571d2f1254ef597475fe6a582907 (diff) | |
download | frameworks_base-2ab3ec21c0d0b13533434cacf72cc1bc0c81bb32.zip frameworks_base-2ab3ec21c0d0b13533434cacf72cc1bc0c81bb32.tar.gz frameworks_base-2ab3ec21c0d0b13533434cacf72cc1bc0c81bb32.tar.bz2 |
am 2458681b: am 263c4310: am ce468a35: Stop wifi display discovery when no longer needed.
* commit '2458681b3ea4571d2f1254ef597475fe6a582907':
Stop wifi display discovery when no longer needed.
8 files changed, 318 insertions, 124 deletions
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index d5208d9..093e0e9 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -297,16 +297,31 @@ public final class DisplayManager { } /** - * Initiates a fresh scan of availble Wifi displays. + * Starts scanning for available Wifi displays. * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. * <p> + * Calls to this method nest and must be matched by an equal number of calls to + * {@link #stopWifiDisplayScan()}. + * </p><p> + * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. + * </p> + * + * @hide + */ + public void startWifiDisplayScan() { + mGlobal.startWifiDisplayScan(); + } + + /** + * Stops scanning for available Wifi displays. + * <p> * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. * </p> * * @hide */ - public void scanWifiDisplays() { - mGlobal.scanWifiDisplays(); + public void stopWifiDisplayScan() { + mGlobal.stopWifiDisplayScan(); } /** diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 936a086..3417430 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -72,6 +72,8 @@ public final class DisplayManagerGlobal { private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>(); private int[] mDisplayIdCache; + private int mWifiDisplayScanNestCount; + private DisplayManagerGlobal(IDisplayManager dm) { mDm = dm; } @@ -267,11 +269,32 @@ public final class DisplayManagerGlobal { } } - public void scanWifiDisplays() { - try { - mDm.scanWifiDisplays(); - } catch (RemoteException ex) { - Log.e(TAG, "Failed to scan for Wifi displays.", ex); + public void startWifiDisplayScan() { + synchronized (mLock) { + if (mWifiDisplayScanNestCount++ == 0) { + registerCallbackIfNeededLocked(); + try { + mDm.startWifiDisplayScan(); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to scan for Wifi displays.", ex); + } + } + } + } + + public void stopWifiDisplayScan() { + synchronized (mLock) { + if (--mWifiDisplayScanNestCount == 0) { + try { + mDm.stopWifiDisplayScan(); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to scan for Wifi displays.", ex); + } + } else if (mWifiDisplayScanNestCount < 0) { + Log.wtf(TAG, "Wifi display scan nest count became negative: " + + mWifiDisplayScanNestCount); + mWifiDisplayScanNestCount = 0; + } } } diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 6b2c887..68eb13f 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -29,11 +29,14 @@ interface IDisplayManager { void registerCallback(in IDisplayManagerCallback callback); - // No permissions required. - void scanWifiDisplays(); + // Requires CONFIGURE_WIFI_DISPLAY permission. + // The process must have previously registered a callback. + void startWifiDisplayScan(); - // Requires CONFIGURE_WIFI_DISPLAY permission to connect to an unknown device. - // No permissions required to connect to a known device. + // Requires CONFIGURE_WIFI_DISPLAY permission. + void stopWifiDisplayScan(); + + // Requires CONFIGURE_WIFI_DISPLAY permission. void connectWifiDisplay(String address); // No permissions required. @@ -45,6 +48,12 @@ interface IDisplayManager { // Requires CONFIGURE_WIFI_DISPLAY permission. void forgetWifiDisplay(String address); + // Requires CONFIGURE_WIFI_DISPLAY permission. + void pauseWifiDisplay(); + + // Requires CONFIGURE_WIFI_DISPLAY permission. + void resumeWifiDisplay(); + // No permissions required. WifiDisplayStatus getWifiDisplayStatus(); @@ -55,10 +64,4 @@ interface IDisplayManager { // No permissions required but must be same Uid as the creator. void releaseVirtualDisplay(in IBinder token); - - // Requires CONFIGURE_WIFI_DISPLAY permission. - void pauseWifiDisplay(); - - // Requires CONFIGURE_WIFI_DISPLAY permission. - void resumeWifiDisplay(); } diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index 3f1851d..de20227 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -61,9 +61,6 @@ public class MediaRouter { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); static class Static implements DisplayManager.DisplayListener { - // Time between wifi display scans when actively scanning in milliseconds. - private static final int WIFI_DISPLAY_SCAN_INTERVAL = 10000; - final Context mAppContext; final Resources mResources; final IAudioService mAudioService; @@ -87,6 +84,7 @@ public class MediaRouter { final boolean mCanConfigureWifiDisplays; boolean mActivelyScanningWifiDisplays; + String mPreviousActiveWifiDisplayAddress; int mDiscoveryRequestRouteTypes; boolean mDiscoverRequestActiveScan; @@ -106,16 +104,6 @@ public class MediaRouter { } }; - final Runnable mScanWifiDisplays = new Runnable() { - @Override - public void run() { - if (mActivelyScanningWifiDisplays) { - mDisplayService.scanWifiDisplays(); - mHandler.postDelayed(this, WIFI_DISPLAY_SCAN_INTERVAL); - } - } - }; - Static(Context appContext) { mAppContext = appContext; mResources = Resources.getSystem(); @@ -279,15 +267,24 @@ public class MediaRouter { } // Update wifi display scanning. - if (activeScanWifiDisplay && mCanConfigureWifiDisplays) { - if (!mActivelyScanningWifiDisplays) { - mActivelyScanningWifiDisplays = true; - mHandler.post(mScanWifiDisplays); + // TODO: All of this should be managed by the media router service. + if (mCanConfigureWifiDisplays) { + if (mSelectedRoute != null + && mSelectedRoute.matchesTypes(ROUTE_TYPE_REMOTE_DISPLAY)) { + // Don't scan while already connected to a remote display since + // it may interfere with the ongoing transmission. + activeScanWifiDisplay = false; } - } else { - if (mActivelyScanningWifiDisplays) { - mActivelyScanningWifiDisplays = false; - mHandler.removeCallbacks(mScanWifiDisplays); + if (activeScanWifiDisplay) { + if (!mActivelyScanningWifiDisplays) { + mActivelyScanningWifiDisplays = true; + mDisplayService.startWifiDisplayScan(); + } + } else { + if (mActivelyScanningWifiDisplays) { + mActivelyScanningWifiDisplays = false; + mDisplayService.stopWifiDisplayScan(); + } } } @@ -945,6 +942,9 @@ public class MediaRouter { } dispatchRouteSelected(types & route.getSupportedTypes(), route); } + + // The behavior of active scans may depend on the currently selected route. + sStatic.updateDiscoveryRequest(); } static void selectDefaultRouteStatic() { @@ -1291,10 +1291,8 @@ public class MediaRouter { } static void updateWifiDisplayStatus(WifiDisplayStatus status) { - boolean wantScan = false; WifiDisplay[] displays; WifiDisplay activeDisplay; - if (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) { displays = status.getDisplays(); activeDisplay = status.getActiveDisplay(); @@ -1314,6 +1312,8 @@ public class MediaRouter { displays = WifiDisplay.EMPTY_ARRAY; activeDisplay = null; } + String activeDisplayAddress = activeDisplay != null ? + activeDisplay.getDeviceAddress() : null; // Add or update routes. for (int i = 0; i < displays.length; i++) { @@ -1323,9 +1323,11 @@ public class MediaRouter { if (route == null) { route = makeWifiDisplayRoute(d, status); addRouteStatic(route); - wantScan = true; } else { - updateWifiDisplayRoute(route, d, status); + String address = d.getDeviceAddress(); + boolean disconnected = !address.equals(activeDisplayAddress) + && address.equals(sStatic.mPreviousActiveWifiDisplayAddress); + updateWifiDisplayRoute(route, d, status, disconnected); } if (d.equals(activeDisplay)) { selectRouteStatic(route.getSupportedTypes(), route, false); @@ -1343,6 +1345,10 @@ public class MediaRouter { } } } + + // Remember the current active wifi display address so that we can infer disconnections. + // TODO: This hack will go away once all of this is moved into the media router service. + sStatic.mPreviousActiveWifiDisplayAddress = activeDisplayAddress; } private static boolean shouldShowWifiDisplay(WifiDisplay d, WifiDisplay activeDisplay) { @@ -1400,7 +1406,8 @@ public class MediaRouter { } private static void updateWifiDisplayRoute( - RouteInfo route, WifiDisplay display, WifiDisplayStatus wfdStatus) { + RouteInfo route, WifiDisplay display, WifiDisplayStatus wfdStatus, + boolean disconnected) { boolean changed = false; final String newName = display.getFriendlyDisplayName(); if (!route.getName().equals(newName)) { @@ -1418,7 +1425,7 @@ public class MediaRouter { dispatchRouteChanged(route); } - if (!enabled && route.isSelected()) { + if ((!enabled || disconnected) && route.isSelected()) { // Oops, no longer available. Reselect the default. selectDefaultRouteStatic(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java index 4012ad8..12e08d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java @@ -813,14 +813,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, } else { connectedRoute = null; connecting = false; - final int count = mMediaRouter.getRouteCount(); - for (int i = 0; i < count; i++) { - MediaRouter.RouteInfo route = mMediaRouter.getRouteAt(i); - if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) { - enabled = true; - break; - } - } + enabled = mMediaRouter.isRouteAvailable(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, + MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE); } mRemoteDisplayState.enabled = enabled; diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 85681c3..73040d5 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -35,6 +35,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.text.TextUtils; +import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.view.Display; @@ -171,6 +172,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // The Wifi display adapter, or null if not registered. private WifiDisplayAdapter mWifiDisplayAdapter; + // The number of active wifi display scan requests. + private int mWifiDisplayScanRequestCount; + // The virtual display adapter, or null if not registered. private VirtualDisplayAdapter mVirtualDisplayAdapter; @@ -445,29 +449,81 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - private void onCallbackDied(int pid) { + private void onCallbackDied(CallbackRecord record) { synchronized (mSyncRoot) { - mCallbacks.remove(pid); + mCallbacks.remove(record.mPid); + stopWifiDisplayScanLocked(record); } } @Override // Binder call - public void scanWifiDisplays() { + public void startWifiDisplayScan() { mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to scan wifi displays"); + "Permission required to start wifi display scans"); + final int callingPid = Binder.getCallingPid(); final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { + CallbackRecord record = mCallbacks.get(callingPid); + if (record == null) { + throw new IllegalStateException("The calling process has not " + + "registered an IDisplayManagerCallback."); + } + startWifiDisplayScanLocked(record); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + private void startWifiDisplayScanLocked(CallbackRecord record) { + if (!record.mWifiDisplayScanRequested) { + record.mWifiDisplayScanRequested = true; + if (mWifiDisplayScanRequestCount++ == 0) { if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestScanLocked(); + mWifiDisplayAdapter.requestStartScanLocked(); } } + } + } + + @Override // Binder call + public void stopWifiDisplayScan() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to stop wifi display scans"); + + final int callingPid = Binder.getCallingPid(); + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mSyncRoot) { + CallbackRecord record = mCallbacks.get(callingPid); + if (record == null) { + throw new IllegalStateException("The calling process has not " + + "registered an IDisplayManagerCallback."); + } + stopWifiDisplayScanLocked(record); + } } finally { Binder.restoreCallingIdentity(token); } } + private void stopWifiDisplayScanLocked(CallbackRecord record) { + if (record.mWifiDisplayScanRequested) { + record.mWifiDisplayScanRequested = false; + if (--mWifiDisplayScanRequestCount == 0) { + if (mWifiDisplayAdapter != null) { + mWifiDisplayAdapter.requestStopScanLocked(); + } + } else if (mWifiDisplayScanRequestCount < 0) { + Log.wtf(TAG, "mWifiDisplayScanRequestCount became negative: " + + mWifiDisplayScanRequestCount); + mWifiDisplayScanRequestCount = 0; + } + } + } + @Override // Binder call public void connectWifiDisplay(String address) { if (address == null) { @@ -1088,6 +1144,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { pw.println(" mDefaultViewport=" + mDefaultViewport); pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); + pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); ipw.increaseIndent(); @@ -1115,6 +1172,15 @@ public final class DisplayManagerService extends IDisplayManager.Stub { pw.println(" Display " + displayId + ":"); display.dumpLocked(ipw); } + + final int callbackCount = mCallbacks.size(); + pw.println(); + pw.println("Callbacks: size=" + callbackCount); + for (int i = 0; i < callbackCount; i++) { + CallbackRecord callback = mCallbacks.valueAt(i); + pw.println(" " + i + ": mPid=" + callback.mPid + + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); + } } } @@ -1215,9 +1281,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } private final class CallbackRecord implements DeathRecipient { - private final int mPid; + public final int mPid; private final IDisplayManagerCallback mCallback; + public boolean mWifiDisplayScanRequested; + public CallbackRecord(int pid, IDisplayManagerCallback callback) { mPid = pid; mCallback = callback; @@ -1228,7 +1296,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { if (DEBUG) { Slog.d(TAG, "Display listener for pid " + mPid + " died."); } - onCallbackDied(mPid); + onCallbackDied(this); } public void notifyDisplayEventAsync(int displayId, int event) { diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index fdef039..cd57941 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -127,7 +127,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate); pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers); - + // Try to dump the controller state. if (mDisplayController == null) { pw.println("mDisplayController=null"); @@ -157,43 +157,49 @@ final class WifiDisplayAdapter extends DisplayAdapter { }); } - public void requestScanLocked() { + public void requestStartScanLocked() { if (DEBUG) { - Slog.d(TAG, "requestScanLocked"); + Slog.d(TAG, "requestStartScanLocked"); } getHandler().post(new Runnable() { @Override public void run() { if (mDisplayController != null) { - mDisplayController.requestScan(); + mDisplayController.requestStartScan(); } } }); } - public void requestConnectLocked(final String address) { + public void requestStopScanLocked() { if (DEBUG) { - Slog.d(TAG, "requestConnectLocked: address=" + address); + Slog.d(TAG, "requestStopScanLocked"); } getHandler().post(new Runnable() { @Override public void run() { if (mDisplayController != null) { - mDisplayController.requestConnect(address); + mDisplayController.requestStopScan(); } } }); } - private boolean isRememberedDisplayLocked(String address) { - for (WifiDisplay display : mRememberedDisplays) { - if (display.getDeviceAddress().equals(address)) { - return true; - } + public void requestConnectLocked(final String address) { + if (DEBUG) { + Slog.d(TAG, "requestConnectLocked: address=" + address); } - return false; + + getHandler().post(new Runnable() { + @Override + public void run() { + if (mDisplayController != null) { + mDisplayController.requestConnect(address); + } + } + }); } public void requestPauseLocked() { @@ -552,20 +558,20 @@ final class WifiDisplayAdapter extends DisplayAdapter { } @Override - public void onScanFinished(WifiDisplay[] availableDisplays) { + public void onScanResults(WifiDisplay[] availableDisplays) { synchronized (getSyncRoot()) { availableDisplays = mPersistentDataStore.applyWifiDisplayAliases( availableDisplays); - // check if any of the available displays changed canConnect status boolean changed = !Arrays.equals(mAvailableDisplays, availableDisplays); + + // Check whether any of the available displays changed canConnect status. for (int i = 0; !changed && i<availableDisplays.length; i++) { changed = availableDisplays[i].canConnect() != mAvailableDisplays[i].canConnect(); } - if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING || changed) { - mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; + if (changed) { mAvailableDisplays = availableDisplays; fixRememberedDisplayNamesFromAvailableDisplaysLocked(); updateDisplaysLocked(); @@ -575,6 +581,16 @@ final class WifiDisplayAdapter extends DisplayAdapter { } @Override + public void onScanFinished() { + synchronized (getSyncRoot()) { + if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING) { + mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; + scheduleStatusChangedBroadcastLocked(); + } + } + } + + @Override public void onDisplayConnecting(WifiDisplay display) { synchronized (getSyncRoot()) { display = mPersistentDataStore.applyWifiDisplayAlias(display); diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java index 932b42e..dbb59b2 100644 --- a/services/java/com/android/server/display/WifiDisplayController.java +++ b/services/java/com/android/server/display/WifiDisplayController.java @@ -74,12 +74,19 @@ 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 = 60; + private static final int CONNECTION_TIMEOUT_SECONDS = 30; private static final int RTSP_TIMEOUT_SECONDS = 30; private static final int RTSP_TIMEOUT_SECONDS_CERT_MODE = 120; - private static final int DISCOVER_PEERS_MAX_RETRIES = 10; - private static final int DISCOVER_PEERS_RETRY_DELAY_MILLIS = 500; + // We repeatedly issue calls to discover peers every so often for a few reasons. + // 1. The initial request may fail and need to retried. + // 2. Discovery will self-abort after any group is initiated, which may not necessarily + // be what we want to have happen. + // 3. Discovery will self-timeout after 2 minutes, whereas we want discovery to + // be occur for as long as a client is requesting it be. + // 4. We don't seem to get updated results for displays we've already found until + // we ask to discover again, particularly for the isSessionAvailable() property. + private static final int DISCOVER_PEERS_INTERVAL_MILLIS = 10000; private static final int CONNECT_MAX_RETRIES = 3; private static final int CONNECT_RETRY_DELAY_MILLIS = 500; @@ -102,12 +109,12 @@ final class WifiDisplayController implements DumpUtils.Dump { // True if Wifi display is enabled by the user. private boolean mWifiDisplayOnSetting; + // True if a scan was requested independent of whether one is actually in progress. + private boolean mScanRequested; + // True if there is a call to discoverPeers in progress. private boolean mDiscoverPeersInProgress; - // Number of discover peers retries remaining. - private int mDiscoverPeersRetriesLeft; - // The device to which we want to connect, or null if we want to be disconnected. private WifiP2pDevice mDesiredDevice; @@ -208,8 +215,8 @@ final class WifiDisplayController implements DumpUtils.Dump { pw.println("mWfdEnabled=" + mWfdEnabled); pw.println("mWfdEnabling=" + mWfdEnabling); pw.println("mNetworkInfo=" + mNetworkInfo); + pw.println("mScanRequested=" + mScanRequested); pw.println("mDiscoverPeersInProgress=" + mDiscoverPeersInProgress); - pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft); pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice)); pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice)); pw.println("mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice)); @@ -231,8 +238,18 @@ final class WifiDisplayController implements DumpUtils.Dump { } } - public void requestScan() { - discoverPeers(); + public void requestStartScan() { + if (!mScanRequested) { + mScanRequested = true; + updateScanState(); + } + } + + public void requestStopScan() { + if (mScanRequested) { + mScanRequested = false; + updateScanState(); + } } public void requestConnect(String address) { @@ -281,6 +298,7 @@ final class WifiDisplayController implements DumpUtils.Dump { mWfdEnabling = false; mWfdEnabled = true; reportFeatureState(); + updateScanState(); } } @@ -317,6 +335,7 @@ final class WifiDisplayController implements DumpUtils.Dump { mWfdEnabling = false; mWfdEnabled = false; reportFeatureState(); + updateScanState(); disconnect(); } } @@ -339,12 +358,29 @@ final class WifiDisplayController implements DumpUtils.Dump { WifiDisplayStatus.FEATURE_STATE_OFF; } - private void discoverPeers() { - if (!mDiscoverPeersInProgress) { - mDiscoverPeersInProgress = true; - mDiscoverPeersRetriesLeft = DISCOVER_PEERS_MAX_RETRIES; - handleScanStarted(); - tryDiscoverPeers(); + private void updateScanState() { + if (mScanRequested && mWfdEnabled && mDesiredDevice == null) { + if (!mDiscoverPeersInProgress) { + Slog.i(TAG, "Starting Wifi display scan."); + mDiscoverPeersInProgress = true; + handleScanStarted(); + tryDiscoverPeers(); + } + } else { + if (mDiscoverPeersInProgress) { + // Cancel automatic retry right away. + mHandler.removeCallbacks(mDiscoverPeers); + + // Defer actually stopping discovery if we have a connection attempt in progress. + // The wifi display connection attempt often fails if we are not in discovery + // mode. So we allow discovery to continue until we give up trying to connect. + if (mDesiredDevice == null || mDesiredDevice == mConnectedDevice) { + Slog.i(TAG, "Stopping Wifi display scan."); + mDiscoverPeersInProgress = false; + stopPeerDiscovery(); + handleScanFinished(); + } + } } } @@ -356,8 +392,9 @@ final class WifiDisplayController implements DumpUtils.Dump { Slog.d(TAG, "Discover peers succeeded. Requesting peers now."); } - mDiscoverPeersInProgress = false; - requestPeers(); + if (mDiscoverPeersInProgress) { + requestPeers(); + } } @Override @@ -366,30 +403,28 @@ final class WifiDisplayController implements DumpUtils.Dump { Slog.d(TAG, "Discover peers failed with reason " + reason + "."); } - if (mDiscoverPeersInProgress) { - if (reason == 0 && mDiscoverPeersRetriesLeft > 0 && mWfdEnabled) { - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - if (mDiscoverPeersInProgress) { - if (mDiscoverPeersRetriesLeft > 0 && mWfdEnabled) { - mDiscoverPeersRetriesLeft -= 1; - if (DEBUG) { - Slog.d(TAG, "Retrying discovery. Retries left: " - + mDiscoverPeersRetriesLeft); - } - tryDiscoverPeers(); - } else { - handleScanFinished(); - mDiscoverPeersInProgress = false; - } - } - } - }, DISCOVER_PEERS_RETRY_DELAY_MILLIS); - } else { - handleScanFinished(); - mDiscoverPeersInProgress = false; - } + // Ignore the error. + // We will retry automatically in a little bit. + } + }); + + // Retry discover peers periodically until stopped. + mHandler.postDelayed(mDiscoverPeers, DISCOVER_PEERS_INTERVAL_MILLIS); + } + + private void stopPeerDiscovery() { + mWifiP2pManager.stopPeerDiscovery(mWifiP2pChannel, new ActionListener() { + @Override + public void onSuccess() { + if (DEBUG) { + Slog.d(TAG, "Stop peer discovery succeeded."); + } + } + + @Override + public void onFailure(int reason) { + if (DEBUG) { + Slog.d(TAG, "Stop peer discovery failed with reason " + reason + "."); } } }); @@ -414,7 +449,9 @@ final class WifiDisplayController implements DumpUtils.Dump { } } - handleScanFinished(); + if (mDiscoverPeersInProgress) { + handleScanResults(); + } } }); } @@ -428,7 +465,7 @@ final class WifiDisplayController implements DumpUtils.Dump { }); } - private void handleScanFinished() { + private void handleScanResults() { final int count = mAvailableWifiDisplayPeers.size(); final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count); for (int i = 0; i < count; i++) { @@ -440,7 +477,16 @@ final class WifiDisplayController implements DumpUtils.Dump { mHandler.post(new Runnable() { @Override public void run() { - mListener.onScanFinished(displays); + mListener.onScanResults(displays); + } + }); + } + + private void handleScanFinished() { + mHandler.post(new Runnable() { + @Override + public void run() { + mListener.onScanFinished(); } }); } @@ -483,6 +529,12 @@ final class WifiDisplayController implements DumpUtils.Dump { return; } + if (!mWfdEnabled) { + Slog.i(TAG, "Ignoring request to connect to Wifi display because the " + +" feature is currently disabled: " + device.deviceName); + return; + } + mDesiredDevice = device; mConnectionRetriesLeft = CONNECT_MAX_RETRIES; updateConnection(); @@ -507,6 +559,10 @@ final class WifiDisplayController implements DumpUtils.Dump { * connection is established (or not). */ private void updateConnection() { + // Step 0. Stop scans if necessary to prevent interference while connected. + // Resume scans later when no longer attempting to connect. + updateScanState(); + // Step 1. Before we try to connect to a new device, tell the system we // have disconnected from the old one. if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) { @@ -660,7 +716,7 @@ final class WifiDisplayController implements DumpUtils.Dump { return; // wait for asynchronous callback } - // Step 6. Listen for incoming connections. + // Step 6. Listen for incoming RTSP connection. if (mConnectedDevice != null && mRemoteDisplay == null) { Inet4Address addr = getInterfaceAddress(mConnectedDeviceGroupInfo); if (addr == null) { @@ -816,7 +872,11 @@ final class WifiDisplayController implements DumpUtils.Dump { } } else { mConnectedDeviceGroupInfo = null; - disconnect(); + + // Disconnect if we lost the network while connecting or connected to a display. + if (mConnectingDevice != null || mConnectedDevice != null) { + disconnect(); + } // After disconnection for a group, for some reason we have a tendency // to get a peer change notification with an empty list of peers. @@ -827,6 +887,13 @@ final class WifiDisplayController implements DumpUtils.Dump { } } + private final Runnable mDiscoverPeers = new Runnable() { + @Override + public void run() { + tryDiscoverPeers(); + } + }; + private final Runnable mConnectionTimeout = new Runnable() { @Override public void run() { @@ -1032,7 +1099,8 @@ final class WifiDisplayController implements DumpUtils.Dump { void onFeatureStateChanged(int featureState); void onScanStarted(); - void onScanFinished(WifiDisplay[] availableDisplays); + void onScanResults(WifiDisplay[] availableDisplays); + void onScanFinished(); void onDisplayConnecting(WifiDisplay display); void onDisplayConnectionFailed(); |