Merge "MediaRouter: grey out wifi displays that's in use"

This commit is contained in:
Chong Zhang
2013-06-15 00:36:15 +00:00
committed by Android (Google) Code Review
8 changed files with 172 additions and 122 deletions

View File

@@ -33,7 +33,9 @@ public final class WifiDisplay implements Parcelable {
private final String mDeviceAddress;
private final String mDeviceName;
private final String mDeviceAlias;
private final boolean mIsAvailable;
private final boolean mCanConnect;
private final boolean mIsRemembered;
public static final WifiDisplay[] EMPTY_ARRAY = new WifiDisplay[0];
@@ -42,9 +44,11 @@ public final class WifiDisplay implements Parcelable {
String deviceAddress = in.readString();
String deviceName = in.readString();
String deviceAlias = in.readString();
boolean isAvailable = (in.readInt() != 0);
boolean canConnect = (in.readInt() != 0);
return new WifiDisplay(deviceAddress, deviceName,
deviceAlias, canConnect);
boolean isRemembered = (in.readInt() != 0);
return new WifiDisplay(deviceAddress, deviceName, deviceAlias,
isAvailable, canConnect, isRemembered);
}
public WifiDisplay[] newArray(int size) {
@@ -52,12 +56,8 @@ public final class WifiDisplay implements Parcelable {
}
};
public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias) {
this(deviceAddress, deviceName, deviceAlias, false);
}
public WifiDisplay(String deviceAddress, String deviceName,
String deviceAlias, boolean canConnect) {
public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias,
boolean available, boolean canConnect, boolean remembered) {
if (deviceAddress == null) {
throw new IllegalArgumentException("deviceAddress must not be null");
}
@@ -68,7 +68,9 @@ public final class WifiDisplay implements Parcelable {
mDeviceAddress = deviceAddress;
mDeviceName = deviceName;
mDeviceAlias = deviceAlias;
mIsAvailable = available;
mCanConnect = canConnect;
mIsRemembered = remembered;
}
/**
@@ -97,12 +99,26 @@ public final class WifiDisplay implements Parcelable {
}
/**
* Gets the availability of the Wifi display device.
* Returns true if device is available, false otherwise.
*/
public boolean isAvailable() {
return mIsAvailable;
}
/**
* Returns true if device can be connected to (not in use), false otherwise.
*/
public boolean canConnect() {
return mCanConnect;
}
/**
* Returns true if device has been remembered, false otherwise.
*/
public boolean isRemembered() {
return mIsRemembered;
}
/**
* Gets the name to show in the UI.
* Uses the device alias if available, otherwise uses the device name.
@@ -116,12 +132,15 @@ public final class WifiDisplay implements Parcelable {
return o instanceof WifiDisplay && equals((WifiDisplay)o);
}
/**
* Returns true if the two displays have the same identity (address, name and alias).
* This method does not compare the current status of the displays.
*/
public boolean equals(WifiDisplay other) {
return other != null
&& mDeviceAddress.equals(other.mDeviceAddress)
&& mDeviceName.equals(other.mDeviceName)
&& Objects.equal(mDeviceAlias, other.mDeviceAlias)
&& (mCanConnect == other.mCanConnect);
&& Objects.equal(mDeviceAlias, other.mDeviceAlias);
}
/**
@@ -144,7 +163,9 @@ public final class WifiDisplay implements Parcelable {
dest.writeString(mDeviceAddress);
dest.writeString(mDeviceName);
dest.writeString(mDeviceAlias);
dest.writeInt(mIsAvailable ? 1 : 0);
dest.writeInt(mCanConnect ? 1 : 0);
dest.writeInt(mIsRemembered ? 1 : 0);
}
@Override
@@ -159,7 +180,8 @@ public final class WifiDisplay implements Parcelable {
if (mDeviceAlias != null) {
result += ", alias " + mDeviceAlias;
}
result += ", canConnect " + mCanConnect;
result += ", isAvailable " + mIsAvailable + ", canConnect " + mCanConnect
+ ", isRemembered " + mIsRemembered;
return result;
}
}

View File

@@ -20,6 +20,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
/**
* Describes the current global state of Wifi display connectivity, including the
@@ -35,8 +37,7 @@ public final class WifiDisplayStatus implements Parcelable {
private final int mScanState;
private final int mActiveDisplayState;
private final WifiDisplay mActiveDisplay;
private final WifiDisplay[] mAvailableDisplays;
private final WifiDisplay[] mRememberedDisplays;
private final WifiDisplay[] mDisplays;
/** Feature state: Wifi display is not available on this device. */
public static final int FEATURE_STATE_UNAVAILABLE = 0;
@@ -70,18 +71,13 @@ public final class WifiDisplayStatus implements Parcelable {
activeDisplay = WifiDisplay.CREATOR.createFromParcel(in);
}
WifiDisplay[] availableDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
for (int i = 0; i < availableDisplays.length; i++) {
availableDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
}
WifiDisplay[] rememberedDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
for (int i = 0; i < rememberedDisplays.length; i++) {
rememberedDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(in.readInt());
for (int i = 0; i < displays.length; i++) {
displays[i] = WifiDisplay.CREATOR.createFromParcel(in);
}
return new WifiDisplayStatus(featureState, scanState, activeDisplayState,
activeDisplay, availableDisplays, rememberedDisplays);
activeDisplay, displays);
}
public WifiDisplayStatus[] newArray(int size) {
@@ -91,25 +87,20 @@ public final class WifiDisplayStatus implements Parcelable {
public WifiDisplayStatus() {
this(FEATURE_STATE_UNAVAILABLE, SCAN_STATE_NOT_SCANNING, DISPLAY_STATE_NOT_CONNECTED,
null, WifiDisplay.EMPTY_ARRAY, WifiDisplay.EMPTY_ARRAY);
null, WifiDisplay.EMPTY_ARRAY);
}
public WifiDisplayStatus(int featureState, int scanState,
int activeDisplayState, WifiDisplay activeDisplay,
WifiDisplay[] availableDisplays, WifiDisplay[] rememberedDisplays) {
if (availableDisplays == null) {
throw new IllegalArgumentException("availableDisplays must not be null");
}
if (rememberedDisplays == null) {
throw new IllegalArgumentException("rememberedDisplays must not be null");
int activeDisplayState, WifiDisplay activeDisplay, WifiDisplay[] displays) {
if (displays == null) {
throw new IllegalArgumentException("displays must not be null");
}
mFeatureState = featureState;
mScanState = scanState;
mActiveDisplayState = activeDisplayState;
mActiveDisplay = activeDisplay;
mAvailableDisplays = availableDisplays;
mRememberedDisplays = rememberedDisplays;
mDisplays = displays;
}
/**
@@ -152,24 +143,12 @@ public final class WifiDisplayStatus implements Parcelable {
}
/**
* Gets the list of all available Wifi displays as reported by the most recent
* scan, never null.
* <p>
* Some of these displays may already be remembered, others may be unknown.
* </p>
* Gets the list of Wifi displays, returns a combined list of all available
* Wifi displays as reported by the most recent scan, and all remembered
* Wifi displays (not necessarily available at the time).
*/
public WifiDisplay[] getAvailableDisplays() {
return mAvailableDisplays;
}
/**
* Gets the list of all remembered Wifi displays, never null.
* <p>
* Not all remembered displays will necessarily be available.
* </p>
*/
public WifiDisplay[] getRememberedDisplays() {
return mRememberedDisplays;
public WifiDisplay[] getDisplays() {
return mDisplays;
}
@Override
@@ -185,13 +164,8 @@ public final class WifiDisplayStatus implements Parcelable {
dest.writeInt(0);
}
dest.writeInt(mAvailableDisplays.length);
for (WifiDisplay display : mAvailableDisplays) {
display.writeToParcel(dest, flags);
}
dest.writeInt(mRememberedDisplays.length);
for (WifiDisplay display : mRememberedDisplays) {
dest.writeInt(mDisplays.length);
for (WifiDisplay display : mDisplays) {
display.writeToParcel(dest, flags);
}
}
@@ -208,8 +182,7 @@ public final class WifiDisplayStatus implements Parcelable {
+ ", scanState=" + mScanState
+ ", activeDisplayState=" + mActiveDisplayState
+ ", activeDisplay=" + mActiveDisplay
+ ", availableDisplays=" + Arrays.toString(mAvailableDisplays)
+ ", rememberedDisplays=" + Arrays.toString(mRememberedDisplays)
+ ", displays=" + Arrays.toString(mDisplays)
+ "}";
}
}

View File

@@ -3970,6 +3970,9 @@
<!-- Status message for remote routes that are not available for connection right now -->
<string name="media_route_status_not_available">Not available</string>
<!-- Status message for a remote route that is in use (and thus unavailabe) right now -->
<string name="media_route_status_in_use">In use</string>
<!-- Display manager service -->
<!-- Name of the built-in display. [CHAR LIMIT=50] -->

View File

@@ -850,6 +850,7 @@
<java-symbol type="string" name="media_route_status_connecting" />
<java-symbol type="string" name="media_route_status_available" />
<java-symbol type="string" name="media_route_status_not_available" />
<java-symbol type="string" name="media_route_status_in_use" />
<java-symbol type="string" name="owner_name" />
<java-symbol type="string" name="config_chooseAccountActivity" />
<java-symbol type="string" name="config_chooseTypeAndAccountActivity" />

View File

@@ -876,44 +876,45 @@ public class MediaRouter {
boolean wantScan = false;
boolean blockScan = false;
WifiDisplay[] oldDisplays = oldStatus != null ?
oldStatus.getRememberedDisplays() : WifiDisplay.EMPTY_ARRAY;
oldStatus.getDisplays() : WifiDisplay.EMPTY_ARRAY;
WifiDisplay[] newDisplays;
WifiDisplay[] availableDisplays;
WifiDisplay activeDisplay;
if (newStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
newDisplays = newStatus.getRememberedDisplays();
availableDisplays = newStatus.getAvailableDisplays();
newDisplays = newStatus.getDisplays();
activeDisplay = newStatus.getActiveDisplay();
} else {
newDisplays = availableDisplays = WifiDisplay.EMPTY_ARRAY;
newDisplays = WifiDisplay.EMPTY_ARRAY;
activeDisplay = null;
}
for (int i = 0; i < newDisplays.length; i++) {
final WifiDisplay d = newDisplays[i];
final boolean available = findMatchingDisplay(d, availableDisplays) != null;
RouteInfo route = findWifiDisplayRoute(d);
if (route == null) {
route = makeWifiDisplayRoute(d, available);
addRouteStatic(route);
wantScan = true;
} else {
updateWifiDisplayRoute(route, d, available, newStatus);
}
if (d.equals(activeDisplay)) {
selectRouteStatic(route.getSupportedTypes(), route);
if (d.isRemembered()) {
RouteInfo route = findWifiDisplayRoute(d);
if (route == null) {
route = makeWifiDisplayRoute(d, newStatus);
addRouteStatic(route);
wantScan = true;
} else {
updateWifiDisplayRoute(route, d, newStatus);
}
if (d.equals(activeDisplay)) {
selectRouteStatic(route.getSupportedTypes(), route);
// Don't scan if we're already connected to a wifi display,
// the scanning process can cause a hiccup with some configurations.
blockScan = true;
// Don't scan if we're already connected to a wifi display,
// the scanning process can cause a hiccup with some configurations.
blockScan = true;
}
}
}
for (int i = 0; i < oldDisplays.length; i++) {
final WifiDisplay d = oldDisplays[i];
final WifiDisplay newDisplay = findMatchingDisplay(d, newDisplays);
if (newDisplay == null) {
removeRoute(findWifiDisplayRoute(d));
if (d.isRemembered()) {
final WifiDisplay newDisplay = findMatchingDisplay(d, newDisplays);
if (newDisplay == null || !newDisplay.isRemembered()) {
removeRoute(findWifiDisplayRoute(d));
}
}
}
@@ -924,42 +925,20 @@ public class MediaRouter {
sStatic.mLastKnownWifiDisplayStatus = newStatus;
}
static RouteInfo makeWifiDisplayRoute(WifiDisplay display, boolean available) {
final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory);
newRoute.mDeviceAddress = display.getDeviceAddress();
newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
newRoute.setStatusCode(available ?
RouteInfo.STATUS_AVAILABLE : RouteInfo.STATUS_CONNECTING);
newRoute.mEnabled = available;
newRoute.mName = display.getFriendlyDisplayName();
newRoute.mDescription = sStatic.mResources.getText(
com.android.internal.R.string.wireless_display_route_description);
newRoute.mPresentationDisplay = choosePresentationDisplayForRoute(newRoute,
sStatic.getAllPresentationDisplays());
return newRoute;
}
private static void updateWifiDisplayRoute(RouteInfo route, WifiDisplay display,
boolean available, WifiDisplayStatus wifiDisplayStatus) {
final boolean isScanning =
wifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING;
boolean changed = false;
static int getWifiDisplayStatusCode(WifiDisplay d, WifiDisplayStatus wfdStatus) {
int newStatus = RouteInfo.STATUS_NONE;
if (available) {
newStatus = isScanning ? RouteInfo.STATUS_SCANNING : RouteInfo.STATUS_AVAILABLE;
if (wfdStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING) {
newStatus = RouteInfo.STATUS_SCANNING;
} else if (d.isAvailable()) {
newStatus = d.canConnect() ?
RouteInfo.STATUS_AVAILABLE: RouteInfo.STATUS_IN_USE;
} else {
newStatus = RouteInfo.STATUS_NOT_AVAILABLE;
}
if (display.equals(wifiDisplayStatus.getActiveDisplay())) {
final int activeState = wifiDisplayStatus.getActiveDisplayState();
if (d.equals(wfdStatus.getActiveDisplay())) {
final int activeState = wfdStatus.getActiveDisplayState();
switch (activeState) {
case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
newStatus = RouteInfo.STATUS_NONE;
@@ -973,22 +952,51 @@ public class MediaRouter {
}
}
return newStatus;
}
static boolean isWifiDisplayEnabled(WifiDisplay d, WifiDisplayStatus wfdStatus) {
return d.isAvailable() && (d.canConnect() || d.equals(wfdStatus.getActiveDisplay()));
}
static RouteInfo makeWifiDisplayRoute(WifiDisplay display, WifiDisplayStatus wfdStatus) {
final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory);
newRoute.mDeviceAddress = display.getDeviceAddress();
newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
newRoute.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
newRoute.mEnabled = isWifiDisplayEnabled(display, wfdStatus);
newRoute.mName = display.getFriendlyDisplayName();
newRoute.mDescription = sStatic.mResources.getText(
com.android.internal.R.string.wireless_display_route_description);
newRoute.mPresentationDisplay = choosePresentationDisplayForRoute(newRoute,
sStatic.getAllPresentationDisplays());
return newRoute;
}
private static void updateWifiDisplayRoute(
RouteInfo route, WifiDisplay display, WifiDisplayStatus wfdStatus) {
boolean changed = false;
final String newName = display.getFriendlyDisplayName();
if (!route.getName().equals(newName)) {
route.mName = newName;
changed = true;
}
changed |= route.mEnabled != available;
route.mEnabled = available;
boolean enabled = isWifiDisplayEnabled(display, wfdStatus);
changed |= route.mEnabled != enabled;
route.mEnabled = enabled;
changed |= route.setStatusCode(newStatus);
changed |= route.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
if (changed) {
dispatchRouteChanged(route);
}
if (!available && route == sStatic.mSelectedRoute) {
if (!enabled && route == sStatic.mSelectedRoute) {
// Oops, no longer available. Reselect the default.
final RouteInfo defaultRoute = sStatic.mDefaultAudioVideo;
selectRouteStatic(defaultRoute.getSupportedTypes(), defaultRoute);
@@ -1069,6 +1077,7 @@ public class MediaRouter {
/** @hide */ public static final int STATUS_CONNECTING = 2;
/** @hide */ public static final int STATUS_AVAILABLE = 3;
/** @hide */ public static final int STATUS_NOT_AVAILABLE = 4;
/** @hide */ public static final int STATUS_IN_USE = 5;
private Object mTag;
@@ -1180,6 +1189,9 @@ public class MediaRouter {
case STATUS_NOT_AVAILABLE:
resId = com.android.internal.R.string.media_route_status_not_available;
break;
case STATUS_IN_USE:
resId = com.android.internal.R.string.media_route_status_in_use;
break;
}
mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
return true;

View File

@@ -106,7 +106,7 @@ final class PersistentDataStore {
}
if (!Objects.equal(display.getDeviceAlias(), alias)) {
return new WifiDisplay(display.getDeviceAddress(), display.getDeviceName(),
alias, display.canConnect());
alias, display.isAvailable(), display.canConnect(), display.isRemembered());
}
}
return display;
@@ -260,7 +260,8 @@ final class PersistentDataStore {
}
mRememberedWifiDisplays.add(
new WifiDisplay(deviceAddress, deviceName, deviceAlias));
new WifiDisplay(deviceAddress, deviceName, deviceAlias,
false, false, false));
}
}
}

View File

@@ -45,6 +45,8 @@ import android.view.SurfaceControl;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import libcore.util.Objects;
@@ -88,6 +90,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
private int mScanState;
private int mActiveDisplayState;
private WifiDisplay mActiveDisplay;
private WifiDisplay[] mDisplays = WifiDisplay.EMPTY_ARRAY;
private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY;
private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
@@ -116,6 +119,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
pw.println("mScanState=" + mScanState);
pw.println("mActiveDisplayState=" + mActiveDisplayState);
pw.println("mActiveDisplay=" + mActiveDisplay);
pw.println("mDisplays=" + Arrays.toString(mDisplays));
pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
@@ -229,7 +233,8 @@ final class WifiDisplayAdapter extends DisplayAdapter {
WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address);
if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) {
display = new WifiDisplay(address, display.getDeviceName(), alias);
display = new WifiDisplay(address, display.getDeviceName(), alias,
false, false, false);
if (mPersistentDataStore.rememberWifiDisplay(display)) {
mPersistentDataStore.saveIfNeeded();
updateRememberedDisplaysLocked();
@@ -262,7 +267,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
if (mCurrentStatus == null) {
mCurrentStatus = new WifiDisplayStatus(
mFeatureState, mScanState, mActiveDisplayState,
mActiveDisplay, mAvailableDisplays, mRememberedDisplays);
mActiveDisplay, mDisplays);
}
if (DEBUG) {
@@ -271,10 +276,36 @@ final class WifiDisplayAdapter extends DisplayAdapter {
return mCurrentStatus;
}
private void updateDisplaysLocked() {
List<WifiDisplay> displays = new ArrayList<WifiDisplay>(
mAvailableDisplays.length + mRememberedDisplays.length);
boolean[] remembered = new boolean[mAvailableDisplays.length];
for (WifiDisplay d : mRememberedDisplays) {
boolean available = false;
for (int i = 0; i < mAvailableDisplays.length; i++) {
if (d.equals(mAvailableDisplays[i])) {
remembered[i] = available = true;
break;
}
}
if (!available) {
displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(),
d.getDeviceAlias(), false, false, true));
}
}
for (int i = 0; i < mAvailableDisplays.length; i++) {
WifiDisplay d = mAvailableDisplays[i];
displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(),
d.getDeviceAlias(), true, d.canConnect(), remembered[i]));
}
mDisplays = displays.toArray(WifiDisplay.EMPTY_ARRAY);
}
private void updateRememberedDisplaysLocked() {
mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays();
mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay);
mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
updateDisplaysLocked();
}
private void fixRememberedDisplayNamesFromAvailableDisplaysLocked() {
@@ -487,11 +518,18 @@ final class WifiDisplayAdapter extends DisplayAdapter {
availableDisplays = mPersistentDataStore.applyWifiDisplayAliases(
availableDisplays);
if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
|| !Arrays.equals(mAvailableDisplays, availableDisplays)) {
// check if any of the available displays changed canConnect status
boolean changed = !Arrays.equals(mAvailableDisplays, availableDisplays);
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;
mAvailableDisplays = availableDisplays;
fixRememberedDisplayNamesFromAvailableDisplaysLocked();
updateDisplaysLocked();
scheduleStatusChangedBroadcastLocked();
}
}

View File

@@ -898,7 +898,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
private static WifiDisplay createWifiDisplay(WifiP2pDevice device) {
return new WifiDisplay(device.deviceAddress, device.deviceName, null,
device.wfdInfo.isSessionAvailable());
true, device.wfdInfo.isSessionAvailable(), false);
}
private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() {