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);
}
/**
* 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
public int hashCode() {
// 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) {
for (int i = 0; i < displays.length; i++) {
final WifiDisplay other = displays[i];
if (d.getDeviceAddress().equals(other.getDeviceAddress())) {
if (d.hasSameAddress(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() {
loadIfNeeded();
return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]);
@ -137,22 +146,6 @@ final class PersistentDataStore {
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) {
int index = findRememberedWifiDisplay(deviceAddress);
if (index >= 0) {

View File

@ -45,6 +45,8 @@ import android.view.Surface;
import java.io.PrintWriter;
import java.util.Arrays;
import libcore.util.Objects;
/**
* Connects to Wifi displays that implement the Miracast protocol.
* <p>
@ -224,16 +226,18 @@ final class WifiDisplayAdapter extends DisplayAdapter {
}
}
if (mPersistentDataStore.renameWifiDisplay(address, alias)) {
mPersistentDataStore.saveIfNeeded();
updateRememberedDisplaysLocked();
scheduleStatusChangedBroadcastLocked();
WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address);
if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) {
display = new WifiDisplay(address, display.getDeviceName(), alias);
if (mPersistentDataStore.rememberWifiDisplay(display)) {
mPersistentDataStore.saveIfNeeded();
updateRememberedDisplaysLocked();
scheduleStatusChangedBroadcastLocked();
}
}
if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)
&& mDisplayDevice != null) {
mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName());
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
renameDisplayDeviceLocked(mActiveDisplay.getFriendlyDisplayName());
}
}
@ -272,9 +276,42 @@ final class WifiDisplayAdapter extends DisplayAdapter {
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) {
handleDisconnectLocked();
removeDisplayDeviceLocked();
if (mPersistentDataStore.rememberWifiDisplay(display)) {
mPersistentDataStore.saveIfNeeded();
@ -303,7 +340,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
scheduleUpdateNotificationLocked();
}
private void handleDisconnectLocked() {
private void removeDisplayDeviceLocked() {
if (mDisplayDevice != null) {
mDisplayDevice.clearSurfaceLocked();
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() {
mCurrentStatus = null;
if (!mPendingStatusChangeBroadcast) {
@ -446,6 +490,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|| !Arrays.equals(mAvailableDisplays, availableDisplays)) {
mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
mAvailableDisplays = availableDisplays;
fixRememberedDisplayNamesFromAvailableDisplaysLocked();
scheduleStatusChangedBroadcastLocked();
}
}
@ -483,7 +528,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
int width, int height, int flags) {
synchronized (getSyncRoot()) {
display = mPersistentDataStore.applyWifiDisplayAlias(display);
handleConnectLocked(display, surface, width, height, flags);
addDisplayDeviceLocked(display, surface, width, height, flags);
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
|| 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
public void onDisplayDisconnected() {
// Stop listening.
synchronized (getSyncRoot()) {
handleDisconnectLocked();
removeDisplayDeviceLocked();
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
|| mActiveDisplay != null) {

View File

@ -120,6 +120,12 @@ final class WifiDisplayController implements DumpUtils.Dump {
// or are not trying to connect.
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.
private WifiP2pDevice mConnectedDevice;
@ -186,6 +192,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
updateWfdEnableState();
}
@Override
public void dump(PrintWriter pw) {
pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
@ -196,6 +203,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft);
pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice));
pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice));
pw.println("mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice));
pw.println("mCancelingDisplay=" + describeWifiP2pDevice(mCancelingDevice));
pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice));
pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft);
pw.println("mRemoteDisplay=" + mRemoteDisplay);
@ -384,7 +393,9 @@ final class WifiDisplayController implements DumpUtils.Dump {
final int count = mAvailableWifiDisplayPeers.size();
final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
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() {
@ -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) {
if (mDesiredDevice != null
&& !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.
if (mDisconnectingDevice != null) {
return; // wait for asynchronous callback
}
if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) {
Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName);
mDisconnectingDevice = mConnectedDevice;
mConnectedDevice = null;
unadvertiseDisplay();
final WifiP2pDevice oldDevice = mConnectedDevice;
final WifiP2pDevice oldDevice = mDisconnectingDevice;
mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() {
@Override
public void onSuccess() {
@ -480,8 +513,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
}
private void next() {
if (mConnectedDevice == oldDevice) {
mConnectedDevice = null;
if (mDisconnectingDevice == oldDevice) {
mDisconnectingDevice = null;
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
// to the old one.
if (mCancelingDevice != null) {
return; // wait for asynchronous callback
}
if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) {
Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName);
mCancelingDevice = mConnectingDevice;
mConnectingDevice = null;
unadvertiseDisplay();
mHandler.removeCallbacks(mConnectionTimeout);
final WifiP2pDevice oldDevice = mConnectingDevice;
final WifiP2pDevice oldDevice = mCancelingDevice;
mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() {
@Override
public void onSuccess() {
@ -513,8 +551,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
}
private void next() {
if (mConnectingDevice == oldDevice) {
mConnectingDevice = null;
if (mCancelingDevice == oldDevice) {
mCancelingDevice = null;
updateConnection();
}
}
@ -763,13 +801,17 @@ final class WifiDisplayController implements DumpUtils.Dump {
public void run() {
if (oldSurface != null && surface != oldSurface) {
mListener.onDisplayDisconnected();
} else if (oldDisplay != null && !Objects.equal(display, oldDisplay)) {
} else if (oldDisplay != null && !oldDisplay.hasSameAddress(display)) {
mListener.onDisplayConnectionFailed();
}
if (display != null) {
if (!Objects.equal(display, oldDisplay)) {
if (!display.hasSameAddress(oldDisplay)) {
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) {
mListener.onDisplayConnected(display, surface, width, height, flags);
@ -784,6 +826,12 @@ final class WifiDisplayController implements DumpUtils.Dump {
advertiseDisplay(null, null, 0, 0, 0);
}
private void readvertiseDisplay(WifiDisplay display) {
advertiseDisplay(display, mAdvertisedDisplaySurface,
mAdvertisedDisplayWidth, mAdvertisedDisplayHeight,
mAdvertisedDisplayFlags);
}
private static Inet4Address getInterfaceAddress(WifiP2pGroup info) {
NetworkInterface iface;
try {
@ -885,6 +933,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
void onDisplayConnecting(WifiDisplay display);
void onDisplayConnectionFailed();
void onDisplayChanged(WifiDisplay display);
void onDisplayConnected(WifiDisplay display,
Surface surface, int width, int height, int flags);
void onDisplayDisconnected();