Skip to content

Commit 74da109

Browse files
author
Jeff Brown
committed
Support Wifi display devices that rename themselves.
Some Wifi display devices like to rename themselves after a connection completes (or at other times). Make sure to update the name of the display when we detect that it changed in our scan results. This problem is somewhat complicated by the fact that we remember the display name persistently, so we need to update our list of remembered displays too. Improve the state machine to avoid redundant attempts to disconnect or cancel connection. Bug: 7478895 Change-Id: I35a9e2c6a8deadbe892dacd5e3b4a5a2b12d6cf0
1 parent eb3aa44 commit 74da109

File tree

5 files changed

+149
-39
lines changed

5 files changed

+149
-39
lines changed

core/java/android/hardware/display/WifiDisplay.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ public boolean equals(WifiDisplay other) {
107107
&& Objects.equal(mDeviceAlias, other.mDeviceAlias);
108108
}
109109

110+
/**
111+
* Returns true if the other display is not null and has the same address as this one.
112+
* Can be used to perform identity comparisons on displays ignoring properties
113+
* that might change during a connection such as the name or alias.
114+
*/
115+
public boolean hasSameAddress(WifiDisplay other) {
116+
return other != null && mDeviceAddress.equals(other.mDeviceAddress);
117+
}
118+
110119
@Override
111120
public int hashCode() {
112121
// The address on its own should be sufficiently unique for hashing purposes.

media/java/android/media/MediaRouter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ private static void updateWifiDisplayRoute(RouteInfo route, WifiDisplay display,
862862
private static WifiDisplay findMatchingDisplay(WifiDisplay d, WifiDisplay[] displays) {
863863
for (int i = 0; i < displays.length; i++) {
864864
final WifiDisplay other = displays[i];
865-
if (d.getDeviceAddress().equals(other.getDeviceAddress())) {
865+
if (d.hasSameAddress(other)) {
866866
return other;
867867
}
868868
}

services/java/com/android/server/display/PersistentDataStore.java

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ public void saveIfNeeded() {
8181
}
8282
}
8383

84+
public WifiDisplay getRememberedWifiDisplay(String deviceAddress) {
85+
loadIfNeeded();
86+
int index = findRememberedWifiDisplay(deviceAddress);
87+
if (index >= 0) {
88+
return mRememberedWifiDisplays.get(index);
89+
}
90+
return null;
91+
}
92+
8493
public WifiDisplay[] getRememberedWifiDisplays() {
8594
loadIfNeeded();
8695
return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]);
@@ -137,22 +146,6 @@ public boolean rememberWifiDisplay(WifiDisplay display) {
137146
return true;
138147
}
139148

140-
public boolean renameWifiDisplay(String deviceAddress, String alias) {
141-
int index = findRememberedWifiDisplay(deviceAddress);
142-
if (index >= 0) {
143-
WifiDisplay display = mRememberedWifiDisplays.get(index);
144-
if (Objects.equal(display.getDeviceAlias(), alias)) {
145-
return false; // already has this alias
146-
}
147-
WifiDisplay renamedDisplay = new WifiDisplay(deviceAddress,
148-
display.getDeviceName(), alias);
149-
mRememberedWifiDisplays.set(index, renamedDisplay);
150-
setDirty();
151-
return true;
152-
}
153-
return false;
154-
}
155-
156149
public boolean forgetWifiDisplay(String deviceAddress) {
157150
int index = findRememberedWifiDisplay(deviceAddress);
158151
if (index >= 0) {

services/java/com/android/server/display/WifiDisplayAdapter.java

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import java.io.PrintWriter;
4646
import java.util.Arrays;
4747

48+
import libcore.util.Objects;
49+
4850
/**
4951
* Connects to Wifi displays that implement the Miracast protocol.
5052
* <p>
@@ -224,16 +226,18 @@ public void requestRenameLocked(String address, String alias) {
224226
}
225227
}
226228

227-
if (mPersistentDataStore.renameWifiDisplay(address, alias)) {
228-
mPersistentDataStore.saveIfNeeded();
229-
updateRememberedDisplaysLocked();
230-
scheduleStatusChangedBroadcastLocked();
229+
WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address);
230+
if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) {
231+
display = new WifiDisplay(address, display.getDeviceName(), alias);
232+
if (mPersistentDataStore.rememberWifiDisplay(display)) {
233+
mPersistentDataStore.saveIfNeeded();
234+
updateRememberedDisplaysLocked();
235+
scheduleStatusChangedBroadcastLocked();
236+
}
231237
}
232238

233-
if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)
234-
&& mDisplayDevice != null) {
235-
mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName());
236-
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
239+
if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
240+
renameDisplayDeviceLocked(mActiveDisplay.getFriendlyDisplayName());
237241
}
238242
}
239243

@@ -272,9 +276,42 @@ private void updateRememberedDisplaysLocked() {
272276
mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
273277
}
274278

275-
private void handleConnectLocked(WifiDisplay display,
279+
private void fixRememberedDisplayNamesFromAvailableDisplaysLocked() {
280+
// It may happen that a display name has changed since it was remembered.
281+
// Consult the list of available displays and update the name if needed.
282+
// We don't do anything special for the active display here. The display
283+
// controller will send a separate event when it needs to be updates.
284+
boolean changed = false;
285+
for (int i = 0; i < mRememberedDisplays.length; i++) {
286+
WifiDisplay rememberedDisplay = mRememberedDisplays[i];
287+
WifiDisplay availableDisplay = findAvailableDisplayLocked(
288+
rememberedDisplay.getDeviceAddress());
289+
if (availableDisplay != null && !rememberedDisplay.equals(availableDisplay)) {
290+
if (DEBUG) {
291+
Slog.d(TAG, "fixRememberedDisplayNamesFromAvailableDisplaysLocked: "
292+
+ "updating remembered display to " + availableDisplay);
293+
}
294+
mRememberedDisplays[i] = availableDisplay;
295+
changed |= mPersistentDataStore.rememberWifiDisplay(availableDisplay);
296+
}
297+
}
298+
if (changed) {
299+
mPersistentDataStore.saveIfNeeded();
300+
}
301+
}
302+
303+
private WifiDisplay findAvailableDisplayLocked(String address) {
304+
for (WifiDisplay display : mAvailableDisplays) {
305+
if (display.getDeviceAddress().equals(address)) {
306+
return display;
307+
}
308+
}
309+
return null;
310+
}
311+
312+
private void addDisplayDeviceLocked(WifiDisplay display,
276313
Surface surface, int width, int height, int flags) {
277-
handleDisconnectLocked();
314+
removeDisplayDeviceLocked();
278315

279316
if (mPersistentDataStore.rememberWifiDisplay(display)) {
280317
mPersistentDataStore.saveIfNeeded();
@@ -303,7 +340,7 @@ private void handleConnectLocked(WifiDisplay display,
303340
scheduleUpdateNotificationLocked();
304341
}
305342

306-
private void handleDisconnectLocked() {
343+
private void removeDisplayDeviceLocked() {
307344
if (mDisplayDevice != null) {
308345
mDisplayDevice.clearSurfaceLocked();
309346
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
@@ -313,6 +350,13 @@ private void handleDisconnectLocked() {
313350
}
314351
}
315352

353+
private void renameDisplayDeviceLocked(String name) {
354+
if (mDisplayDevice != null && !mDisplayDevice.getNameLocked().equals(name)) {
355+
mDisplayDevice.setNameLocked(name);
356+
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
357+
}
358+
}
359+
316360
private void scheduleStatusChangedBroadcastLocked() {
317361
mCurrentStatus = null;
318362
if (!mPendingStatusChangeBroadcast) {
@@ -446,6 +490,7 @@ public void onScanFinished(WifiDisplay[] availableDisplays) {
446490
|| !Arrays.equals(mAvailableDisplays, availableDisplays)) {
447491
mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
448492
mAvailableDisplays = availableDisplays;
493+
fixRememberedDisplayNamesFromAvailableDisplaysLocked();
449494
scheduleStatusChangedBroadcastLocked();
450495
}
451496
}
@@ -483,7 +528,7 @@ public void onDisplayConnected(WifiDisplay display, Surface surface,
483528
int width, int height, int flags) {
484529
synchronized (getSyncRoot()) {
485530
display = mPersistentDataStore.applyWifiDisplayAlias(display);
486-
handleConnectLocked(display, surface, width, height, flags);
531+
addDisplayDeviceLocked(display, surface, width, height, flags);
487532

488533
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
489534
|| mActiveDisplay == null
@@ -495,11 +540,25 @@ public void onDisplayConnected(WifiDisplay display, Surface surface,
495540
}
496541
}
497542

543+
@Override
544+
public void onDisplayChanged(WifiDisplay display) {
545+
synchronized (getSyncRoot()) {
546+
display = mPersistentDataStore.applyWifiDisplayAlias(display);
547+
if (mActiveDisplay != null
548+
&& mActiveDisplay.hasSameAddress(display)
549+
&& !mActiveDisplay.equals(display)) {
550+
mActiveDisplay = display;
551+
renameDisplayDeviceLocked(display.getFriendlyDisplayName());
552+
scheduleStatusChangedBroadcastLocked();
553+
}
554+
}
555+
}
556+
498557
@Override
499558
public void onDisplayDisconnected() {
500559
// Stop listening.
501560
synchronized (getSyncRoot()) {
502-
handleDisconnectLocked();
561+
removeDisplayDeviceLocked();
503562

504563
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
505564
|| mActiveDisplay != null) {

services/java/com/android/server/display/WifiDisplayController.java

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ final class WifiDisplayController implements DumpUtils.Dump {
120120
// or are not trying to connect.
121121
private WifiP2pDevice mConnectingDevice;
122122

123+
// The device from which we are currently disconnecting.
124+
private WifiP2pDevice mDisconnectingDevice;
125+
126+
// The device to which we were previously trying to connect and are now canceling.
127+
private WifiP2pDevice mCancelingDevice;
128+
123129
// The device to which we are currently connected, which means we have an active P2P group.
124130
private WifiP2pDevice mConnectedDevice;
125131

@@ -186,6 +192,7 @@ private void updateSettings() {
186192
updateWfdEnableState();
187193
}
188194

195+
@Override
189196
public void dump(PrintWriter pw) {
190197
pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
191198
pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
@@ -196,6 +203,8 @@ public void dump(PrintWriter pw) {
196203
pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft);
197204
pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice));
198205
pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice));
206+
pw.println("mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice));
207+
pw.println("mCancelingDisplay=" + describeWifiP2pDevice(mCancelingDevice));
199208
pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice));
200209
pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft);
201210
pw.println("mRemoteDisplay=" + mRemoteDisplay);
@@ -384,7 +393,9 @@ private void handleScanFinished() {
384393
final int count = mAvailableWifiDisplayPeers.size();
385394
final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
386395
for (int i = 0; i < count; i++) {
387-
displays[i] = createWifiDisplay(mAvailableWifiDisplayPeers.get(i));
396+
WifiP2pDevice device = mAvailableWifiDisplayPeers.get(i);
397+
displays[i] = createWifiDisplay(device);
398+
updateDesiredDevice(device);
388399
}
389400

390401
mHandler.post(new Runnable() {
@@ -395,6 +406,23 @@ public void run() {
395406
});
396407
}
397408

409+
private void updateDesiredDevice(WifiP2pDevice device) {
410+
// Handle the case where the device to which we are connecting or connected
411+
// may have been renamed or reported different properties in the latest scan.
412+
final String address = device.deviceAddress;
413+
if (mDesiredDevice != null && mDesiredDevice.deviceAddress.equals(address)) {
414+
if (DEBUG) {
415+
Slog.d(TAG, "updateDesiredDevice: new information "
416+
+ describeWifiP2pDevice(device));
417+
}
418+
mDesiredDevice.update(device);
419+
if (mAdvertisedDisplay != null
420+
&& mAdvertisedDisplay.getDeviceAddress().equals(address)) {
421+
readvertiseDisplay(createWifiDisplay(mDesiredDevice));
422+
}
423+
}
424+
}
425+
398426
private void connect(final WifiP2pDevice device) {
399427
if (mDesiredDevice != null
400428
&& !mDesiredDevice.deviceAddress.equals(device.deviceAddress)) {
@@ -459,12 +487,17 @@ private void updateConnection() {
459487
}
460488

461489
// Step 2. Before we try to connect to a new device, disconnect from the old one.
490+
if (mDisconnectingDevice != null) {
491+
return; // wait for asynchronous callback
492+
}
462493
if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) {
463494
Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName);
495+
mDisconnectingDevice = mConnectedDevice;
496+
mConnectedDevice = null;
464497

465498
unadvertiseDisplay();
466499

467-
final WifiP2pDevice oldDevice = mConnectedDevice;
500+
final WifiP2pDevice oldDevice = mDisconnectingDevice;
468501
mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() {
469502
@Override
470503
public void onSuccess() {
@@ -480,8 +513,8 @@ public void onFailure(int reason) {
480513
}
481514

482515
private void next() {
483-
if (mConnectedDevice == oldDevice) {
484-
mConnectedDevice = null;
516+
if (mDisconnectingDevice == oldDevice) {
517+
mDisconnectingDevice = null;
485518
updateConnection();
486519
}
487520
}
@@ -491,13 +524,18 @@ private void next() {
491524

492525
// Step 3. Before we try to connect to a new device, stop trying to connect
493526
// to the old one.
527+
if (mCancelingDevice != null) {
528+
return; // wait for asynchronous callback
529+
}
494530
if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) {
495531
Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName);
532+
mCancelingDevice = mConnectingDevice;
533+
mConnectingDevice = null;
496534

497535
unadvertiseDisplay();
498536
mHandler.removeCallbacks(mConnectionTimeout);
499537

500-
final WifiP2pDevice oldDevice = mConnectingDevice;
538+
final WifiP2pDevice oldDevice = mCancelingDevice;
501539
mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() {
502540
@Override
503541
public void onSuccess() {
@@ -513,8 +551,8 @@ public void onFailure(int reason) {
513551
}
514552

515553
private void next() {
516-
if (mConnectingDevice == oldDevice) {
517-
mConnectingDevice = null;
554+
if (mCancelingDevice == oldDevice) {
555+
mCancelingDevice = null;
518556
updateConnection();
519557
}
520558
}
@@ -763,13 +801,17 @@ private void advertiseDisplay(final WifiDisplay display,
763801
public void run() {
764802
if (oldSurface != null && surface != oldSurface) {
765803
mListener.onDisplayDisconnected();
766-
} else if (oldDisplay != null && !Objects.equal(display, oldDisplay)) {
804+
} else if (oldDisplay != null && !oldDisplay.hasSameAddress(display)) {
767805
mListener.onDisplayConnectionFailed();
768806
}
769807

770808
if (display != null) {
771-
if (!Objects.equal(display, oldDisplay)) {
809+
if (!display.hasSameAddress(oldDisplay)) {
772810
mListener.onDisplayConnecting(display);
811+
} else if (!display.equals(oldDisplay)) {
812+
// The address is the same but some other property such as the
813+
// name must have changed.
814+
mListener.onDisplayChanged(display);
773815
}
774816
if (surface != null && surface != oldSurface) {
775817
mListener.onDisplayConnected(display, surface, width, height, flags);
@@ -784,6 +826,12 @@ private void unadvertiseDisplay() {
784826
advertiseDisplay(null, null, 0, 0, 0);
785827
}
786828

829+
private void readvertiseDisplay(WifiDisplay display) {
830+
advertiseDisplay(display, mAdvertisedDisplaySurface,
831+
mAdvertisedDisplayWidth, mAdvertisedDisplayHeight,
832+
mAdvertisedDisplayFlags);
833+
}
834+
787835
private static Inet4Address getInterfaceAddress(WifiP2pGroup info) {
788836
NetworkInterface iface;
789837
try {
@@ -885,6 +933,7 @@ public interface Listener {
885933

886934
void onDisplayConnecting(WifiDisplay display);
887935
void onDisplayConnectionFailed();
936+
void onDisplayChanged(WifiDisplay display);
888937
void onDisplayConnected(WifiDisplay display,
889938
Surface surface, int width, int height, int flags);
890939
void onDisplayDisconnected();

0 commit comments

Comments
 (0)