am 706a8699: Merge "Make MediaRouter UI more robust around route count changes" into jb-dev
* commit '706a8699008ce416a7fbd9a4215726fdb00ee803': Make MediaRouter UI more robust around route count changes
This commit is contained in:
@@ -22823,6 +22823,12 @@ package android.view {
|
||||
method public boolean onPerformDefaultAction();
|
||||
method public void onPrepareSubMenu(android.view.SubMenu);
|
||||
method public boolean overridesItemVisibility();
|
||||
method public void refreshVisibility();
|
||||
method public void setVisibilityListener(android.view.ActionProvider.VisibilityListener);
|
||||
}
|
||||
|
||||
public static abstract interface ActionProvider.VisibilityListener {
|
||||
method public abstract void onActionProviderVisibilityChanged(boolean);
|
||||
}
|
||||
|
||||
public final class Choreographer {
|
||||
|
||||
@@ -21,11 +21,14 @@ import com.android.internal.app.MediaRouteChooserDialogFragment;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.media.MediaRouter;
|
||||
import android.media.MediaRouter.RouteInfo;
|
||||
import android.util.Log;
|
||||
import android.view.ActionProvider;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class MediaRouteActionProvider extends ActionProvider {
|
||||
private static final String TAG = "MediaRouteActionProvider";
|
||||
|
||||
@@ -35,11 +38,13 @@ public class MediaRouteActionProvider extends ActionProvider {
|
||||
private MediaRouteButton mView;
|
||||
private int mRouteTypes;
|
||||
private View.OnClickListener mExtendedSettingsListener;
|
||||
private RouterCallback mCallback;
|
||||
|
||||
public MediaRouteActionProvider(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
|
||||
mCallback = new RouterCallback(this);
|
||||
|
||||
// Start with live audio by default.
|
||||
// TODO Update this when new route types are added; segment by API level
|
||||
@@ -48,7 +53,14 @@ public class MediaRouteActionProvider extends ActionProvider {
|
||||
}
|
||||
|
||||
public void setRouteTypes(int types) {
|
||||
if (mRouteTypes == types) return;
|
||||
if (mRouteTypes != 0) {
|
||||
mRouter.removeCallback(mCallback);
|
||||
}
|
||||
mRouteTypes = types;
|
||||
if (types != 0) {
|
||||
mRouter.addCallback(types, mCallback);
|
||||
}
|
||||
if (mView != null) {
|
||||
mView.setRouteTypes(mRouteTypes);
|
||||
}
|
||||
@@ -68,7 +80,6 @@ public class MediaRouteActionProvider extends ActionProvider {
|
||||
}
|
||||
mMenuItem = item;
|
||||
mView = new MediaRouteButton(mContext);
|
||||
mMenuItem.setVisible(mRouter.getRouteCount() > 1);
|
||||
mView.setRouteTypes(mRouteTypes);
|
||||
mView.setExtendedSettingsClickListener(mExtendedSettingsListener);
|
||||
return mView;
|
||||
@@ -123,4 +134,34 @@ public class MediaRouteActionProvider extends ActionProvider {
|
||||
public boolean isVisible() {
|
||||
return mRouter.getRouteCount() > 1;
|
||||
}
|
||||
|
||||
private static class RouterCallback extends MediaRouter.SimpleCallback {
|
||||
private WeakReference<MediaRouteActionProvider> mAp;
|
||||
|
||||
RouterCallback(MediaRouteActionProvider ap) {
|
||||
mAp = new WeakReference<MediaRouteActionProvider>(ap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRouteAdded(MediaRouter router, RouteInfo info) {
|
||||
final MediaRouteActionProvider ap = mAp.get();
|
||||
if (ap == null) {
|
||||
router.removeCallback(this);
|
||||
return;
|
||||
}
|
||||
|
||||
ap.refreshVisibility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRouteRemoved(MediaRouter router, RouteInfo info) {
|
||||
final MediaRouteActionProvider ap = mAp.get();
|
||||
if (ap == null) {
|
||||
router.removeCallback(this);
|
||||
return;
|
||||
}
|
||||
|
||||
ap.refreshVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* An ActionProvider defines rich menu interaction in a single component.
|
||||
@@ -55,7 +56,9 @@ import android.content.Context;
|
||||
* @see MenuItem#getActionProvider()
|
||||
*/
|
||||
public abstract class ActionProvider {
|
||||
private static final String TAG = "ActionProvider";
|
||||
private SubUiVisibilityListener mSubUiVisibilityListener;
|
||||
private VisibilityListener mVisibilityListener;
|
||||
|
||||
/**
|
||||
* Creates a new instance. ActionProvider classes should always implement a
|
||||
@@ -121,6 +124,18 @@ public abstract class ActionProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this ActionProvider is associated with an item in a menu,
|
||||
* refresh the visibility of the item based on {@link #overridesItemVisibility()} and
|
||||
* {@link #isVisible()}. If {@link #overridesItemVisibility()} returns false, this call
|
||||
* will have no effect.
|
||||
*/
|
||||
public void refreshVisibility() {
|
||||
if (mVisibilityListener != null && overridesItemVisibility()) {
|
||||
mVisibilityListener.onActionProviderVisibilityChanged(isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an optional default action.
|
||||
* <p>
|
||||
@@ -206,10 +221,35 @@ public abstract class ActionProvider {
|
||||
mSubUiVisibilityListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a listener to be notified when this ActionProvider's overridden visibility changes.
|
||||
* This should only be used by MenuItem implementations.
|
||||
*
|
||||
* @param listener listener to set
|
||||
*/
|
||||
public void setVisibilityListener(VisibilityListener listener) {
|
||||
if (mVisibilityListener != null) {
|
||||
Log.w(TAG, "setVisibilityListener: Setting a new ActionProvider.VisibilityListener " +
|
||||
"when one is already set. Are you reusing this " + getClass().getSimpleName() +
|
||||
" instance while it is still in use somewhere else?");
|
||||
}
|
||||
mVisibilityListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide Internal use only
|
||||
*/
|
||||
public interface SubUiVisibilityListener {
|
||||
public void onSubUiVisibilityChanged(boolean isVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to changes in visibility as reported by {@link ActionProvider#refreshVisibility()}.
|
||||
*
|
||||
* @see ActionProvider#overridesItemVisibility()
|
||||
* @see ActionProvider#isVisible()
|
||||
*/
|
||||
public interface VisibilityListener {
|
||||
public void onActionProviderVisibilityChanged(boolean isVisible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,9 +589,17 @@ public final class MenuItemImpl implements MenuItem {
|
||||
}
|
||||
|
||||
public MenuItem setActionProvider(ActionProvider actionProvider) {
|
||||
if (mActionProvider != null) {
|
||||
mActionProvider.setVisibilityListener(null);
|
||||
}
|
||||
mActionView = null;
|
||||
mActionProvider = actionProvider;
|
||||
mMenu.onItemsChanged(true); // Measurement can be changed
|
||||
mActionProvider.setVisibilityListener(new ActionProvider.VisibilityListener() {
|
||||
@Override public void onActionProviderVisibilityChanged(boolean isVisible) {
|
||||
mMenu.onItemVisibleChanged(MenuItemImpl.this);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* MediaRouter allows applications to control the routing of media channels
|
||||
@@ -48,7 +49,8 @@ public class MediaRouter {
|
||||
final Resources mResources;
|
||||
final IAudioService mAudioService;
|
||||
final Handler mHandler;
|
||||
final ArrayList<CallbackInfo> mCallbacks = new ArrayList<CallbackInfo>();
|
||||
final CopyOnWriteArrayList<CallbackInfo> mCallbacks =
|
||||
new CopyOnWriteArrayList<CallbackInfo>();
|
||||
|
||||
final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
|
||||
final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>();
|
||||
@@ -497,9 +499,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
static void dispatchRouteSelected(int type, RouteInfo info) {
|
||||
final int count = sStatic.mCallbacks.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CallbackInfo cbi = sStatic.mCallbacks.get(i);
|
||||
for (CallbackInfo cbi : sStatic.mCallbacks) {
|
||||
if ((cbi.type & type) != 0) {
|
||||
cbi.cb.onRouteSelected(cbi.router, type, info);
|
||||
}
|
||||
@@ -507,9 +507,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
static void dispatchRouteUnselected(int type, RouteInfo info) {
|
||||
final int count = sStatic.mCallbacks.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CallbackInfo cbi = sStatic.mCallbacks.get(i);
|
||||
for (CallbackInfo cbi : sStatic.mCallbacks) {
|
||||
if ((cbi.type & type) != 0) {
|
||||
cbi.cb.onRouteUnselected(cbi.router, type, info);
|
||||
}
|
||||
@@ -517,9 +515,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
static void dispatchRouteChanged(RouteInfo info) {
|
||||
final int count = sStatic.mCallbacks.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CallbackInfo cbi = sStatic.mCallbacks.get(i);
|
||||
for (CallbackInfo cbi : sStatic.mCallbacks) {
|
||||
if ((cbi.type & info.mSupportedTypes) != 0) {
|
||||
cbi.cb.onRouteChanged(cbi.router, info);
|
||||
}
|
||||
@@ -527,9 +523,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
static void dispatchRouteAdded(RouteInfo info) {
|
||||
final int count = sStatic.mCallbacks.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CallbackInfo cbi = sStatic.mCallbacks.get(i);
|
||||
for (CallbackInfo cbi : sStatic.mCallbacks) {
|
||||
if ((cbi.type & info.mSupportedTypes) != 0) {
|
||||
cbi.cb.onRouteAdded(cbi.router, info);
|
||||
}
|
||||
@@ -537,9 +531,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
static void dispatchRouteRemoved(RouteInfo info) {
|
||||
final int count = sStatic.mCallbacks.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CallbackInfo cbi = sStatic.mCallbacks.get(i);
|
||||
for (CallbackInfo cbi : sStatic.mCallbacks) {
|
||||
if ((cbi.type & info.mSupportedTypes) != 0) {
|
||||
cbi.cb.onRouteRemoved(cbi.router, info);
|
||||
}
|
||||
@@ -547,9 +539,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
static void dispatchRouteGrouped(RouteInfo info, RouteGroup group, int index) {
|
||||
final int count = sStatic.mCallbacks.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CallbackInfo cbi = sStatic.mCallbacks.get(i);
|
||||
for (CallbackInfo cbi : sStatic.mCallbacks) {
|
||||
if ((cbi.type & group.mSupportedTypes) != 0) {
|
||||
cbi.cb.onRouteGrouped(cbi.router, info, group, index);
|
||||
}
|
||||
@@ -557,9 +547,7 @@ public class MediaRouter {
|
||||
}
|
||||
|
||||
static void dispatchRouteUngrouped(RouteInfo info, RouteGroup group) {
|
||||
final int count = sStatic.mCallbacks.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CallbackInfo cbi = sStatic.mCallbacks.get(i);
|
||||
for (CallbackInfo cbi : sStatic.mCallbacks) {
|
||||
if ((cbi.type & group.mSupportedTypes) != 0) {
|
||||
cbi.cb.onRouteUngrouped(cbi.router, info, group);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user