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:
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user