Merge "UI tweaks." into klp-dev

This commit is contained in:
Jeff Brown
2013-11-12 05:57:48 +00:00
committed by Android (Google) Code Review
6 changed files with 244 additions and 69 deletions

View File

@ -106,8 +106,8 @@ public class MediaRouteChooserDialog extends Dialog {
/**
* Returns true if the route should be included in the list.
* <p>
* The default implementation returns true for non-default routes that
* match the selector. Subclasses can override this method to filter routes
* The default implementation returns true for enabled non-default routes that
* match the route types. Subclasses can override this method to filter routes
* differently.
* </p>
*
@ -115,7 +115,7 @@ public class MediaRouteChooserDialog extends Dialog {
* @return True if the route should be included in the chooser dialog.
*/
public boolean onFilterRoute(MediaRouter.RouteInfo route) {
return !route.isDefault() && route.matchesTypes(mRouteTypes);
return !route.isDefault() && route.isEnabled() && route.matchesTypes(mRouteTypes);
}
@Override

View File

@ -23,7 +23,8 @@
<!-- List of routes. -->
<ListView android:id="@+id/media_route_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- Content to show when list is empty. -->
<LinearLayout android:id="@android:id/empty"

View File

@ -469,7 +469,7 @@ public class MediaRouter {
route.mDescription = globalRoute.description;
route.mSupportedTypes = globalRoute.supportedTypes;
route.mEnabled = globalRoute.enabled;
route.setStatusCode(globalRoute.statusCode);
route.setRealStatusCode(globalRoute.statusCode);
route.mPlaybackType = globalRoute.playbackType;
route.mPlaybackStream = globalRoute.playbackStream;
route.mVolume = globalRoute.volume;
@ -501,8 +501,8 @@ public class MediaRouter {
route.mEnabled = globalRoute.enabled;
changed = true;
}
if (route.mStatusCode != globalRoute.statusCode) {
route.setStatusCode(globalRoute.statusCode);
if (route.mRealStatusCode != globalRoute.statusCode) {
route.setRealStatusCode(globalRoute.statusCode);
changed = true;
}
if (route.mPlaybackType != globalRoute.playbackType) {
@ -918,8 +918,14 @@ public class MediaRouter {
if (oldRoute != null) {
dispatchRouteUnselected(types & oldRoute.getSupportedTypes(), oldRoute);
if (oldRoute.resolveStatusCode()) {
dispatchRouteChanged(oldRoute);
}
}
if (route != null) {
if (route.resolveStatusCode()) {
dispatchRouteChanged(route);
}
dispatchRouteSelected(types & route.getSupportedTypes(), route);
}
}
@ -1337,7 +1343,7 @@ public class MediaRouter {
newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
newRoute.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
newRoute.setRealStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
newRoute.mEnabled = isWifiDisplayEnabled(display, wfdStatus);
newRoute.mName = display.getFriendlyDisplayName();
newRoute.mDescription = sStatic.mResources.getText(
@ -1359,7 +1365,7 @@ public class MediaRouter {
changed |= route.mEnabled != enabled;
route.mEnabled = enabled;
changed |= route.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
changed |= route.setRealStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
if (changed) {
dispatchRouteChanged(route);
@ -1422,7 +1428,8 @@ public class MediaRouter {
String mGlobalRouteId;
// A predetermined connection status that can override mStatus
private int mStatusCode;
private int mRealStatusCode;
private int mResolvedStatusCode;
/** @hide */ public static final int STATUS_NONE = 0;
/** @hide */ public static final int STATUS_SCANNING = 1;
@ -1526,43 +1533,71 @@ public class MediaRouter {
* Set this route's status by predetermined status code. If the caller
* should dispatch a route changed event this call will return true;
*/
boolean setStatusCode(int statusCode) {
if (statusCode != mStatusCode) {
mStatusCode = statusCode;
int resId;
switch (statusCode) {
case STATUS_SCANNING:
resId = com.android.internal.R.string.media_route_status_scanning;
break;
case STATUS_CONNECTING:
resId = com.android.internal.R.string.media_route_status_connecting;
break;
case STATUS_AVAILABLE:
resId = com.android.internal.R.string.media_route_status_available;
break;
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;
case STATUS_CONNECTED:
case STATUS_NONE:
default:
resId = 0;
break;
}
mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
return true;
boolean setRealStatusCode(int statusCode) {
if (mRealStatusCode != statusCode) {
mRealStatusCode = statusCode;
return resolveStatusCode();
}
return false;
}
/**
* Resolves the status code whenever the real status code or selection state
* changes.
*/
boolean resolveStatusCode() {
int statusCode = mRealStatusCode;
if (isSelected()) {
switch (statusCode) {
// If the route is selected and its status appears to be between states
// then report it as connecting even though it has not yet had a chance
// to officially move into the CONNECTING state. Note that routes in
// the NONE state are assumed to not require an explicit connection
// lifecycle whereas those that are AVAILABLE are assumed to have
// to eventually proceed to CONNECTED.
case STATUS_AVAILABLE:
case STATUS_SCANNING:
statusCode = STATUS_CONNECTING;
break;
}
}
if (mResolvedStatusCode == statusCode) {
return false;
}
mResolvedStatusCode = statusCode;
int resId;
switch (statusCode) {
case STATUS_SCANNING:
resId = com.android.internal.R.string.media_route_status_scanning;
break;
case STATUS_CONNECTING:
resId = com.android.internal.R.string.media_route_status_connecting;
break;
case STATUS_AVAILABLE:
resId = com.android.internal.R.string.media_route_status_available;
break;
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;
case STATUS_CONNECTED:
case STATUS_NONE:
default:
resId = 0;
break;
}
mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
return true;
}
/**
* @hide
*/
public int getStatusCode() {
return mStatusCode;
return mResolvedStatusCode;
}
/**
@ -1821,19 +1856,7 @@ public class MediaRouter {
* @return True if this route is in the process of connecting.
*/
public boolean isConnecting() {
// If the route is selected and its status appears to be between states
// then report it as connecting even though it has not yet had a chance
// to move into the CONNECTING state. Note that routes in the NONE state
// are assumed to not require an explicit connection lifecycle.
if (isSelected()) {
switch (mStatusCode) {
case STATUS_AVAILABLE:
case STATUS_SCANNING:
case STATUS_CONNECTING:
return true;
}
}
return false;
return mResolvedStatusCode == STATUS_CONNECTING;
}
/** @hide */

View File

@ -16,6 +16,7 @@
package com.android.media.remotedisplay;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@ -27,6 +28,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.ArrayMap;
import java.util.Collection;
@ -95,6 +97,7 @@ public abstract class RemoteDisplayProvider {
private static final int MSG_SET_VOLUME = 5;
private static final int MSG_ADJUST_VOLUME = 6;
private final Context mContext;
private final ProviderStub mStub;
private final ProviderHandler mHandler;
private final ArrayMap<String, RemoteDisplay> mDisplays =
@ -102,6 +105,8 @@ public abstract class RemoteDisplayProvider {
private IRemoteDisplayCallback mCallback;
private int mDiscoveryMode = DISCOVERY_MODE_NONE;
private PendingIntent mSettingsPendingIntent;
/**
* The {@link Intent} that must be declared as handled by the service.
* Put this in your manifest.
@ -140,10 +145,18 @@ public abstract class RemoteDisplayProvider {
* @param context The application context for the remote display provider.
*/
public RemoteDisplayProvider(Context context) {
mContext = context;
mStub = new ProviderStub();
mHandler = new ProviderHandler(context.getMainLooper());
}
/**
* Gets the context of the remote display provider.
*/
public final Context getContext() {
return mContext;
}
/**
* Gets the Binder associated with the provider.
* <p>
@ -261,11 +274,29 @@ public abstract class RemoteDisplayProvider {
* Finds the remote display with the specified id, returns null if not found.
*
* @param id Id of the remote display.
* @return The display, or null if none.
*/
public RemoteDisplay findRemoteDisplay(String id) {
return mDisplays.get(id);
}
/**
* Gets a pending intent to launch the remote display settings activity.
*
* @return A pending intent to launch the settings activity.
*/
public PendingIntent getSettingsPendingIntent() {
if (mSettingsPendingIntent == null) {
Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
mSettingsPendingIntent = PendingIntent.getActivity(
mContext, 0, settingsIntent, 0, null);
}
return mSettingsPendingIntent;
}
void setCallback(IRemoteDisplayCallback callback) {
mCallback = callback;
publishState();

View File

@ -600,8 +600,16 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private static final int MSG_CONNECTION_TIMED_OUT = 9;
private static final int TIMEOUT_REASON_NOT_AVAILABLE = 1;
private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTING = 2;
private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTED = 3;
private static final int TIMEOUT_REASON_CONNECTION_LOST = 2;
private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTING = 3;
private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTED = 4;
// The relative order of these constants is important and expresses progress
// through the process of connecting to a route.
private static final int PHASE_NOT_AVAILABLE = -1;
private static final int PHASE_NOT_CONNECTED = 0;
private static final int PHASE_CONNECTING = 1;
private static final int PHASE_CONNECTED = 2;
private final MediaRouterService mService;
private final UserRecord mUserRecord;
@ -614,6 +622,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private boolean mRunning;
private int mDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_NONE;
private RouteRecord mGloballySelectedRouteRecord;
private int mConnectionPhase = PHASE_NOT_AVAILABLE;
private int mConnectionTimeoutReason;
private long mConnectionTimeoutStartTime;
private boolean mClientStateUpdateScheduled;
@ -675,6 +684,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
pw.println(indent + "mRunning=" + mRunning);
pw.println(indent + "mDiscoveryMode=" + mDiscoveryMode);
pw.println(indent + "mGloballySelectedRouteRecord=" + mGloballySelectedRouteRecord);
pw.println(indent + "mConnectionPhase=" + mConnectionPhase);
pw.println(indent + "mConnectionTimeoutReason=" + mConnectionTimeoutReason);
pw.println(indent + "mConnectionTimeoutStartTime=" + (mConnectionTimeoutReason != 0 ?
TimeUtils.formatUptime(mConnectionTimeoutStartTime) : "<n/a>"));
@ -843,6 +853,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private void checkGloballySelectedRouteState() {
// Unschedule timeouts when the route is unselected.
if (mGloballySelectedRouteRecord == null) {
mConnectionPhase = PHASE_NOT_AVAILABLE;
updateConnectionTimeout(0);
return;
}
@ -854,29 +865,34 @@ public final class MediaRouterService extends IMediaRouterService.Stub
return;
}
// Make sure we haven't lost our connection.
final int oldPhase = mConnectionPhase;
mConnectionPhase = getConnectionPhase(mGloballySelectedRouteRecord.getStatus());
if (oldPhase >= PHASE_CONNECTING && mConnectionPhase < PHASE_CONNECTING) {
updateConnectionTimeout(TIMEOUT_REASON_CONNECTION_LOST);
return;
}
// Check the route status.
switch (mGloballySelectedRouteRecord.getStatus()) {
case MediaRouter.RouteInfo.STATUS_NONE:
case MediaRouter.RouteInfo.STATUS_CONNECTED:
if (mConnectionTimeoutReason != 0) {
switch (mConnectionPhase) {
case PHASE_CONNECTED:
if (oldPhase != PHASE_CONNECTED) {
Slog.i(TAG, "Connected to global route: "
+ mGloballySelectedRouteRecord);
}
updateConnectionTimeout(0);
break;
case MediaRouter.RouteInfo.STATUS_CONNECTING:
if (mConnectionTimeoutReason != 0) {
case PHASE_CONNECTING:
if (oldPhase != PHASE_CONNECTING) {
Slog.i(TAG, "Connecting to global route: "
+ mGloballySelectedRouteRecord);
}
updateConnectionTimeout(TIMEOUT_REASON_WAITING_FOR_CONNECTED);
break;
case MediaRouter.RouteInfo.STATUS_SCANNING:
case MediaRouter.RouteInfo.STATUS_AVAILABLE:
case PHASE_NOT_CONNECTED:
updateConnectionTimeout(TIMEOUT_REASON_WAITING_FOR_CONNECTING);
break;
case MediaRouter.RouteInfo.STATUS_NOT_AVAILABLE:
case MediaRouter.RouteInfo.STATUS_IN_USE:
case PHASE_NOT_AVAILABLE:
default:
updateConnectionTimeout(TIMEOUT_REASON_NOT_AVAILABLE);
break;
@ -892,7 +908,9 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mConnectionTimeoutStartTime = SystemClock.uptimeMillis();
switch (reason) {
case TIMEOUT_REASON_NOT_AVAILABLE:
// Route became unavailable. Unselect it immediately.
case TIMEOUT_REASON_CONNECTION_LOST:
// Route became unavailable or connection lost.
// Unselect it immediately.
sendEmptyMessage(MSG_CONNECTION_TIMED_OUT);
break;
case TIMEOUT_REASON_WAITING_FOR_CONNECTING:
@ -919,6 +937,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
Slog.i(TAG, "Global route no longer available: "
+ mGloballySelectedRouteRecord);
break;
case TIMEOUT_REASON_CONNECTION_LOST:
Slog.i(TAG, "Global route connection lost: "
+ mGloballySelectedRouteRecord);
break;
case TIMEOUT_REASON_WAITING_FOR_CONNECTING:
Slog.i(TAG, "Global route timed out while waiting for "
+ "connection attempt to begin after "
@ -1004,6 +1026,23 @@ public final class MediaRouterService extends IMediaRouterService.Stub
return null;
}
private static int getConnectionPhase(int status) {
switch (status) {
case MediaRouter.RouteInfo.STATUS_NONE:
case MediaRouter.RouteInfo.STATUS_CONNECTED:
return PHASE_CONNECTED;
case MediaRouter.RouteInfo.STATUS_CONNECTING:
return PHASE_CONNECTING;
case MediaRouter.RouteInfo.STATUS_SCANNING:
case MediaRouter.RouteInfo.STATUS_AVAILABLE:
return PHASE_NOT_CONNECTED;
case MediaRouter.RouteInfo.STATUS_NOT_AVAILABLE:
case MediaRouter.RouteInfo.STATUS_IN_USE:
default:
return PHASE_NOT_AVAILABLE;
}
}
static final class ProviderRecord {
private final RemoteDisplayProviderProxy mProvider;
private final String mUniquePrefix;

View File

@ -52,6 +52,9 @@ public class RemoteDisplayProviderService extends Service {
private RemoteDisplay mTestDisplay5; // available but ignores request to connect
private RemoteDisplay mTestDisplay6; // available but never finishes connecting
private RemoteDisplay mTestDisplay7; // blinks in and out of existence
private RemoteDisplay mTestDisplay8; // available but connecting attempt flakes out
private RemoteDisplay mTestDisplay9; // available but connection flakes out
private RemoteDisplay mTestDisplay10; // available and reconnects periodically
private final Handler mHandler;
private boolean mBlinking;
@ -112,6 +115,27 @@ public class RemoteDisplayProviderService extends Service {
mTestDisplay6.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay6);
}
if (mTestDisplay8 == null) {
mTestDisplay8 = new RemoteDisplay("testDisplay8",
"Test Display 8 (flaky when connecting)");
mTestDisplay8.setDescription("Aborts spontaneously while connecting");
mTestDisplay8.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay8);
}
if (mTestDisplay9 == null) {
mTestDisplay9 = new RemoteDisplay("testDisplay9",
"Test Display 9 (flaky when connected)");
mTestDisplay9.setDescription("Aborts spontaneously while connected");
mTestDisplay9.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay9);
}
if (mTestDisplay10 == null) {
mTestDisplay10 = new RemoteDisplay("testDisplay10",
"Test Display 10 (reconnects periodically)");
mTestDisplay10.setDescription("Reconnects spontaneously");
mTestDisplay10.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay10);
}
} else {
// When discovery ends, go hide some of the routes we can't actually use.
// This isn't something a normal route provider would do though.
@ -144,6 +168,7 @@ public class RemoteDisplayProviderService extends Service {
if (display == mTestDisplay1 || display == mTestDisplay2) {
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
@ -154,12 +179,67 @@ public class RemoteDisplayProviderService extends Service {
}
}
}, 2000);
updateDisplay(display);
}
if (display == mTestDisplay6 || display == mTestDisplay7) {
} else if (display == mTestDisplay6 || display == mTestDisplay7) {
// never finishes connecting
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
} else if (display == mTestDisplay8) {
// flakes out while connecting
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if ((display == mTestDisplay8)
&& display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
updateDisplay(display);
}
}
}, 2000);
} else if (display == mTestDisplay9) {
// flakes out when connected
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if ((display == mTestDisplay9)
&& display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
display.setStatus(RemoteDisplay.STATUS_CONNECTED);
updateDisplay(display);
}
}
}, 2000);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if ((display == mTestDisplay9)
&& display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
updateDisplay(display);
}
}
}, 5000);
} else if (display == mTestDisplay10) {
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (display == mTestDisplay10) {
if (display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
display.setStatus(RemoteDisplay.STATUS_CONNECTED);
updateDisplay(display);
mHandler.postDelayed(this, 7000);
} else if (display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(this, 2000);
}
}
}
}, 2000);
}
}
@ -168,7 +248,8 @@ public class RemoteDisplayProviderService extends Service {
Log.d(TAG, "onDisconnect: display.getId()=" + display.getId());
if (display == mTestDisplay1 || display == mTestDisplay2
|| display == mTestDisplay6) {
|| display == mTestDisplay6 || display == mTestDisplay8
|| display == mTestDisplay9 || display == mTestDisplay10) {
display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
updateDisplay(display);
}