summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI
diff options
context:
space:
mode:
authorJohn Spurlock <jspurlock@google.com>2014-07-13 11:59:50 -0400
committerJohn Spurlock <jspurlock@google.com>2014-07-13 12:06:21 -0400
commit1e6eb17a22056529601c8e413c2da0541d59d93b (patch)
tree0687b474f9c61b21ac7e09fac0a1b8b54bc764e4 /packages/SystemUI
parentf6e2fcc2eaf5e650237d3c6d79a2de49d2d4111e (diff)
downloadframeworks_base-1e6eb17a22056529601c8e413c2da0541d59d93b.zip
frameworks_base-1e6eb17a22056529601c8e413c2da0541d59d93b.tar.gz
frameworks_base-1e6eb17a22056529601c8e413c2da0541d59d93b.tar.bz2
QS: Introduce cast control panel.
Make cast controller more granular, at the route level, and bind a common detail item panel to the available routes. Fix tile icon, add connecting label. Remove dialog presentation, no longer needed. Add the new empty state, and add controller state to dump. Found a bug in keyguard when in presentation mode, added a workaround - don't crash when no owner info in keyguard status view. Bug:15833210 Change-Id: I19afec390eac2260bccf4a7064065b666b7bceca
Diffstat (limited to 'packages/SystemUI')
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_cast_on.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java184
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java151
7 files changed, 317 insertions, 82 deletions
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
new file mode 100644
index 0000000..fbc21d4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <size
+ android:width="56dp"
+ android:height="56dp"/>
+
+ <viewport
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0"/>
+
+ <path
+ android:fill="@color/qs_detail_empty"
+ android:pathData="M42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
index 8dacdc9..159bf65 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
@@ -24,5 +24,5 @@ Copyright (C) 2014 The Android Open Source Project
<path
android:fill="#FFFFFFFF"
- android:pathData="M42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0z"/>
+ android:pathData="M2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM38.0,14.0L10.0,14.0l0.0,3.3c7.9,2.6 14.2,8.8 16.7,16.7L38.0,34.0L38.0,14.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0z"/>
</vector>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b0f2133..6a7b450 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -526,8 +526,16 @@
<string name="quick_settings_wifi_off_label">Wi-Fi Off</string>
<!-- QuickSettings: Wifi detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_detail_empty_text">No saved networks available</string>
- <!-- QuickSettings: Remote display [CHAR LIMIT=NONE] -->
- <string name="quick_settings_remote_display_no_connection_label">Cast screen</string>
+ <!-- QuickSettings: Cast title [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_cast_title">Cast screen</string>
+ <!-- QuickSettings: Cast detail panel, status text when casting [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_casting">Casting</string>
+ <!-- QuickSettings: Cast detail panel, default device name [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_cast_device_default_name">Unnamed device</string>
+ <!-- QuickSettings: Cast detail panel, default device description [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_cast_device_default_description">Ready to cast</string>
+ <!-- QuickSettings: Cast detail panel, text when there are no items [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_cast_detail_empty_text">No devices available</string>
<!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_dialog_title">Brightness</string>
<!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 502713f..ab952c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -16,17 +16,23 @@
package com.android.systemui.qs.tiles;
-import android.app.Dialog;
+import android.content.Context;
import android.content.Intent;
-import android.media.MediaRouter;
import android.provider.Settings;
+import android.util.Log;
import android.view.View;
-import android.view.WindowManager;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.ViewGroup;
-import com.android.internal.app.MediaRouteDialogPresenter;
import com.android.systemui.R;
+import com.android.systemui.qs.QSDetailItems;
+import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastController.CastDevice;
+
+import java.util.LinkedHashMap;
+import java.util.Set;
/** Quick settings tile: Cast **/
public class CastTile extends QSTile<QSTile.BooleanState> {
@@ -34,10 +40,17 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
private final CastController mController;
+ private final CastDetailAdapter mDetailAdapter;
public CastTile(Host host) {
super(host);
mController = host.getCastController();
+ mDetailAdapter = new CastDetailAdapter();
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
}
@Override
@@ -48,12 +61,13 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
@Override
public void setListening(boolean listening) {
if (mController == null) return;
+ if (DEBUG) Log.d(TAG, "setListening " + listening);
if (listening) {
mController.addCallback(mCallback);
} else {
+ mController.setDiscovering(false);
mController.removeCallback(mCallback);
}
- mController.setDiscovering(listening);
}
@Override
@@ -65,61 +79,147 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleClick() {
- mHandler.post(new Runnable() {
- public void run() {
- mHost.collapsePanels();
- mUiHandler.post(mShowDialog);
- }
- });
+ showDetail(true);
}
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.visible = true;
- state.label = mContext
- .getString(R.string.quick_settings_remote_display_no_connection_label);
- if (arg instanceof CallbackInfo) {
- final CallbackInfo cb = (CallbackInfo) arg;
- if (cb.connectedRouteName != null) {
- state.value = !cb.connecting;
+ state.label = mContext.getString(R.string.quick_settings_cast_title);
+ state.value = false;
+ final Set<CastDevice> devices = mController.getCastDevices();
+ boolean connecting = false;
+ for (CastDevice device : devices) {
+ if (device.state == CastDevice.STATE_CONNECTED) {
+ state.value = true;
+ state.label = getDeviceName(device);
+ } else if (device.state == CastDevice.STATE_CONNECTING) {
+ connecting = true;
}
}
+ if (!state.value && connecting) {
+ state.label = mContext.getString(R.string.quick_settings_connecting);
+ }
state.iconId = state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off;
+ mDetailAdapter.updateItems(devices);
}
- private static class CallbackInfo {
- boolean enabled;
- boolean connecting;
- String connectedRouteName;
+ private String getDeviceName(CastDevice device) {
+ return device.name != null ? device.name
+ : mContext.getString(R.string.quick_settings_cast_device_default_name);
}
private final CastController.Callback mCallback = new CastController.Callback() {
@Override
- public void onStateChanged(boolean enabled, boolean connecting,
- String connectedRouteName) {
- final CallbackInfo info = new CallbackInfo(); // TODO pool
- info.enabled = enabled;
- info.connecting = connecting;
- info.connectedRouteName = connectedRouteName;
- refreshState(info);
+ public void onCastDevicesChanged() {
+ refreshState();
}
};
- private final Runnable mShowDialog = new Runnable() {
- private Dialog mDialog;
+ private final class CastDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
+ private final LinkedHashMap<String, CastDevice> mVisibleOrder = new LinkedHashMap<>();
+
+ private QSDetailItems mItems;
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_cast_title;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return WIFI_DISPLAY_SETTINGS;
+ }
+
@Override
- public void run() {
- mDialog = MediaRouteDialogPresenter.createDialog(mContext,
- MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mDialog.dismiss();
- mHost.startSettingsActivity(WIFI_DISPLAY_SETTINGS);
+ public void setToggleState(boolean state) {
+ // noop
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
+ mItems.setTagSuffix("Cast");
+ if (convertView == null) {
+ if (DEBUG) Log.d(TAG, "addOnAttachStateChangeListener");
+ mItems.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ if (DEBUG) Log.d(TAG, "onViewAttachedToWindow");
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ if (DEBUG) Log.d(TAG, "onViewDetachedFromWindow");
+ mVisibleOrder.clear();
+ }
+ });
+ }
+ mItems.setEmptyState(R.drawable.ic_qs_cast_detail_empty,
+ R.string.quick_settings_cast_detail_empty_text);
+ mItems.setCallback(this);
+ updateItems(mController.getCastDevices());
+ mController.setDiscovering(true);
+ return mItems;
+ }
+
+ private void updateItems(Set<CastDevice> devices) {
+ if (mItems == null) return;
+ Item[] items = null;
+ if (devices != null && !devices.isEmpty()) {
+ // if we are connected, simply show that device
+ for (CastDevice device : devices) {
+ if (device.state == CastDevice.STATE_CONNECTED) {
+ final Item item = new Item();
+ item.icon = R.drawable.ic_qs_cast_on;
+ item.line1 = getDeviceName(device);
+ item.line2 = mContext.getString(R.string.quick_settings_connected);
+ item.tag = device;
+ item.canDisconnect = true;
+ items = new Item[] { item };
+ break;
+ }
}
- });
- mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
- mDialog.show();
+ // otherwise list all available devices, and don't move them around
+ if (items == null) {
+ for (CastDevice device : devices) {
+ mVisibleOrder.put(device.id, device);
+ }
+ items = new Item[devices.size()];
+ int i = 0;
+ for (String id : mVisibleOrder.keySet()) {
+ final CastDevice device = mVisibleOrder.get(id);
+ if (!devices.contains(device)) continue;
+ final Item item = new Item();
+ item.icon = R.drawable.ic_qs_cast_off;
+ item.line1 = getDeviceName(device);
+ if (device.state == CastDevice.STATE_CONNECTING) {
+ item.line2 = mContext.getString(R.string.quick_settings_connecting);
+ }
+ item.tag = device;
+ items[i++] = item;
+ }
+ }
+ }
+ mItems.setItems(items);
}
- };
+
+ @Override
+ public void onDetailItemClick(Item item) {
+ if (item == null || item.tag == null) return;
+ final CastDevice device = (CastDevice) item.tag;
+ mController.startCasting(device);
+ }
+
+ @Override
+ public void onDetailItemDisconnect(Item item) {
+ if (item == null || item.tag == null) return;
+ mController.stopCasting();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 9d7d933..505af44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2322,6 +2322,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mBluetoothController != null) {
mBluetoothController.dump(fd, pw, args);
}
+ if (mCastController != null) {
+ mCastController.dump(fd, pw, args);
+ }
}
private String hunStateToString(Entry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
index 54041e1..eb5804a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
@@ -16,13 +16,30 @@
package com.android.systemui.statusbar.policy;
+import java.util.Set;
+
public interface CastController {
void addCallback(Callback callback);
void removeCallback(Callback callback);
void setDiscovering(boolean request);
void setCurrentUserId(int currentUserId);
+ Set<CastDevice> getCastDevices();
+ void startCasting(CastDevice device);
+ void stopCasting();
public interface Callback {
- void onStateChanged(boolean enabled, boolean connecting, String connectedRouteName);
+ void onCastDevicesChanged();
+ }
+
+ public static final class CastDevice {
+ public static final int STATE_DISCONNECTED = 0;
+ public static final int STATE_CONNECTING = 1;
+ public static final int STATE_CONNECTED = 2;
+
+ public String id;
+ public String name;
+ public String description;
+ public int state = STATE_DISCONNECTED;
+ public Object tag;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index bcd865c..22179e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -16,30 +16,55 @@
package com.android.systemui.statusbar.policy;
+import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
+
import android.content.Context;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Set;
+import java.util.UUID;
/** Platform implementation of the cast controller. **/
public class CastControllerImpl implements CastController {
+ private static final String TAG = "CastController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private final Context mContext;
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final MediaRouter mMediaRouter;
+ private final ArrayMap<String, RouteInfo> mRoutes = new ArrayMap<>();
+ private final Object mDiscoveringLock = new Object();
- private boolean mEnabled;
- private boolean mConnecting;
- private String mConnectedRouteName;
+ private boolean mDiscovering;
public CastControllerImpl(Context context) {
+ mContext = context;
mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ if (DEBUG) Log.d(TAG, "new CastController()");
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("CastController state:");
+ pw.print(" mDiscovering="); pw.println(mDiscovering);
+ pw.print(" mCallbacks.size="); pw.println(mCallbacks.size());
+ pw.print(" mRoutes.size="); pw.println(mRoutes.size());
+ for (int i = 0; i < mRoutes.size(); i++) {
+ final RouteInfo route = mRoutes.valueAt(i);
+ pw.print(" "); pw.println(routeToString(route));
+ }
}
@Override
public void addCallback(Callback callback) {
mCallbacks.add(callback);
- fireStateChanged(callback);
+ fireOnCastDevicesChanged(callback);
}
@Override
@@ -49,12 +74,16 @@ public class CastControllerImpl implements CastController {
@Override
public void setDiscovering(boolean request) {
- if (request) {
- mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
- mMediaCallback,
- MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
- } else {
- mMediaRouter.removeCallback(mMediaCallback);
+ synchronized (mDiscoveringLock) {
+ if (mDiscovering == request) return;
+ mDiscovering = request;
+ if (DEBUG) Log.d(TAG, "setDiscovering: " + request);
+ if (request) {
+ mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
+ MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
+ } else {
+ mMediaRouter.removeCallback(mMediaCallback);
+ }
}
}
@@ -63,63 +92,113 @@ public class CastControllerImpl implements CastController {
mMediaRouter.rebindAsUser(currentUserId);
}
- private void updateRemoteDisplays() {
- final MediaRouter.RouteInfo connectedRoute = mMediaRouter.getSelectedRoute(
- MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
- boolean enabled = connectedRoute != null
- && connectedRoute.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
- boolean connecting;
- if (enabled) {
- connecting = connectedRoute.isConnecting();
- } else {
- connecting = false;
- enabled = mMediaRouter.isRouteAvailable(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
- MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE);
+ @Override
+ public Set<CastDevice> getCastDevices() {
+ final ArraySet<CastDevice> devices = new ArraySet<CastDevice>();
+ synchronized(mRoutes) {
+ for (RouteInfo route : mRoutes.values()) {
+ final CastDevice device = new CastDevice();
+ device.id = route.getTag().toString();
+ final CharSequence name = route.getName(mContext);
+ device.name = name != null ? name.toString() : null;
+ final CharSequence description = route.getDescription();
+ device.description = description != null ? description.toString() : null;
+ device.state = route.isConnecting() ? CastDevice.STATE_CONNECTING
+ : route.isSelected() ? CastDevice.STATE_CONNECTED
+ : CastDevice.STATE_DISCONNECTED;
+ device.tag = route;
+ devices.add(device);
+ }
}
+ return devices;
+ }
+
+ @Override
+ public void startCasting(CastDevice device) {
+ if (device == null || device.tag == null) return;
+ final RouteInfo route = (RouteInfo) device.tag;
+ if (DEBUG) Log.d(TAG, "startCasting: " + routeToString(route));
+ mMediaRouter.selectRoute(ROUTE_TYPE_REMOTE_DISPLAY, route);
+ }
- String connectedRouteName = null;
- if (connectedRoute != null) {
- connectedRouteName = connectedRoute.getName().toString();
+ @Override
+ public void stopCasting() {
+ if (DEBUG) Log.d(TAG, "stopCasting");
+ mMediaRouter.getDefaultRoute().select();
+ }
+
+ private void updateRemoteDisplays() {
+ synchronized(mRoutes) {
+ mRoutes.clear();
+ final int n = mMediaRouter.getRouteCount();
+ for (int i = 0; i < n; i++) {
+ final RouteInfo route = mMediaRouter.getRouteAt(i);
+ if (!route.isEnabled()) continue;
+ if (!route.matchesTypes(ROUTE_TYPE_REMOTE_DISPLAY)) continue;
+ ensureTagExists(route);
+ mRoutes.put(route.getTag().toString(), route);
+ }
+ final RouteInfo selected = mMediaRouter.getSelectedRoute(ROUTE_TYPE_REMOTE_DISPLAY);
+ if (selected != null && !selected.isDefault()) {
+ ensureTagExists(selected);
+ mRoutes.put(selected.getTag().toString(), selected);
+ }
}
- synchronized(mCallbacks) {
- mEnabled = enabled;
- mConnecting = connecting;
- mConnectedRouteName = connectedRouteName;
+ fireOnCastDevicesChanged();
+ }
+
+ private void ensureTagExists(RouteInfo route) {
+ if (route.getTag() == null) {
+ route.setTag(UUID.randomUUID().toString());
}
- fireStateChanged();
}
- private void fireStateChanged() {
+ private void fireOnCastDevicesChanged() {
for (Callback callback : mCallbacks) {
- fireStateChanged(callback);
+ fireOnCastDevicesChanged(callback);
}
}
- private void fireStateChanged(Callback callback) {
- synchronized(mCallbacks) {
- callback.onStateChanged(mEnabled, mConnecting, mConnectedRouteName);
- }
+ private void fireOnCastDevicesChanged(Callback callback) {
+ callback.onCastDevicesChanged();
+ }
+
+ private static String routeToString(RouteInfo route) {
+ if (route == null) return null;
+ final StringBuilder sb = new StringBuilder().append(route.getName()).append('/')
+ .append(route.getDescription()).append('@').append(route.getDeviceAddress())
+ .append(",status=").append(route.getStatus());
+ if (route.isDefault()) sb.append(",default");
+ if (route.isEnabled()) sb.append(",enabled");
+ if (route.isConnecting()) sb.append(",connecting");
+ if (route.isSelected()) sb.append(",selected");
+ return sb.append(",id=").append(route.getTag()).toString();
}
private final MediaRouter.SimpleCallback mMediaCallback = new MediaRouter.SimpleCallback() {
@Override
public void onRouteAdded(MediaRouter router, RouteInfo route) {
+ if (DEBUG) Log.d(TAG, "onRouteAdded: " + routeToString(route));
updateRemoteDisplays();
}
@Override
public void onRouteChanged(MediaRouter router, RouteInfo route) {
+ if (DEBUG) Log.d(TAG, "onRouteChanged: " + routeToString(route));
updateRemoteDisplays();
}
@Override
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
+ if (DEBUG) Log.d(TAG, "onRouteRemoved: " + routeToString(route));
updateRemoteDisplays();
}
@Override
public void onRouteSelected(MediaRouter router, int type, RouteInfo route) {
+ if (DEBUG) Log.d(TAG, "onRouteSelected(" + type + "): " + routeToString(route));
updateRemoteDisplays();
}
@Override
public void onRouteUnselected(MediaRouter router, int type, RouteInfo route) {
+ if (DEBUG) Log.d(TAG, "onRouteUnselected(" + type + "): " + routeToString(route));
updateRemoteDisplays();
}
};