summaryrefslogtreecommitdiff
path: root/core/java/android/app/MediaRouteButton.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/app/MediaRouteButton.java')
-rw-r--r--core/java/android/app/MediaRouteButton.java321
1 files changed, 145 insertions, 176 deletions
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 7e0a27aca508..a7982f4584fc 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -17,7 +17,7 @@
package android.app;
import com.android.internal.R;
-import com.android.internal.app.MediaRouteChooserDialogFragment;
+import com.android.internal.app.MediaRouteDialogPresenter;
import android.content.Context;
import android.content.ContextWrapper;
@@ -30,7 +30,6 @@ import android.media.MediaRouter.RouteGroup;
import android.media.MediaRouter.RouteInfo;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.SoundEffectConstants;
@@ -38,17 +37,15 @@ import android.view.View;
import android.widget.Toast;
public class MediaRouteButton extends View {
- private static final String TAG = "MediaRouteButton";
+ private final MediaRouter mRouter;
+ private final MediaRouterCallback mCallback;
- private MediaRouter mRouter;
- private final MediaRouteCallback mRouterCallback = new MediaRouteCallback();
private int mRouteTypes;
private boolean mAttachedToWindow;
private Drawable mRemoteIndicator;
private boolean mRemoteActive;
- private boolean mToggleMode;
private boolean mCheatSheetEnabled;
private boolean mIsConnecting;
@@ -56,12 +53,13 @@ public class MediaRouteButton extends View {
private int mMinHeight;
private OnClickListener mExtendedSettingsClickListener;
- private MediaRouteChooserDialogFragment mDialogFragment;
+ // The checked state is used when connected to a remote route.
private static final int[] CHECKED_STATE_SET = {
R.attr.state_checked
};
+ // The activated state is used while connecting to a remote route.
private static final int[] ACTIVATED_STATE_SET = {
R.attr.state_activated
};
@@ -78,6 +76,7 @@ public class MediaRouteButton extends View {
super(context, attrs, defStyleAttr);
mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ mCallback = new MediaRouterCallback();
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0);
@@ -98,54 +97,100 @@ public class MediaRouteButton extends View {
setRouteTypes(routeTypes);
}
- private void setRemoteIndicatorDrawable(Drawable d) {
- if (mRemoteIndicator != null) {
- mRemoteIndicator.setCallback(null);
- unscheduleDrawable(mRemoteIndicator);
- }
- mRemoteIndicator = d;
- if (d != null) {
- d.setCallback(this);
- d.setState(getDrawableState());
- d.setVisible(getVisibility() == VISIBLE, false);
+ /**
+ * Gets the media route types for filtering the routes that the user can
+ * select using the media route chooser dialog.
+ *
+ * @return The route types.
+ */
+ public int getRouteTypes() {
+ return mRouteTypes;
+ }
+
+ /**
+ * Sets the types of routes that will be shown in the media route chooser dialog
+ * launched by this button.
+ *
+ * @param types The route types to match.
+ */
+ public void setRouteTypes(int types) {
+ if (mRouteTypes != types) {
+ if (mAttachedToWindow && mRouteTypes != 0) {
+ mRouter.removeCallback(mCallback);
+ }
+
+ mRouteTypes = types;
+
+ if (mAttachedToWindow && types != 0) {
+ mRouter.addCallback(types, mCallback,
+ MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
+ }
+
+ refreshRoute();
}
+ }
- refreshDrawableState();
+ public void setExtendedSettingsClickListener(OnClickListener listener) {
+ mExtendedSettingsClickListener = listener;
}
- @Override
- public boolean performClick() {
- // Send the appropriate accessibility events and call listeners
- boolean handled = super.performClick();
- if (!handled) {
- playSoundEffect(SoundEffectConstants.CLICK);
+ /**
+ * Show the route chooser or controller dialog.
+ * <p>
+ * If the default route is selected or if the currently selected route does
+ * not match the {@link #getRouteTypes route types}, then shows the route chooser dialog.
+ * Otherwise, shows the route controller dialog to offer the user
+ * a choice to disconnect from the route or perform other control actions
+ * such as setting the route's volume.
+ * </p><p>
+ * This will attach a {@link DialogFragment} to the containing Activity.
+ * </p>
+ */
+ public void showDialog() {
+ showDialogInternal();
+ }
+
+ boolean showDialogInternal() {
+ if (!mAttachedToWindow) {
+ return false;
}
- if (mToggleMode) {
- if (mRemoteActive) {
- mRouter.selectRouteInt(mRouteTypes, mRouter.getDefaultRoute());
- } else {
- final int N = mRouter.getRouteCount();
- for (int i = 0; i < N; i++) {
- final RouteInfo route = mRouter.getRouteAt(i);
- if ((route.getSupportedTypes() & mRouteTypes) != 0 &&
- route != mRouter.getDefaultRoute()) {
- mRouter.selectRouteInt(mRouteTypes, route);
- }
- }
+ DialogFragment f = MediaRouteDialogPresenter.showDialogFragment(getActivity(),
+ mRouteTypes, mExtendedSettingsClickListener);
+ return f != null;
+ }
+
+ private Activity getActivity() {
+ // Gross way of unwrapping the Activity so we can get the FragmentManager
+ Context context = getContext();
+ while (context instanceof ContextWrapper) {
+ if (context instanceof Activity) {
+ return (Activity)context;
}
- } else {
- showDialog();
+ context = ((ContextWrapper)context).getBaseContext();
}
-
- return handled;
+ throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
}
+ /**
+ * Sets whether to enable showing a toast with the content descriptor of the
+ * button when the button is long pressed.
+ */
void setCheatSheetEnabled(boolean enable) {
mCheatSheetEnabled = enable;
}
@Override
+ public boolean performClick() {
+ // Send the appropriate accessibility events and call listeners
+ boolean handled = super.performClick();
+ if (!handled) {
+ playSoundEffect(SoundEffectConstants.CLICK);
+ }
+ return showDialogInternal() || handled;
+ }
+
+ @Override
public boolean performLongClick() {
if (super.performLongClick()) {
return true;
@@ -183,85 +228,9 @@ public class MediaRouteButton extends View {
}
cheatSheet.show();
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-
return true;
}
- public void setRouteTypes(int types) {
- if (types == mRouteTypes) {
- // Already registered; nothing to do.
- return;
- }
-
- if (mAttachedToWindow && mRouteTypes != 0) {
- mRouter.removeCallback(mRouterCallback);
- }
-
- mRouteTypes = types;
-
- if (mAttachedToWindow) {
- updateRouteInfo();
- mRouter.addCallback(types, mRouterCallback);
- }
- }
-
- private void updateRouteInfo() {
- updateRemoteIndicator();
- updateRouteCount();
- }
-
- public int getRouteTypes() {
- return mRouteTypes;
- }
-
- void updateRemoteIndicator() {
- final RouteInfo selected = mRouter.getSelectedRoute(mRouteTypes);
- final boolean isRemote = selected != mRouter.getDefaultRoute();
- final boolean isConnecting = selected != null &&
- selected.getStatusCode() == RouteInfo.STATUS_CONNECTING;
-
- boolean needsRefresh = false;
- if (mRemoteActive != isRemote) {
- mRemoteActive = isRemote;
- needsRefresh = true;
- }
- if (mIsConnecting != isConnecting) {
- mIsConnecting = isConnecting;
- needsRefresh = true;
- }
-
- if (needsRefresh) {
- refreshDrawableState();
- }
- }
-
- void updateRouteCount() {
- final int N = mRouter.getRouteCount();
- int count = 0;
- boolean hasVideoRoutes = false;
- for (int i = 0; i < N; i++) {
- final RouteInfo route = mRouter.getRouteAt(i);
- final int routeTypes = route.getSupportedTypes();
- if ((routeTypes & mRouteTypes) != 0) {
- if (route instanceof RouteGroup) {
- count += ((RouteGroup) route).getRouteCount();
- } else {
- count++;
- }
- if ((routeTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0) {
- hasVideoRoutes = true;
- }
- }
- }
-
- setEnabled(count != 0);
-
- // Only allow toggling if we have more than just user routes.
- // Don't toggle if we support video routes, we may have to let the dialog scan.
- mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0 &&
- !hasVideoRoutes;
- }
-
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
@@ -289,6 +258,21 @@ public class MediaRouteButton extends View {
}
}
+ private void setRemoteIndicatorDrawable(Drawable d) {
+ if (mRemoteIndicator != null) {
+ mRemoteIndicator.setCallback(null);
+ unscheduleDrawable(mRemoteIndicator);
+ }
+ mRemoteIndicator = d;
+ if (d != null) {
+ d.setCallback(this);
+ d.setState(getDrawableState());
+ d.setVisible(getVisibility() == VISIBLE, false);
+ }
+
+ refreshDrawableState();
+ }
+
@Override
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || who == mRemoteIndicator;
@@ -297,12 +281,16 @@ public class MediaRouteButton extends View {
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
- if (mRemoteIndicator != null) mRemoteIndicator.jumpToCurrentState();
+
+ if (mRemoteIndicator != null) {
+ mRemoteIndicator.jumpToCurrentState();
+ }
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
+
if (mRemoteIndicator != null) {
mRemoteIndicator.setVisible(getVisibility() == VISIBLE, false);
}
@@ -311,19 +299,22 @@ public class MediaRouteButton extends View {
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
+
mAttachedToWindow = true;
if (mRouteTypes != 0) {
- mRouter.addCallback(mRouteTypes, mRouterCallback);
- updateRouteInfo();
+ mRouter.addCallback(mRouteTypes, mCallback,
+ MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
}
+ refreshRoute();
}
@Override
public void onDetachedFromWindow() {
+ mAttachedToWindow = false;
if (mRouteTypes != 0) {
- mRouter.removeCallback(mRouterCallback);
+ mRouter.removeCallback(mCallback);
}
- mAttachedToWindow = false;
+
super.onDetachedFromWindow();
}
@@ -386,93 +377,71 @@ public class MediaRouteButton extends View {
final int drawLeft = left + (right - left - drawWidth) / 2;
final int drawTop = top + (bottom - top - drawHeight) / 2;
- mRemoteIndicator.setBounds(drawLeft, drawTop, drawLeft + drawWidth, drawTop + drawHeight);
+ mRemoteIndicator.setBounds(drawLeft, drawTop,
+ drawLeft + drawWidth, drawTop + drawHeight);
mRemoteIndicator.draw(canvas);
}
- public void setExtendedSettingsClickListener(OnClickListener listener) {
- mExtendedSettingsClickListener = listener;
- if (mDialogFragment != null) {
- mDialogFragment.setExtendedSettingsClickListener(listener);
- }
- }
-
- /**
- * Asynchronously show the route chooser dialog.
- * This will attach a {@link DialogFragment} to the containing Activity.
- */
- public void showDialog() {
- final FragmentManager fm = getActivity().getFragmentManager();
- if (mDialogFragment == null) {
- // See if one is already attached to this activity.
- mDialogFragment = (MediaRouteChooserDialogFragment) fm.findFragmentByTag(
- MediaRouteChooserDialogFragment.FRAGMENT_TAG);
- }
- if (mDialogFragment != null) {
- Log.w(TAG, "showDialog(): Already showing!");
- return;
- }
+ private void refreshRoute() {
+ if (mAttachedToWindow) {
+ final MediaRouter.RouteInfo route = mRouter.getSelectedRoute();
+ final boolean isRemote = !route.isDefault() && route.matchesTypes(mRouteTypes);
+ final boolean isConnecting = isRemote && route.isConnecting();
+
+ boolean needsRefresh = false;
+ if (mRemoteActive != isRemote) {
+ mRemoteActive = isRemote;
+ needsRefresh = true;
+ }
+ if (mIsConnecting != isConnecting) {
+ mIsConnecting = isConnecting;
+ needsRefresh = true;
+ }
- mDialogFragment = new MediaRouteChooserDialogFragment();
- mDialogFragment.setExtendedSettingsClickListener(mExtendedSettingsClickListener);
- mDialogFragment.setLauncherListener(new MediaRouteChooserDialogFragment.LauncherListener() {
- @Override
- public void onDetached(MediaRouteChooserDialogFragment detachedFragment) {
- mDialogFragment = null;
+ if (needsRefresh) {
+ refreshDrawableState();
}
- });
- mDialogFragment.setRouteTypes(mRouteTypes);
- mDialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG);
- }
- private Activity getActivity() {
- // Gross way of unwrapping the Activity so we can get the FragmentManager
- Context context = getContext();
- while (context instanceof ContextWrapper && !(context instanceof Activity)) {
- context = ((ContextWrapper) context).getBaseContext();
+ setEnabled(mRouter.isRouteAvailable(mRouteTypes,
+ MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE));
}
- if (!(context instanceof Activity)) {
- throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
- }
-
- return (Activity) context;
}
- private class MediaRouteCallback extends MediaRouter.SimpleCallback {
+ private final class MediaRouterCallback extends MediaRouter.SimpleCallback {
@Override
- public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
- updateRemoteIndicator();
+ public void onRouteAdded(MediaRouter router, RouteInfo info) {
+ refreshRoute();
}
@Override
- public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
- updateRemoteIndicator();
+ public void onRouteRemoved(MediaRouter router, RouteInfo info) {
+ refreshRoute();
}
@Override
public void onRouteChanged(MediaRouter router, RouteInfo info) {
- updateRemoteIndicator();
+ refreshRoute();
}
@Override
- public void onRouteAdded(MediaRouter router, RouteInfo info) {
- updateRouteCount();
+ public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
+ refreshRoute();
}
@Override
- public void onRouteRemoved(MediaRouter router, RouteInfo info) {
- updateRouteCount();
+ public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
+ refreshRoute();
}
@Override
public void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group,
int index) {
- updateRouteCount();
+ refreshRoute();
}
@Override
public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
- updateRouteCount();
+ refreshRoute();
}
}
}