Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 706a8699 authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "Make MediaRouter UI more robust around route count changes" into jb-dev

parents d7a04de1 39d5c617
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -22822,6 +22822,12 @@ package android.view {
    method public boolean onPerformDefaultAction();
    method public boolean onPerformDefaultAction();
    method public void onPrepareSubMenu(android.view.SubMenu);
    method public void onPrepareSubMenu(android.view.SubMenu);
    method public boolean overridesItemVisibility();
    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 {
  public final class Choreographer {
+42 −1
Original line number Original line Diff line number Diff line
@@ -21,11 +21,14 @@ import com.android.internal.app.MediaRouteChooserDialogFragment;
import android.content.Context;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.ContextWrapper;
import android.media.MediaRouter;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
import android.util.Log;
import android.util.Log;
import android.view.ActionProvider;
import android.view.ActionProvider;
import android.view.MenuItem;
import android.view.MenuItem;
import android.view.View;
import android.view.View;


import java.lang.ref.WeakReference;

public class MediaRouteActionProvider extends ActionProvider {
public class MediaRouteActionProvider extends ActionProvider {
    private static final String TAG = "MediaRouteActionProvider";
    private static final String TAG = "MediaRouteActionProvider";


@@ -35,11 +38,13 @@ public class MediaRouteActionProvider extends ActionProvider {
    private MediaRouteButton mView;
    private MediaRouteButton mView;
    private int mRouteTypes;
    private int mRouteTypes;
    private View.OnClickListener mExtendedSettingsListener;
    private View.OnClickListener mExtendedSettingsListener;
    private RouterCallback mCallback;


    public MediaRouteActionProvider(Context context) {
    public MediaRouteActionProvider(Context context) {
        super(context);
        super(context);
        mContext = context;
        mContext = context;
        mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
        mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
        mCallback = new RouterCallback(this);


        // Start with live audio by default.
        // Start with live audio by default.
        // TODO Update this when new route types are added; segment by API level
        // 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) {
    public void setRouteTypes(int types) {
        if (mRouteTypes == types) return;
        if (mRouteTypes != 0) {
            mRouter.removeCallback(mCallback);
        }
        mRouteTypes = types;
        mRouteTypes = types;
        if (types != 0) {
            mRouter.addCallback(types, mCallback);
        }
        if (mView != null) {
        if (mView != null) {
            mView.setRouteTypes(mRouteTypes);
            mView.setRouteTypes(mRouteTypes);
        }
        }
@@ -68,7 +80,6 @@ public class MediaRouteActionProvider extends ActionProvider {
        }
        }
        mMenuItem = item;
        mMenuItem = item;
        mView = new MediaRouteButton(mContext);
        mView = new MediaRouteButton(mContext);
        mMenuItem.setVisible(mRouter.getRouteCount() > 1);
        mView.setRouteTypes(mRouteTypes);
        mView.setRouteTypes(mRouteTypes);
        mView.setExtendedSettingsClickListener(mExtendedSettingsListener);
        mView.setExtendedSettingsClickListener(mExtendedSettingsListener);
        return mView;
        return mView;
@@ -123,4 +134,34 @@ public class MediaRouteActionProvider extends ActionProvider {
    public boolean isVisible() {
    public boolean isVisible() {
        return mRouter.getRouteCount() > 1;
        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();
        }
    }
}
}
+40 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.view;
package android.view;


import android.content.Context;
import android.content.Context;
import android.util.Log;


/**
/**
 * An ActionProvider defines rich menu interaction in a single component.
 * An ActionProvider defines rich menu interaction in a single component.
@@ -55,7 +56,9 @@ import android.content.Context;
 * @see MenuItem#getActionProvider()
 * @see MenuItem#getActionProvider()
 */
 */
public abstract class ActionProvider {
public abstract class ActionProvider {
    private static final String TAG = "ActionProvider";
    private SubUiVisibilityListener mSubUiVisibilityListener;
    private SubUiVisibilityListener mSubUiVisibilityListener;
    private VisibilityListener mVisibilityListener;


    /**
    /**
     * Creates a new instance. ActionProvider classes should always implement a
     * Creates a new instance. ActionProvider classes should always implement a
@@ -121,6 +124,18 @@ public abstract class ActionProvider {
        return true;
        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.
     * Performs an optional default action.
     * <p>
     * <p>
@@ -206,10 +221,35 @@ public abstract class ActionProvider {
        mSubUiVisibilityListener = listener;
        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
     * @hide Internal use only
     */
     */
    public interface SubUiVisibilityListener {
    public interface SubUiVisibilityListener {
        public void onSubUiVisibilityChanged(boolean isVisible);
        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);
    }
}
}
+8 −0
Original line number Original line Diff line number Diff line
@@ -589,9 +589,17 @@ public final class MenuItemImpl implements MenuItem {
    }
    }


    public MenuItem setActionProvider(ActionProvider actionProvider) {
    public MenuItem setActionProvider(ActionProvider actionProvider) {
        if (mActionProvider != null) {
            mActionProvider.setVisibilityListener(null);
        }
        mActionView = null;
        mActionView = null;
        mActionProvider = actionProvider;
        mActionProvider = actionProvider;
        mMenu.onItemsChanged(true); // Measurement can be changed
        mMenu.onItemsChanged(true); // Measurement can be changed
        mActionProvider.setVisibilityListener(new ActionProvider.VisibilityListener() {
            @Override public void onActionProviderVisibilityChanged(boolean isVisible) {
                mMenu.onItemVisibleChanged(MenuItemImpl.this);
            }
        });
        return this;
        return this;
    }
    }


+10 −22
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;


/**
/**
 * MediaRouter allows applications to control the routing of media channels
 * MediaRouter allows applications to control the routing of media channels
@@ -48,7 +49,8 @@ public class MediaRouter {
        final Resources mResources;
        final Resources mResources;
        final IAudioService mAudioService;
        final IAudioService mAudioService;
        final Handler mHandler;
        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<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
        final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>();
        final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>();
@@ -497,9 +499,7 @@ public class MediaRouter {
    }
    }


    static void dispatchRouteSelected(int type, RouteInfo info) {
    static void dispatchRouteSelected(int type, RouteInfo info) {
        final int count = sStatic.mCallbacks.size();
        for (CallbackInfo cbi : sStatic.mCallbacks) {
        for (int i = 0; i < count; i++) {
            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
            if ((cbi.type & type) != 0) {
            if ((cbi.type & type) != 0) {
                cbi.cb.onRouteSelected(cbi.router, type, info);
                cbi.cb.onRouteSelected(cbi.router, type, info);
            }
            }
@@ -507,9 +507,7 @@ public class MediaRouter {
    }
    }


    static void dispatchRouteUnselected(int type, RouteInfo info) {
    static void dispatchRouteUnselected(int type, RouteInfo info) {
        final int count = sStatic.mCallbacks.size();
        for (CallbackInfo cbi : sStatic.mCallbacks) {
        for (int i = 0; i < count; i++) {
            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
            if ((cbi.type & type) != 0) {
            if ((cbi.type & type) != 0) {
                cbi.cb.onRouteUnselected(cbi.router, type, info);
                cbi.cb.onRouteUnselected(cbi.router, type, info);
            }
            }
@@ -517,9 +515,7 @@ public class MediaRouter {
    }
    }


    static void dispatchRouteChanged(RouteInfo info) {
    static void dispatchRouteChanged(RouteInfo info) {
        final int count = sStatic.mCallbacks.size();
        for (CallbackInfo cbi : sStatic.mCallbacks) {
        for (int i = 0; i < count; i++) {
            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
            if ((cbi.type & info.mSupportedTypes) != 0) {
            if ((cbi.type & info.mSupportedTypes) != 0) {
                cbi.cb.onRouteChanged(cbi.router, info);
                cbi.cb.onRouteChanged(cbi.router, info);
            }
            }
@@ -527,9 +523,7 @@ public class MediaRouter {
    }
    }


    static void dispatchRouteAdded(RouteInfo info) {
    static void dispatchRouteAdded(RouteInfo info) {
        final int count = sStatic.mCallbacks.size();
        for (CallbackInfo cbi : sStatic.mCallbacks) {
        for (int i = 0; i < count; i++) {
            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
            if ((cbi.type & info.mSupportedTypes) != 0) {
            if ((cbi.type & info.mSupportedTypes) != 0) {
                cbi.cb.onRouteAdded(cbi.router, info);
                cbi.cb.onRouteAdded(cbi.router, info);
            }
            }
@@ -537,9 +531,7 @@ public class MediaRouter {
    }
    }


    static void dispatchRouteRemoved(RouteInfo info) {
    static void dispatchRouteRemoved(RouteInfo info) {
        final int count = sStatic.mCallbacks.size();
        for (CallbackInfo cbi : sStatic.mCallbacks) {
        for (int i = 0; i < count; i++) {
            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
            if ((cbi.type & info.mSupportedTypes) != 0) {
            if ((cbi.type & info.mSupportedTypes) != 0) {
                cbi.cb.onRouteRemoved(cbi.router, info);
                cbi.cb.onRouteRemoved(cbi.router, info);
            }
            }
@@ -547,9 +539,7 @@ public class MediaRouter {
    }
    }


    static void dispatchRouteGrouped(RouteInfo info, RouteGroup group, int index) {
    static void dispatchRouteGrouped(RouteInfo info, RouteGroup group, int index) {
        final int count = sStatic.mCallbacks.size();
        for (CallbackInfo cbi : sStatic.mCallbacks) {
        for (int i = 0; i < count; i++) {
            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
            if ((cbi.type & group.mSupportedTypes) != 0) {
            if ((cbi.type & group.mSupportedTypes) != 0) {
                cbi.cb.onRouteGrouped(cbi.router, info, group, index);
                cbi.cb.onRouteGrouped(cbi.router, info, group, index);
            }
            }
@@ -557,9 +547,7 @@ public class MediaRouter {
    }
    }


    static void dispatchRouteUngrouped(RouteInfo info, RouteGroup group) {
    static void dispatchRouteUngrouped(RouteInfo info, RouteGroup group) {
        final int count = sStatic.mCallbacks.size();
        for (CallbackInfo cbi : sStatic.mCallbacks) {
        for (int i = 0; i < count; i++) {
            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
            if ((cbi.type & group.mSupportedTypes) != 0) {
            if ((cbi.type & group.mSupportedTypes) != 0) {
                cbi.cb.onRouteUngrouped(cbi.router, info, group);
                cbi.cb.onRouteUngrouped(cbi.router, info, group);
            }
            }