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

Commit 9471faf5 authored by Adam Powell's avatar Adam Powell Committed by Android Git Automerger
Browse files

am 8f695c52: am 706a8699: Merge "Make MediaRouter UI more robust around route...

am 8f695c52: am 706a8699: Merge "Make MediaRouter UI more robust around route count changes" into jb-dev

* commit '8f695c52':
  Make MediaRouter UI more robust around route count changes
parents 91a5f4be 8f695c52
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -22843,6 +22843,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 {
+42 −1
Original line number Diff line number Diff line
@@ -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();
        }
    }
}
+40 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -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;
    }

+10 −22
Original line number Diff line number Diff line
@@ -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);
            }