diff options
Diffstat (limited to 'services/java/com/android/server/display')
3 files changed, 286 insertions, 128 deletions
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 249c8b0..bcb677f 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; @@ -173,6 +174,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; @@ -458,38 +462,94 @@ 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 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) { 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 { @@ -499,12 +559,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 { @@ -520,12 +576,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 { @@ -541,6 +593,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) { @@ -558,10 +615,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 { @@ -580,10 +635,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 { @@ -599,6 +652,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) { @@ -612,11 +668,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) { @@ -1112,6 +1163,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(); @@ -1139,6 +1191,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); + } } } @@ -1239,9 +1300,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; @@ -1252,7 +1315,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 f7bbdf8..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,34 +157,39 @@ 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, final boolean trusted) { + public void requestStopScanLocked() { if (DEBUG) { - Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted); + Slog.d(TAG, "requestStopScanLocked"); } - 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() { + if (mDisplayController != null) { + mDisplayController.requestStopScan(); } } + }); + } + + public void requestConnectLocked(final String address) { + if (DEBUG) { + Slog.d(TAG, "requestConnectLocked: address=" + address); } getHandler().post(new Runnable() { @@ -197,15 +202,6 @@ 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 requestPauseLocked() { if (DEBUG) { Slog.d(TAG, "requestPauseLocked"); @@ -400,8 +396,6 @@ final class WifiDisplayAdapter extends DisplayAdapter { mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, refreshRate, deviceFlags, address, surface); sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); - - scheduleUpdateNotificationLocked(); } private void removeDisplayDeviceLocked() { @@ -409,8 +403,6 @@ final class WifiDisplayAdapter extends DisplayAdapter { mDisplayDevice.destroyLocked(); sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); mDisplayDevice = null; - - scheduleUpdateNotificationLocked(); } } @@ -457,21 +449,24 @@ final class WifiDisplayAdapter extends DisplayAdapter { // Runs on the handler. private void handleUpdateNotification() { - final boolean isConnected; + final int state; + final WifiDisplay display; synchronized (getSyncRoot()) { if (!mPendingNotificationUpdate) { return; } mPendingNotificationUpdate = false; - isConnected = (mDisplayDevice != null); + state = mActiveDisplayState; + display = mActiveDisplay; } // Cancel the old notification if there is one. mNotificationManager.cancelAsUser(null, - R.string.wifi_display_notification_title, UserHandle.ALL); + R.string.wifi_display_notification_disconnect, UserHandle.ALL); - if (isConnected) { + if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING + || state == WifiDisplayStatus.DISPLAY_STATE_CONNECTED) { Context context = getContext(); // Initialize pending intents for the notification outside of the lock because @@ -493,20 +488,38 @@ final class WifiDisplayAdapter extends DisplayAdapter { // Post the notification. Resources r = context.getResources(); - Notification notification = new Notification.Builder(context) - .setContentTitle(r.getString( - R.string.wifi_display_notification_title)) - .setContentText(r.getString( - R.string.wifi_display_notification_message)) - .setContentIntent(mSettingsPendingIntent) - .setSmallIcon(R.drawable.ic_notify_wifidisplay) - .setOngoing(true) - .addAction(android.R.drawable.ic_menu_close_clear_cancel, - r.getString(R.string.wifi_display_notification_disconnect), - mDisconnectPendingIntent) - .build(); + Notification notification; + if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING) { + notification = new Notification.Builder(context) + .setContentTitle(r.getString( + R.string.wifi_display_notification_connecting_title)) + .setContentText(r.getString( + R.string.wifi_display_notification_connecting_message, + display.getFriendlyDisplayName())) + .setContentIntent(mSettingsPendingIntent) + .setSmallIcon(R.drawable.ic_notification_cast_connecting) + .setOngoing(true) + .addAction(android.R.drawable.ic_menu_close_clear_cancel, + r.getString(R.string.wifi_display_notification_disconnect), + mDisconnectPendingIntent) + .build(); + } else { + notification = new Notification.Builder(context) + .setContentTitle(r.getString( + R.string.wifi_display_notification_connected_title)) + .setContentText(r.getString( + R.string.wifi_display_notification_connected_message, + display.getFriendlyDisplayName())) + .setContentIntent(mSettingsPendingIntent) + .setSmallIcon(R.drawable.ic_notification_cast_on) + .setOngoing(true) + .addAction(android.R.drawable.ic_menu_close_clear_cancel, + r.getString(R.string.wifi_display_notification_disconnect), + mDisconnectPendingIntent) + .build(); + } mNotificationManager.notifyAsUser(null, - R.string.wifi_display_notification_title, + R.string.wifi_display_notification_disconnect, notification, UserHandle.ALL); } } @@ -545,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(); @@ -568,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); @@ -578,6 +601,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; mActiveDisplay = display; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -590,6 +614,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; mActiveDisplay = null; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -607,6 +632,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; mActiveDisplay = display; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -629,6 +655,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplay = display; renameDisplayDeviceLocked(display.getFriendlyDisplayName()); scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -644,6 +671,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; mActiveDisplay = null; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java index 9a4cfb7..dbb59b2 100644 --- a/services/java/com/android/server/display/WifiDisplayController.java +++ b/services/java/com/android/server/display/WifiDisplayController.java @@ -27,7 +27,6 @@ import android.database.ContentObserver; import android.hardware.display.WifiDisplay; import android.hardware.display.WifiDisplaySessionInfo; import android.hardware.display.WifiDisplayStatus; -import android.media.AudioManager; import android.media.RemoteDisplay; import android.net.NetworkInfo; import android.net.Uri; @@ -75,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 RTSP_TIMEOUT_SECONDS = 15; + 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; @@ -103,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; @@ -209,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)); @@ -232,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) { @@ -282,6 +298,7 @@ final class WifiDisplayController implements DumpUtils.Dump { mWfdEnabling = false; mWfdEnabled = true; reportFeatureState(); + updateScanState(); } } @@ -318,6 +335,7 @@ final class WifiDisplayController implements DumpUtils.Dump { mWfdEnabling = false; mWfdEnabled = false; reportFeatureState(); + updateScanState(); disconnect(); } } @@ -340,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(); + } + } } } @@ -357,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 @@ -367,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 + "."); } } }); @@ -415,7 +449,9 @@ final class WifiDisplayController implements DumpUtils.Dump { } } - handleScanFinished(); + if (mDiscoverPeersInProgress) { + handleScanResults(); + } } }); } @@ -429,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++) { @@ -441,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(); } }); } @@ -484,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(); @@ -508,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) { @@ -661,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) { @@ -817,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. @@ -828,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() { @@ -1033,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(); |
