am c10914ca: Merge "Support Wifi display devices that rename themselves." into jb-mr1.1-dev

* commit 'c10914ca5c83ad6ac2c9acd7b52bfeb05d6e72e5':
  Support Wifi display devices that rename themselves.
This commit is contained in:
Craig Mautner
2012-11-13 10:02:21 -08:00
committed by Android Git Automerger
5 changed files with 149 additions and 39 deletions

View File

@ -107,6 +107,15 @@ public final class WifiDisplay implements Parcelable {
&& Objects.equal(mDeviceAlias, other.mDeviceAlias); && Objects.equal(mDeviceAlias, other.mDeviceAlias);
} }
/**
* Returns true if the other display is not null and has the same address as this one.
* Can be used to perform identity comparisons on displays ignoring properties
* that might change during a connection such as the name or alias.
*/
public boolean hasSameAddress(WifiDisplay other) {
return other != null && mDeviceAddress.equals(other.mDeviceAddress);
}
@Override @Override
public int hashCode() { public int hashCode() {
// The address on its own should be sufficiently unique for hashing purposes. // The address on its own should be sufficiently unique for hashing purposes.

View File

@ -862,7 +862,7 @@ public class MediaRouter {
private static WifiDisplay findMatchingDisplay(WifiDisplay d, WifiDisplay[] displays) { private static WifiDisplay findMatchingDisplay(WifiDisplay d, WifiDisplay[] displays) {
for (int i = 0; i < displays.length; i++) { for (int i = 0; i < displays.length; i++) {
final WifiDisplay other = displays[i]; final WifiDisplay other = displays[i];
if (d.getDeviceAddress().equals(other.getDeviceAddress())) { if (d.hasSameAddress(other)) {
return other; return other;
} }
} }

View File

@ -81,6 +81,15 @@ final class PersistentDataStore {
} }
} }
public WifiDisplay getRememberedWifiDisplay(String deviceAddress) {
loadIfNeeded();
int index = findRememberedWifiDisplay(deviceAddress);
if (index >= 0) {
return mRememberedWifiDisplays.get(index);
}
return null;
}
public WifiDisplay[] getRememberedWifiDisplays() { public WifiDisplay[] getRememberedWifiDisplays() {
loadIfNeeded(); loadIfNeeded();
return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]); return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]);
@ -137,22 +146,6 @@ final class PersistentDataStore {
return true; return true;
} }
public boolean renameWifiDisplay(String deviceAddress, String alias) {
int index = findRememberedWifiDisplay(deviceAddress);
if (index >= 0) {
WifiDisplay display = mRememberedWifiDisplays.get(index);
if (Objects.equal(display.getDeviceAlias(), alias)) {
return false; // already has this alias
}
WifiDisplay renamedDisplay = new WifiDisplay(deviceAddress,
display.getDeviceName(), alias);
mRememberedWifiDisplays.set(index, renamedDisplay);
setDirty();
return true;
}
return false;
}
public boolean forgetWifiDisplay(String deviceAddress) { public boolean forgetWifiDisplay(String deviceAddress) {
int index = findRememberedWifiDisplay(deviceAddress); int index = findRememberedWifiDisplay(deviceAddress);
if (index >= 0) { if (index >= 0) {

View File

@ -45,6 +45,8 @@ import android.view.Surface;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Arrays; import java.util.Arrays;
import libcore.util.Objects;
/** /**
* Connects to Wifi displays that implement the Miracast protocol. * Connects to Wifi displays that implement the Miracast protocol.
* <p> * <p>
@ -224,16 +226,18 @@ final class WifiDisplayAdapter extends DisplayAdapter {
} }
} }
if (mPersistentDataStore.renameWifiDisplay(address, alias)) { WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address);
mPersistentDataStore.saveIfNeeded(); if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) {
updateRememberedDisplaysLocked(); display = new WifiDisplay(address, display.getDeviceName(), alias);
scheduleStatusChangedBroadcastLocked(); if (mPersistentDataStore.rememberWifiDisplay(display)) {
mPersistentDataStore.saveIfNeeded();
updateRememberedDisplaysLocked();
scheduleStatusChangedBroadcastLocked();
}
} }
if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address) if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
&& mDisplayDevice != null) { renameDisplayDeviceLocked(mActiveDisplay.getFriendlyDisplayName());
mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName());
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
} }
} }
@ -272,9 +276,42 @@ final class WifiDisplayAdapter extends DisplayAdapter {
mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays); mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
} }
private void handleConnectLocked(WifiDisplay display, private void fixRememberedDisplayNamesFromAvailableDisplaysLocked() {
// It may happen that a display name has changed since it was remembered.
// Consult the list of available displays and update the name if needed.
// We don't do anything special for the active display here. The display
// controller will send a separate event when it needs to be updates.
boolean changed = false;
for (int i = 0; i < mRememberedDisplays.length; i++) {
WifiDisplay rememberedDisplay = mRememberedDisplays[i];
WifiDisplay availableDisplay = findAvailableDisplayLocked(
rememberedDisplay.getDeviceAddress());
if (availableDisplay != null && !rememberedDisplay.equals(availableDisplay)) {
if (DEBUG) {
Slog.d(TAG, "fixRememberedDisplayNamesFromAvailableDisplaysLocked: "
+ "updating remembered display to " + availableDisplay);
}
mRememberedDisplays[i] = availableDisplay;
changed |= mPersistentDataStore.rememberWifiDisplay(availableDisplay);
}
}
if (changed) {
mPersistentDataStore.saveIfNeeded();
}
}
private WifiDisplay findAvailableDisplayLocked(String address) {
for (WifiDisplay display : mAvailableDisplays) {
if (display.getDeviceAddress().equals(address)) {
return display;
}
}
return null;
}
private void addDisplayDeviceLocked(WifiDisplay display,
Surface surface, int width, int height, int flags) { Surface surface, int width, int height, int flags) {
handleDisconnectLocked(); removeDisplayDeviceLocked();
if (mPersistentDataStore.rememberWifiDisplay(display)) { if (mPersistentDataStore.rememberWifiDisplay(display)) {
mPersistentDataStore.saveIfNeeded(); mPersistentDataStore.saveIfNeeded();
@ -303,7 +340,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
scheduleUpdateNotificationLocked(); scheduleUpdateNotificationLocked();
} }
private void handleDisconnectLocked() { private void removeDisplayDeviceLocked() {
if (mDisplayDevice != null) { if (mDisplayDevice != null) {
mDisplayDevice.clearSurfaceLocked(); mDisplayDevice.clearSurfaceLocked();
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
@ -313,6 +350,13 @@ final class WifiDisplayAdapter extends DisplayAdapter {
} }
} }
private void renameDisplayDeviceLocked(String name) {
if (mDisplayDevice != null && !mDisplayDevice.getNameLocked().equals(name)) {
mDisplayDevice.setNameLocked(name);
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
}
}
private void scheduleStatusChangedBroadcastLocked() { private void scheduleStatusChangedBroadcastLocked() {
mCurrentStatus = null; mCurrentStatus = null;
if (!mPendingStatusChangeBroadcast) { if (!mPendingStatusChangeBroadcast) {
@ -446,6 +490,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|| !Arrays.equals(mAvailableDisplays, availableDisplays)) { || !Arrays.equals(mAvailableDisplays, availableDisplays)) {
mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
mAvailableDisplays = availableDisplays; mAvailableDisplays = availableDisplays;
fixRememberedDisplayNamesFromAvailableDisplaysLocked();
scheduleStatusChangedBroadcastLocked(); scheduleStatusChangedBroadcastLocked();
} }
} }
@ -483,7 +528,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
int width, int height, int flags) { int width, int height, int flags) {
synchronized (getSyncRoot()) { synchronized (getSyncRoot()) {
display = mPersistentDataStore.applyWifiDisplayAlias(display); display = mPersistentDataStore.applyWifiDisplayAlias(display);
handleConnectLocked(display, surface, width, height, flags); addDisplayDeviceLocked(display, surface, width, height, flags);
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
|| mActiveDisplay == null || mActiveDisplay == null
@ -495,11 +540,25 @@ final class WifiDisplayAdapter extends DisplayAdapter {
} }
} }
@Override
public void onDisplayChanged(WifiDisplay display) {
synchronized (getSyncRoot()) {
display = mPersistentDataStore.applyWifiDisplayAlias(display);
if (mActiveDisplay != null
&& mActiveDisplay.hasSameAddress(display)
&& !mActiveDisplay.equals(display)) {
mActiveDisplay = display;
renameDisplayDeviceLocked(display.getFriendlyDisplayName());
scheduleStatusChangedBroadcastLocked();
}
}
}
@Override @Override
public void onDisplayDisconnected() { public void onDisplayDisconnected() {
// Stop listening. // Stop listening.
synchronized (getSyncRoot()) { synchronized (getSyncRoot()) {
handleDisconnectLocked(); removeDisplayDeviceLocked();
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
|| mActiveDisplay != null) { || mActiveDisplay != null) {

View File

@ -120,6 +120,12 @@ final class WifiDisplayController implements DumpUtils.Dump {
// or are not trying to connect. // or are not trying to connect.
private WifiP2pDevice mConnectingDevice; private WifiP2pDevice mConnectingDevice;
// The device from which we are currently disconnecting.
private WifiP2pDevice mDisconnectingDevice;
// The device to which we were previously trying to connect and are now canceling.
private WifiP2pDevice mCancelingDevice;
// The device to which we are currently connected, which means we have an active P2P group. // The device to which we are currently connected, which means we have an active P2P group.
private WifiP2pDevice mConnectedDevice; private WifiP2pDevice mConnectedDevice;
@ -186,6 +192,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
updateWfdEnableState(); updateWfdEnableState();
} }
@Override
public void dump(PrintWriter pw) { public void dump(PrintWriter pw) {
pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting); pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled); pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
@ -196,6 +203,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft); pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft);
pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice)); pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice));
pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice)); pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice));
pw.println("mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice));
pw.println("mCancelingDisplay=" + describeWifiP2pDevice(mCancelingDevice));
pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice)); pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice));
pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft); pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft);
pw.println("mRemoteDisplay=" + mRemoteDisplay); pw.println("mRemoteDisplay=" + mRemoteDisplay);
@ -384,7 +393,9 @@ final class WifiDisplayController implements DumpUtils.Dump {
final int count = mAvailableWifiDisplayPeers.size(); final int count = mAvailableWifiDisplayPeers.size();
final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count); final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
displays[i] = createWifiDisplay(mAvailableWifiDisplayPeers.get(i)); WifiP2pDevice device = mAvailableWifiDisplayPeers.get(i);
displays[i] = createWifiDisplay(device);
updateDesiredDevice(device);
} }
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@ -395,6 +406,23 @@ final class WifiDisplayController implements DumpUtils.Dump {
}); });
} }
private void updateDesiredDevice(WifiP2pDevice device) {
// Handle the case where the device to which we are connecting or connected
// may have been renamed or reported different properties in the latest scan.
final String address = device.deviceAddress;
if (mDesiredDevice != null && mDesiredDevice.deviceAddress.equals(address)) {
if (DEBUG) {
Slog.d(TAG, "updateDesiredDevice: new information "
+ describeWifiP2pDevice(device));
}
mDesiredDevice.update(device);
if (mAdvertisedDisplay != null
&& mAdvertisedDisplay.getDeviceAddress().equals(address)) {
readvertiseDisplay(createWifiDisplay(mDesiredDevice));
}
}
}
private void connect(final WifiP2pDevice device) { private void connect(final WifiP2pDevice device) {
if (mDesiredDevice != null if (mDesiredDevice != null
&& !mDesiredDevice.deviceAddress.equals(device.deviceAddress)) { && !mDesiredDevice.deviceAddress.equals(device.deviceAddress)) {
@ -459,12 +487,17 @@ final class WifiDisplayController implements DumpUtils.Dump {
} }
// Step 2. Before we try to connect to a new device, disconnect from the old one. // Step 2. Before we try to connect to a new device, disconnect from the old one.
if (mDisconnectingDevice != null) {
return; // wait for asynchronous callback
}
if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) { if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) {
Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName); Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName);
mDisconnectingDevice = mConnectedDevice;
mConnectedDevice = null;
unadvertiseDisplay(); unadvertiseDisplay();
final WifiP2pDevice oldDevice = mConnectedDevice; final WifiP2pDevice oldDevice = mDisconnectingDevice;
mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() { mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() {
@Override @Override
public void onSuccess() { public void onSuccess() {
@ -480,8 +513,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
} }
private void next() { private void next() {
if (mConnectedDevice == oldDevice) { if (mDisconnectingDevice == oldDevice) {
mConnectedDevice = null; mDisconnectingDevice = null;
updateConnection(); updateConnection();
} }
} }
@ -491,13 +524,18 @@ final class WifiDisplayController implements DumpUtils.Dump {
// Step 3. Before we try to connect to a new device, stop trying to connect // Step 3. Before we try to connect to a new device, stop trying to connect
// to the old one. // to the old one.
if (mCancelingDevice != null) {
return; // wait for asynchronous callback
}
if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) { if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) {
Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName); Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName);
mCancelingDevice = mConnectingDevice;
mConnectingDevice = null;
unadvertiseDisplay(); unadvertiseDisplay();
mHandler.removeCallbacks(mConnectionTimeout); mHandler.removeCallbacks(mConnectionTimeout);
final WifiP2pDevice oldDevice = mConnectingDevice; final WifiP2pDevice oldDevice = mCancelingDevice;
mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() { mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() {
@Override @Override
public void onSuccess() { public void onSuccess() {
@ -513,8 +551,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
} }
private void next() { private void next() {
if (mConnectingDevice == oldDevice) { if (mCancelingDevice == oldDevice) {
mConnectingDevice = null; mCancelingDevice = null;
updateConnection(); updateConnection();
} }
} }
@ -763,13 +801,17 @@ final class WifiDisplayController implements DumpUtils.Dump {
public void run() { public void run() {
if (oldSurface != null && surface != oldSurface) { if (oldSurface != null && surface != oldSurface) {
mListener.onDisplayDisconnected(); mListener.onDisplayDisconnected();
} else if (oldDisplay != null && !Objects.equal(display, oldDisplay)) { } else if (oldDisplay != null && !oldDisplay.hasSameAddress(display)) {
mListener.onDisplayConnectionFailed(); mListener.onDisplayConnectionFailed();
} }
if (display != null) { if (display != null) {
if (!Objects.equal(display, oldDisplay)) { if (!display.hasSameAddress(oldDisplay)) {
mListener.onDisplayConnecting(display); mListener.onDisplayConnecting(display);
} else if (!display.equals(oldDisplay)) {
// The address is the same but some other property such as the
// name must have changed.
mListener.onDisplayChanged(display);
} }
if (surface != null && surface != oldSurface) { if (surface != null && surface != oldSurface) {
mListener.onDisplayConnected(display, surface, width, height, flags); mListener.onDisplayConnected(display, surface, width, height, flags);
@ -784,6 +826,12 @@ final class WifiDisplayController implements DumpUtils.Dump {
advertiseDisplay(null, null, 0, 0, 0); advertiseDisplay(null, null, 0, 0, 0);
} }
private void readvertiseDisplay(WifiDisplay display) {
advertiseDisplay(display, mAdvertisedDisplaySurface,
mAdvertisedDisplayWidth, mAdvertisedDisplayHeight,
mAdvertisedDisplayFlags);
}
private static Inet4Address getInterfaceAddress(WifiP2pGroup info) { private static Inet4Address getInterfaceAddress(WifiP2pGroup info) {
NetworkInterface iface; NetworkInterface iface;
try { try {
@ -885,6 +933,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
void onDisplayConnecting(WifiDisplay display); void onDisplayConnecting(WifiDisplay display);
void onDisplayConnectionFailed(); void onDisplayConnectionFailed();
void onDisplayChanged(WifiDisplay display);
void onDisplayConnected(WifiDisplay display, void onDisplayConnected(WifiDisplay display,
Surface surface, int width, int height, int flags); Surface surface, int width, int height, int flags);
void onDisplayDisconnected(); void onDisplayDisconnected();