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

Commit 4f2645ae authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Android (Google) Code Review
Browse files

Merge "Add SystemAPI to override default media output switcher"

parents 34bf5558 ded4a734
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -851,6 +851,10 @@ package android.app {
    field public static final int SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY = 11; // 0xb
  }
  public static class Notification.MediaStyle extends android.app.Notification.Style {
    method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.app.Notification.MediaStyle setRemotePlaybackInfo(@NonNull CharSequence, @DrawableRes int, @Nullable android.app.PendingIntent);
  }
  public static final class Notification.TvExtender implements android.app.Notification.Extender {
    ctor public Notification.TvExtender();
    ctor public Notification.TvExtender(android.app.Notification);
+3 −0
Original line number Diff line number Diff line
@@ -300,6 +300,9 @@ package android.app {

  public class Notification implements android.os.Parcelable {
    method public boolean shouldShowForegroundImmediately();
    field public static final String EXTRA_MEDIA_REMOTE_DEVICE = "android.mediaRemoteDevice";
    field public static final String EXTRA_MEDIA_REMOTE_ICON = "android.mediaRemoteIcon";
    field public static final String EXTRA_MEDIA_REMOTE_INTENT = "android.mediaRemoteIntent";
  }

  public final class NotificationChannel implements android.os.Parcelable {
+73 −0
Original line number Diff line number Diff line
@@ -1329,6 +1329,32 @@ public class Notification implements Parcelable
     */
    public static final String EXTRA_MEDIA_SESSION = "android.mediaSession";

    /**
     * {@link #extras} key: A {@code CharSequence} name of a remote device used for a media session
     * associated with a {@link Notification.MediaStyle} notification. This will show in the media
     * controls output switcher instead of the local device name.
     * @hide
     */
    @TestApi
    public static final String EXTRA_MEDIA_REMOTE_DEVICE = "android.mediaRemoteDevice";

    /**
     * {@link #extras} key: A {@code int} resource ID for an icon that should show in the output
     * switcher of the media controls for a {@link Notification.MediaStyle} notification.
     * @hide
     */
    @TestApi
    public static final String EXTRA_MEDIA_REMOTE_ICON = "android.mediaRemoteIcon";

    /**
     * {@link #extras} key: A {@code PendingIntent} that will replace the default action for the
     * media controls output switcher chip, associated with a {@link Notification.MediaStyle}
     * notification. This should launch an activity.
     * @hide
     */
    @TestApi
    public static final String EXTRA_MEDIA_REMOTE_INTENT = "android.mediaRemoteIntent";

    /**
     * {@link #extras} key: the indices of actions to be shown in the compact view,
     * as supplied to (e.g.) {@link MediaStyle#setShowActionsInCompactView(int...)}.
@@ -8943,6 +8969,9 @@ public class Notification implements Parcelable

        private int[] mActionsToShowInCompact = null;
        private MediaSession.Token mToken;
        private CharSequence mDeviceName;
        private int mDeviceIcon;
        private PendingIntent mDeviceIntent;

        public MediaStyle() {
        }
@@ -8975,6 +9004,32 @@ public class Notification implements Parcelable
            return this;
        }

        /**
         * For media notifications associated with playback on a remote device, provide device
         * information that will replace the default values for the output switcher chip on the
         * media control, as well as an intent to use when the output switcher chip is tapped,
         * on devices where this is supported.
         *
         * @param deviceName The name of the remote device to display
         * @param iconResource Icon resource representing the device
         * @param chipIntent PendingIntent to send when the output switcher is tapped. May be
         *                   {@code null}, in which case the output switcher will be disabled.
         *                   This intent should open an Activity or it will be ignored.
         * @return MediaStyle
         *
         * @hide
         */
        @SystemApi
        @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL)
        @NonNull
        public MediaStyle setRemotePlaybackInfo(@NonNull CharSequence deviceName,
                @DrawableRes int iconResource, @Nullable PendingIntent chipIntent) {
            mDeviceName = deviceName;
            mDeviceIcon = iconResource;
            mDeviceIntent = chipIntent;
            return this;
        }

        /**
         * @hide
         */
@@ -9023,6 +9078,15 @@ public class Notification implements Parcelable
            if (mActionsToShowInCompact != null) {
                extras.putIntArray(EXTRA_COMPACT_ACTIONS, mActionsToShowInCompact);
            }
            if (mDeviceName != null) {
                extras.putCharSequence(EXTRA_MEDIA_REMOTE_DEVICE, mDeviceName);
            }
            if (mDeviceIcon > 0) {
                extras.putInt(EXTRA_MEDIA_REMOTE_ICON, mDeviceIcon);
            }
            if (mDeviceIntent != null) {
                extras.putParcelable(EXTRA_MEDIA_REMOTE_INTENT, mDeviceIntent);
            }
        }

        /**
@@ -9038,6 +9102,15 @@ public class Notification implements Parcelable
            if (extras.containsKey(EXTRA_COMPACT_ACTIONS)) {
                mActionsToShowInCompact = extras.getIntArray(EXTRA_COMPACT_ACTIONS);
            }
            if (extras.containsKey(EXTRA_MEDIA_REMOTE_DEVICE)) {
                mDeviceName = extras.getCharSequence(EXTRA_MEDIA_REMOTE_DEVICE);
            }
            if (extras.containsKey(EXTRA_MEDIA_REMOTE_ICON)) {
                mDeviceIcon = extras.getInt(EXTRA_MEDIA_REMOTE_ICON);
            }
            if (extras.containsKey(EXTRA_MEDIA_REMOTE_INTENT)) {
                mDeviceIntent = extras.getParcelable(EXTRA_MEDIA_REMOTE_INTENT);
            }
        }

        /**
+24 −12
Original line number Diff line number Diff line
@@ -371,13 +371,6 @@ public class MediaControlPanel {
        // Output switcher chip
        ViewGroup seamlessView = mMediaViewHolder.getSeamless();
        seamlessView.setVisibility(View.VISIBLE);
        seamlessView.setOnClickListener(
                v -> {
                    if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                        mMediaOutputDialogFactory.create(data.getPackageName(), true,
                                mMediaViewHolder.getSeamlessButton());
                    }
                });
        ImageView iconView = mMediaViewHolder.getSeamlessIcon();
        TextView deviceName = mMediaViewHolder.getSeamlessText();
        final MediaDeviceData device = data.getDevice();
@@ -387,8 +380,8 @@ public class MediaControlPanel {
        final float seamlessAlpha = seamlessDisabled ? DISABLED_ALPHA : 1.0f;
        mMediaViewHolder.getSeamlessButton().setAlpha(seamlessAlpha);
        seamlessView.setEnabled(!seamlessDisabled);
        String deviceString = null;
        if (device != null && device.getEnabled()) {
        CharSequence deviceString = mContext.getString(R.string.media_seamless_other_device);
        if (device != null) {
            Drawable icon = device.getIcon();
            if (icon instanceof AdaptiveIcon) {
                AdaptiveIcon aIcon = (AdaptiveIcon) icon;
@@ -399,13 +392,32 @@ public class MediaControlPanel {
            }
            deviceString = device.getName();
        } else {
            // Reset to default
            Log.w(TAG, "Device is null or not enabled: " + device + ", not binding output chip.");
            // Set to default icon
            iconView.setImageResource(R.drawable.ic_media_home_devices);
            deviceString =  mContext.getString(R.string.media_seamless_other_device);
        }
        deviceName.setText(deviceString);
        seamlessView.setContentDescription(deviceString);
        seamlessView.setOnClickListener(
                v -> {
                    if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                        return;
                    }
                    if (device.getIntent() != null) {
                        if (device.getIntent().isActivity()) {
                            mActivityStarter.startActivity(
                                    device.getIntent().getIntent(), true);
                        } else {
                            try {
                                device.getIntent().send();
                            } catch (PendingIntent.CanceledException e) {
                                Log.e(TAG, "Device pending intent was canceled");
                            }
                        }
                    } else {
                        mMediaOutputDialogFactory.create(data.getPackageName(), true,
                                mMediaViewHolder.getSeamlessButton());
                    }
            });

        // Dismiss
        mMediaViewHolder.getDismissText().setAlpha(isDismissible ? 1 : DISABLED_ALPHA);
+11 −2
Original line number Diff line number Diff line
@@ -164,8 +164,17 @@ data class MediaAction(
)

/** State of the media device. */
data class MediaDeviceData(
data class MediaDeviceData
@JvmOverloads constructor(
    /** Whether or not to enable the chip */
    val enabled: Boolean,

    /** Device icon to show in the chip */
    val icon: Drawable?,
    val name: String?

    /** Device display name */
    val name: CharSequence?,

    /** Optional intent to override the default output switcher for this control */
    val intent: PendingIntent? = null
)
Loading