// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.media.ui;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.NotificationCompat;
import android.support.v7.media.MediaRouter;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.KeyEvent;

import org.chromium.base.SysUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.blink.mojom.MediaSessionAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.notifications.NotificationConstants;
import org.chromium.content_public.common.MediaMetadata;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * A class for notifications that provide information and optional media controls for a given media.
 * Internally implements a Service for transforming notification Intents into
 * {@link MediaNotificationListener} calls for all registered listeners.
 * There's one service started for a distinct notification id.
 */
public class MediaNotificationManager {
    private static final String TAG = "MediaNotification";

    @VisibleForTesting
    static final int CUSTOM_MEDIA_SESSION_ACTION_STOP = MediaSessionAction.LAST + 1;

    // The media artwork image resolution on high-end devices.
    private static final int HIGH_IMAGE_SIZE_PX = 512;

    // The media artwork image resolution on high-end devices.
    private static final int LOW_IMAGE_SIZE_PX = 256;

    // The maximum number of actions in CompactView media notification.
    private static final int COMPACT_VIEW_ACTIONS_COUNT = 3;

    // The maximum number of actions in BigView media notification.
    private static final int BIG_VIEW_ACTIONS_COUNT = isRunningN() ? 5 : 3;

    // We're always used on the UI thread but the LOCK is required by lint when creating the
    // singleton.
    private static final Object LOCK = new Object();

    // Maps the notification ids to their corresponding notification managers.
    private static SparseArray<MediaNotificationManager> sManagers;

    private final Context mContext;

    // ListenerService running for the notification. Only non-null when showing.
    private ListenerService mService;

    private SparseArray<MediaButtonInfo> mActionToButtonInfo;

    private NotificationCompat.Builder mNotificationBuilder;

    private Bitmap mDefaultNotificationLargeIcon;

    // |mMediaNotificationInfo| should be not null if and only if the notification is showing.
    private MediaNotificationInfo mMediaNotificationInfo;

    private MediaSessionCompat mMediaSession;

    private final MediaSessionCompat.Callback mMediaSessionCallback =
            new MediaSessionCompat.Callback() {
                @Override
                public void onPlay() {
                    MediaNotificationManager.this.onPlay(
                            MediaNotificationListener.ACTION_SOURCE_MEDIA_SESSION);
                }

                @Override
                public void onPause() {
                    MediaNotificationManager.this.onPause(
                            MediaNotificationListener.ACTION_SOURCE_MEDIA_SESSION);
                }

                @Override
                public void onSkipToPrevious() {
                    MediaNotificationManager.this.onMediaSessionAction(
                            MediaSessionAction.PREVIOUS_TRACK);
                }

                @Override
                public void onSkipToNext() {
                    MediaNotificationManager.this.onMediaSessionAction(
                            MediaSessionAction.NEXT_TRACK);
                }

                @Override
                public void onFastForward() {
                    MediaNotificationManager.this.onMediaSessionAction(
                            MediaSessionAction.SEEK_FORWARD);
                }

                @Override
                public void onRewind() {
                    MediaNotificationManager.this.onMediaSessionAction(
                            MediaSessionAction.SEEK_BACKWARD);
                }
            };

    /**
     * Service used to transform intent requests triggered from the notification into
     * {@code MediaNotificationListener} callbacks. We have to create a separate derived class for
     * each type of notification since one class corresponds to one instance of the service only.
     */
    private abstract static class ListenerService extends Service {
        private static final String ACTION_PLAY =
                "MediaNotificationManager.ListenerService.PLAY";
        private static final String ACTION_PAUSE =
                "MediaNotificationManager.ListenerService.PAUSE";
        private static final String ACTION_STOP =
                "MediaNotificationManager.ListenerService.STOP";
        private static final String ACTION_SWIPE =
                "MediaNotificationManager.ListenerService.SWIPE";
        private static final String ACTION_CANCEL =
                "MediaNotificationManager.ListenerService.CANCEL";
        private static final String ACTION_PREVIOUS_TRACK =
                "MediaNotificationManager.ListenerService.PREVIOUS_TRACK";
        private static final String ACTION_NEXT_TRACK =
                "MediaNotificationManager.ListenerService.NEXT_TRACK";
        private static final String ACTION_SEEK_FORWARD =
                "MediaNotificationManager.ListenerService.SEEK_FORWARD";
        private static final String ACTION_SEEK_BACKWARD =
                "MediaNotificationmanager.ListenerService.SEEK_BACKWARD";

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }

        @Override
        public void onDestroy() {
            super.onDestroy();

            MediaNotificationManager manager = getManager();
            if (manager == null) return;

            manager.onServiceDestroyed();
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (!processIntent(intent)) stopSelf();

            return START_NOT_STICKY;
        }

        @Nullable
        protected abstract MediaNotificationManager getManager();

        private boolean processIntent(Intent intent) {
            if (intent == null) return false;

            MediaNotificationManager manager = getManager();
            if (manager == null || manager.mMediaNotificationInfo == null) return false;

            manager.onServiceStarted(this);

            processAction(intent, manager);
            return true;
        }

        private void processAction(Intent intent, MediaNotificationManager manager) {
            String action = intent.getAction();

            // Before Android L, instead of using the MediaSession callback, the system will fire
            // ACTION_MEDIA_BUTTON intents which stores the information about the key event.
            if (Intent.ACTION_MEDIA_BUTTON.equals(action)) {
                assert Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;

                KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
                if (event == null) return;
                if (event.getAction() != KeyEvent.ACTION_DOWN) return;

                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_MEDIA_PLAY:
                        manager.onPlay(
                                MediaNotificationListener.ACTION_SOURCE_MEDIA_SESSION);
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PAUSE:
                        manager.onPause(
                                MediaNotificationListener.ACTION_SOURCE_MEDIA_SESSION);
                        break;
                    case KeyEvent.KEYCODE_HEADSETHOOK:
                    case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                        if (manager.mMediaNotificationInfo.isPaused) {
                            manager.onPlay(MediaNotificationListener.ACTION_SOURCE_MEDIA_SESSION);
                        } else {
                            manager.onPause(
                                    MediaNotificationListener.ACTION_SOURCE_MEDIA_SESSION);
                        }
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                        manager.onMediaSessionAction(MediaSessionAction.PREVIOUS_TRACK);
                        break;
                    case KeyEvent.KEYCODE_MEDIA_NEXT:
                        manager.onMediaSessionAction(MediaSessionAction.NEXT_TRACK);
                        break;
                    case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
                        manager.onMediaSessionAction(MediaSessionAction.SEEK_FORWARD);
                        break;
                    case KeyEvent.KEYCODE_MEDIA_REWIND:
                        manager.onMediaSessionAction(MediaSessionAction.SEEK_BACKWARD);
                        break;
                    default:
                        break;
                }
            } else if (ACTION_STOP.equals(action)
                    || ACTION_SWIPE.equals(action)
                    || ACTION_CANCEL.equals(action)) {
                manager.onStop(
                        MediaNotificationListener.ACTION_SOURCE_MEDIA_NOTIFICATION);
                stopSelf();
            } else if (ACTION_PLAY.equals(action)) {
                manager.onPlay(MediaNotificationListener.ACTION_SOURCE_MEDIA_NOTIFICATION);
            } else if (ACTION_PAUSE.equals(action)) {
                manager.onPause(MediaNotificationListener.ACTION_SOURCE_MEDIA_NOTIFICATION);
            } else if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(action)) {
                manager.onPause(MediaNotificationListener.ACTION_SOURCE_HEADSET_UNPLUG);
            } else if (ACTION_PREVIOUS_TRACK.equals(action)) {
                manager.onMediaSessionAction(MediaSessionAction.PREVIOUS_TRACK);
            } else if (ACTION_NEXT_TRACK.equals(action)) {
                manager.onMediaSessionAction(MediaSessionAction.NEXT_TRACK);
            } else if (ACTION_SEEK_FORWARD.equals(action)) {
                manager.onMediaSessionAction(MediaSessionAction.SEEK_FORWARD);
            } else if (ACTION_SEEK_BACKWARD.equals(action)) {
                manager.onMediaSessionAction(MediaSessionAction.SEEK_BACKWARD);
            }
        }
    }

    /**
     * This class is used internally but have to be public to be able to launch the service.
     */
    public static final class PlaybackListenerService extends ListenerService {
        private static final int NOTIFICATION_ID = R.id.media_playback_notification;

        @Override
        public void onCreate() {
            super.onCreate();
            IntentFilter filter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
            registerReceiver(mAudioBecomingNoisyReceiver, filter);
        }

        @Override
        public void onDestroy() {
            unregisterReceiver(mAudioBecomingNoisyReceiver);
            super.onDestroy();
        }

        @Override
        @Nullable
        protected MediaNotificationManager getManager() {
            return MediaNotificationManager.getManager(NOTIFICATION_ID);
        }

        private BroadcastReceiver mAudioBecomingNoisyReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (!AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
                        return;
                    }

                    Intent i = new Intent(context, PlaybackListenerService.class);
                    i.setAction(intent.getAction());
                    context.startService(i);
                }
            };
    }

    /**
     * This class is used internally but have to be public to be able to launch the service.
     */
    public static final class PresentationListenerService extends ListenerService {
        private static final int NOTIFICATION_ID = R.id.presentation_notification;

        @Override
        @Nullable
        protected MediaNotificationManager getManager() {
            return MediaNotificationManager.getManager(NOTIFICATION_ID);
        }
    }

    /**
     * This class is used internally but have to be public to be able to launch the service.
     */
    public static final class CastListenerService extends ListenerService {
        private static final int NOTIFICATION_ID = R.id.remote_notification;

        @Override
        @Nullable
        protected MediaNotificationManager getManager() {
            return MediaNotificationManager.getManager(NOTIFICATION_ID);
        }
    }

    // Three classes to specify the right notification id in the intent.

    /**
     * This class is used internally but have to be public to be able to launch the service.
     */
    public static final class PlaybackMediaButtonReceiver extends MediaButtonReceiver {
        @Override
        public String getServiceClassName() {
            return PlaybackListenerService.class.getName();
        }
    }

    /**
     * This class is used internally but have to be public to be able to launch the service.
     */
    public static final class PresentationMediaButtonReceiver extends MediaButtonReceiver {
        @Override
        public String getServiceClassName() {
            return PresentationListenerService.class.getName();
        }
    }

    /**
     * This class is used internally but have to be public to be able to launch the service.
     */
    public static final class CastMediaButtonReceiver extends MediaButtonReceiver {
        @Override
        public String getServiceClassName() {
            return CastListenerService.class.getName();
        }
    }

    private Intent createIntent(Context context) {
        Intent intent = null;
        if (mMediaNotificationInfo.id == PlaybackListenerService.NOTIFICATION_ID) {
            intent = new Intent(context, PlaybackListenerService.class);
        } else if (mMediaNotificationInfo.id == PresentationListenerService.NOTIFICATION_ID) {
            intent = new Intent(context, PresentationListenerService.class);
        }  else if (mMediaNotificationInfo.id == CastListenerService.NOTIFICATION_ID) {
            intent = new Intent(context, CastListenerService.class);
        }
        return intent;
    }

    private PendingIntent createPendingIntent(String action) {
        assert mService != null;
        Intent intent = createIntent(mService).setAction(action);
        return PendingIntent.getService(mService, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    }

    private String getButtonReceiverClassName() {
        if (mMediaNotificationInfo.id == PlaybackListenerService.NOTIFICATION_ID) {
            return PlaybackMediaButtonReceiver.class.getName();
        } else if (mMediaNotificationInfo.id == PresentationListenerService.NOTIFICATION_ID) {
            return PresentationMediaButtonReceiver.class.getName();
        } else if (mMediaNotificationInfo.id == CastListenerService.NOTIFICATION_ID) {
            return CastMediaButtonReceiver.class.getName();
        }

        assert false;
        return null;
    }

    // Returns the notification group name used to prevent automatic grouping.
    private String getNotificationGroupName() {
        if (mMediaNotificationInfo.id == PlaybackListenerService.NOTIFICATION_ID) {
            return NotificationConstants.GROUP_MEDIA_PLAYBACK;
        } else if (mMediaNotificationInfo.id == PresentationListenerService.NOTIFICATION_ID) {
            return NotificationConstants.GROUP_MEDIA_PRESENTATION;
        } else if (mMediaNotificationInfo.id == CastListenerService.NOTIFICATION_ID) {
            return NotificationConstants.GROUP_MEDIA_REMOTE;
        }

        assert false;
        return null;
    }

    /**
     * Shows the notification with media controls with the specified media info. Replaces/updates
     * the current notification if already showing. Does nothing if |mediaNotificationInfo| hasn't
     * changed from the last one.
     *
     * @param applicationContext context to create the notification with
     * @param notificationInfo information to show in the notification
     */
    public static void show(Context applicationContext,
                            MediaNotificationInfo notificationInfo) {
        synchronized (LOCK) {
            if (sManagers == null) {
                sManagers = new SparseArray<MediaNotificationManager>();
            }
        }

        MediaNotificationManager manager = sManagers.get(notificationInfo.id);
        if (manager == null) {
            manager = new MediaNotificationManager(applicationContext, notificationInfo.id);
            sManagers.put(notificationInfo.id, manager);
        }

        manager.showNotification(notificationInfo);
    }

    /**
     * Hides the notification for the specified tabId and notificationId
     *
     * @param tabId the id of the tab that showed the notification or invalid tab id.
     * @param notificationId the id of the notification to hide for this tab.
     */
    public static void hide(int tabId, int notificationId) {
        MediaNotificationManager manager = getManager(notificationId);
        if (manager == null) return;

        manager.hideNotification(tabId);
    }

    /**
     * Hides notifications with the specified id for all tabs if shown.
     *
     * @param notificationId the id of the notification to hide for all tabs.
     */
    public static void clear(int notificationId) {
        MediaNotificationManager manager = getManager(notificationId);
        if (manager == null) return;

        manager.clearNotification();
        sManagers.remove(notificationId);
    }

    /**
     * Hides notifications with all known ids for all tabs if shown.
     */
    public static void clearAll() {
        if (sManagers == null) return;

        for (int i = 0; i < sManagers.size(); ++i) {
            MediaNotificationManager manager = sManagers.valueAt(i);
            manager.clearNotification();
        }
        sManagers.clear();
    }

    /**
     * Activates the Android MediaSession. This method is used to activate Android MediaSession more
     * often because some old version of Android might send events to the latest active session
     * based on when setActive(true) was called and regardless of the current playback state.
     * @param tabId the id of the tab requesting to reactivate the Android MediaSession.
     * @param notificationId the id of the notification to reactivate Android MediaSession for.
     */
    public static void activateAndroidMediaSession(int tabId, int notificationId) {
        MediaNotificationManager manager = getManager(notificationId);
        if (manager == null) return;
        manager.activateAndroidMediaSession(tabId);
    }

    /**
     * Scales |icon| to the size returned by {@link getIdealMediaImageSize()}. Returns null if
     * |icon| is null.
     * @param icon The icon to be scaled.
     */
    @Nullable
    public static Bitmap scaleIconToIdealSize(Bitmap icon) {
        if (icon == null) return null;

        int targetSize = getIdealMediaImageSize();

        Matrix m = new Matrix();
        int dominantLength = Math.max(icon.getWidth(), icon.getHeight());
        // Move the center to (0,0).
        m.postTranslate(icon.getWidth() / -2.0f, icon.getHeight() / -2.0f);
        // Scale to desired size.
        float scale = 1.0f * targetSize / dominantLength;
        m.postScale(scale, scale);
        // Move to the desired place.
        m.postTranslate(targetSize / 2.0f, targetSize / 2.0f);

        // Draw the image.
        Bitmap paddedBitmap = Bitmap.createBitmap(targetSize, targetSize, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(paddedBitmap);
        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
        canvas.drawBitmap(icon, m, paint);
        return paddedBitmap;
    }

    /**
     * @returns The ideal size of the media image.
     */
    public static int getIdealMediaImageSize() {
        if (SysUtils.isLowEndDevice()) {
            return LOW_IMAGE_SIZE_PX;
        }
        return HIGH_IMAGE_SIZE_PX;
    }

    private static MediaNotificationManager getManager(int notificationId) {
        if (sManagers == null) return null;

        return sManagers.get(notificationId);
    }

    @VisibleForTesting
    static boolean hasManagerForTesting(int notificationId) {
        return getManager(notificationId) != null;
    }

    @VisibleForTesting
    @Nullable
    static NotificationCompat.Builder getNotificationBuilderForTesting(
            int notificationId) {
        MediaNotificationManager manager = getManager(notificationId);
        if (manager == null) return null;

        return manager.mNotificationBuilder;
    }

    private static boolean isRunningN() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
    }

    /**
     * The class containing all the information for adding a button in the notification for an
     * action.
     */
    private static final class MediaButtonInfo {
        /** The resource ID of this media button icon. */
        public int iconResId;

        /** The resource ID of this media button description. */
        public int descriptionResId;

        /** The intent string to be fired when this media button is clicked. */
        public String intentString;

        public MediaButtonInfo(int buttonResId, int descriptionResId, String intentString) {
            this.iconResId = buttonResId;
            this.descriptionResId = descriptionResId;
            this.intentString = intentString;
        }
    }
    private MediaNotificationManager(Context context, int notificationId) {
        mContext = context;

        mActionToButtonInfo = new SparseArray<>();

        mActionToButtonInfo.put(MediaSessionAction.PLAY,
                new MediaButtonInfo(R.drawable.ic_media_control_play, R.string.accessibility_play,
                        ListenerService.ACTION_PLAY));
        mActionToButtonInfo.put(MediaSessionAction.PAUSE,
                new MediaButtonInfo(R.drawable.ic_media_control_pause, R.string.accessibility_pause,
                        ListenerService.ACTION_PAUSE));
        mActionToButtonInfo.put(CUSTOM_MEDIA_SESSION_ACTION_STOP,
                new MediaButtonInfo(R.drawable.ic_media_control_stop, R.string.accessibility_stop,
                        ListenerService.ACTION_STOP));
        mActionToButtonInfo.put(MediaSessionAction.PREVIOUS_TRACK,
                new MediaButtonInfo(R.drawable.ic_media_control_skip_previous,
                        R.string.accessibility_previous_track,
                        ListenerService.ACTION_PREVIOUS_TRACK));
        mActionToButtonInfo.put(MediaSessionAction.NEXT_TRACK,
                new MediaButtonInfo(R.drawable.ic_media_control_skip_next,
                        R.string.accessibility_next_track, ListenerService.ACTION_NEXT_TRACK));
        mActionToButtonInfo.put(MediaSessionAction.SEEK_FORWARD,
                new MediaButtonInfo(R.drawable.ic_media_control_fast_forward,
                        R.string.accessibility_seek_forward, ListenerService.ACTION_SEEK_FORWARD));
        mActionToButtonInfo.put(MediaSessionAction.SEEK_BACKWARD,
                new MediaButtonInfo(R.drawable.ic_media_control_fast_rewind,
                        R.string.accessibility_seek_backward,
                        ListenerService.ACTION_SEEK_BACKWARD));
    }

    /**
     * Registers the started {@link Service} with the manager and creates the notification.
     *
     * @param service the service that was started
     */
    private void onServiceStarted(ListenerService service) {
        mService = service;
        updateNotification();
    }

    /**
     * Handles the service destruction destruction.
     */
    private void onServiceDestroyed() {
        // Service already detached
        if (mService == null) return;
        // Notification is not showing
        if (mMediaNotificationInfo == null) return;

        clear(mMediaNotificationInfo.id);

        mNotificationBuilder = null;
        mService = null;
    }

    private void onPlay(int actionSource) {
        if (!mMediaNotificationInfo.isPaused) return;
        mMediaNotificationInfo.listener.onPlay(actionSource);
    }

    private void onPause(int actionSource) {
        if (mMediaNotificationInfo.isPaused) return;
        mMediaNotificationInfo.listener.onPause(actionSource);
    }

    private void onStop(int actionSource) {
        mMediaNotificationInfo.listener.onStop(actionSource);
    }

    private void onMediaSessionAction(int action) {
        mMediaNotificationInfo.listener.onMediaSessionAction(action);
    }

    private void showNotification(MediaNotificationInfo mediaNotificationInfo) {
        if (mediaNotificationInfo.equals(mMediaNotificationInfo)) return;

        mMediaNotificationInfo = mediaNotificationInfo;
        mContext.startService(createIntent(mContext));

        updateNotification();
    }

    private void clearNotification() {
        if (mMediaNotificationInfo == null) return;

        NotificationManagerCompat manager = NotificationManagerCompat.from(mContext);
        manager.cancel(mMediaNotificationInfo.id);

        if (mMediaSession != null) {
            mMediaSession.setCallback(null);
            mMediaSession.setActive(false);
            mMediaSession.release();
            mMediaSession = null;
        }
        mContext.stopService(createIntent(mContext));
        mMediaNotificationInfo = null;
    }

    private void hideNotification(int tabId) {
        if (mMediaNotificationInfo == null || tabId != mMediaNotificationInfo.tabId) return;
        clearNotification();
    }

    private MediaMetadataCompat createMetadata() {
        MediaMetadataCompat.Builder metadataBuilder = new MediaMetadataCompat.Builder();

        metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_TITLE,
                mMediaNotificationInfo.metadata.getTitle());
        metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST,
                mMediaNotificationInfo.origin);

        if (!TextUtils.isEmpty(mMediaNotificationInfo.metadata.getArtist())) {
            metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST,
                    mMediaNotificationInfo.metadata.getArtist());
        }
        if (!TextUtils.isEmpty(mMediaNotificationInfo.metadata.getAlbum())) {
            metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM,
                    mMediaNotificationInfo.metadata.getAlbum());
        }
        if (mMediaNotificationInfo.mediaSessionImage != null) {
            metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART,
                                      mMediaNotificationInfo.mediaSessionImage);
        }

        return metadataBuilder.build();
    }

    private void updateNotification() {
        if (mService == null) return;

        if (mMediaNotificationInfo == null) return;

        updateMediaSession();

        mNotificationBuilder = new NotificationCompat.Builder(mContext);
        setMediaStyleLayoutForNotificationBuilder(mNotificationBuilder);

        mNotificationBuilder.setSmallIcon(mMediaNotificationInfo.notificationSmallIcon);
        mNotificationBuilder.setAutoCancel(false);
        mNotificationBuilder.setLocalOnly(true);
        mNotificationBuilder.setGroup(getNotificationGroupName());
        mNotificationBuilder.setGroupSummary(true);

        if (mMediaNotificationInfo.supportsSwipeAway()) {
            mNotificationBuilder.setOngoing(!mMediaNotificationInfo.isPaused);
            mNotificationBuilder.setDeleteIntent(createPendingIntent(ListenerService.ACTION_SWIPE));
        }

        // The intent will currently only be null when using a custom tab.
        // TODO(avayvod) work out what we should do in this case. See https://crbug.com/585395.
        if (mMediaNotificationInfo.contentIntent != null) {
            mNotificationBuilder.setContentIntent(PendingIntent.getActivity(mContext,
                    mMediaNotificationInfo.tabId, mMediaNotificationInfo.contentIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT));
            // Set FLAG_UPDATE_CURRENT so that the intent extras is updated, otherwise the
            // intent extras will stay the same for the same tab.
        }

        mNotificationBuilder.setVisibility(
                mMediaNotificationInfo.isPrivate ? NotificationCompat.VISIBILITY_PRIVATE
                                                 : NotificationCompat.VISIBILITY_PUBLIC);

        Notification notification = mNotificationBuilder.build();

        // We keep the service as a foreground service while the media is playing. When it is not,
        // the service isn't stopped but is no longer in foreground, thus at a lower priority.
        // While the service is in foreground, the associated notification can't be swipped away.
        // Moving it back to background allows the user to remove the notification.
        if (mMediaNotificationInfo.supportsSwipeAway() && mMediaNotificationInfo.isPaused) {
            mService.stopForeground(false /* removeNotification */);

            NotificationManagerCompat manager = NotificationManagerCompat.from(mContext);
            manager.notify(mMediaNotificationInfo.id, notification);
        } else {
            mService.startForeground(mMediaNotificationInfo.id, notification);
        }
    }

    private void updateMediaSession() {
        if (!mMediaNotificationInfo.supportsPlayPause()) return;

        if (mMediaSession == null) mMediaSession = createMediaSession();

        activateAndroidMediaSession(mMediaNotificationInfo.tabId);

        try {
            // Tell the MediaRouter about the session, so that Chrome can control the volume
            // on the remote cast device (if any).
            // Pre-MR1 versions of JB do not have the complete MediaRouter APIs,
            // so getting the MediaRouter instance will throw an exception.
            MediaRouter.getInstance(mContext).setMediaSessionCompat(mMediaSession);
        } catch (NoSuchMethodError e) {
            // Do nothing. Chrome can't be casting without a MediaRouter, so there is nothing
            // to do here.
        }

        mMediaSession.setMetadata(createMetadata());

        PlaybackStateCompat.Builder playbackStateBuilder =
                new PlaybackStateCompat.Builder().setActions(computeMediaSessionActions());
        if (mMediaNotificationInfo.isPaused) {
            playbackStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED,
                    PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 1.0f);
        } else {
            // If notification only supports stop, still pretend
            playbackStateBuilder.setState(PlaybackStateCompat.STATE_PLAYING,
                    PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 1.0f);
        }
        mMediaSession.setPlaybackState(playbackStateBuilder.build());
    }

    private long computeMediaSessionActions() {
        assert mMediaNotificationInfo != null;

        long actions = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE;
        if (mMediaNotificationInfo.mediaSessionActions.contains(
                    MediaSessionAction.PREVIOUS_TRACK)) {
            actions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
        }
        if (mMediaNotificationInfo.mediaSessionActions.contains(MediaSessionAction.NEXT_TRACK)) {
            actions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
        }
        if (mMediaNotificationInfo.mediaSessionActions.contains(MediaSessionAction.SEEK_FORWARD)) {
            actions |= PlaybackStateCompat.ACTION_FAST_FORWARD;
        }
        if (mMediaNotificationInfo.mediaSessionActions.contains(MediaSessionAction.SEEK_BACKWARD)) {
            actions |= PlaybackStateCompat.ACTION_REWIND;
        }
        return actions;
    }

    private MediaSessionCompat createMediaSession() {
        MediaSessionCompat mediaSession = new MediaSessionCompat(
                mContext,
                mContext.getString(R.string.app_name),
                new ComponentName(mContext.getPackageName(),
                        getButtonReceiverClassName()),
                null);
        mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
                | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mediaSession.setCallback(mMediaSessionCallback);

        // TODO(mlamouri): the following code is to work around a bug that hopefully
        // MediaSessionCompat will handle directly. see b/24051980.
        try {
            mediaSession.setActive(true);
        } catch (NullPointerException e) {
            // Some versions of KitKat do not support AudioManager.registerMediaButtonIntent
            // with a PendingIntent. They will throw a NullPointerException, in which case
            // they should be able to activate a MediaSessionCompat with only transport
            // controls.
            mediaSession.setActive(false);
            mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
            mediaSession.setActive(true);
        }
        return mediaSession;
    }

    private void activateAndroidMediaSession(int tabId) {
        if (mMediaNotificationInfo == null) return;
        if (mMediaNotificationInfo.tabId != tabId) return;
        if (!mMediaNotificationInfo.supportsPlayPause() || mMediaNotificationInfo.isPaused) return;
        if (mMediaSession == null) return;
        mMediaSession.setActive(true);
    }

    private void setMediaStyleLayoutForNotificationBuilder(NotificationCompat.Builder builder) {
        setMediaStyleNotificationText(builder);
        if (!mMediaNotificationInfo.supportsPlayPause()) {
            builder.setLargeIcon(null);
        } else if (mMediaNotificationInfo.notificationLargeIcon != null) {
            builder.setLargeIcon(mMediaNotificationInfo.notificationLargeIcon);
        } else if (!isRunningN()) {
            if (mDefaultNotificationLargeIcon == null) {
                int resourceId = (mMediaNotificationInfo.defaultNotificationLargeIcon != 0)
                        ? mMediaNotificationInfo.defaultNotificationLargeIcon
                        : R.drawable.audio_playing_square;
                mDefaultNotificationLargeIcon = scaleIconToIdealSize(
                    BitmapFactory.decodeResource(mContext.getResources(), resourceId));
            }
            builder.setLargeIcon(mDefaultNotificationLargeIcon);
        }
        // TODO(zqzhang): It's weird that setShowWhen() don't work on K. Calling setWhen() to force
        // removing the time.
        builder.setShowWhen(false).setWhen(0);

        addNotificationButtons(builder);
    }

    private void addNotificationButtons(NotificationCompat.Builder builder) {
        Set<Integer> actions = new HashSet<>();

        // TODO(zqzhang): handle other actions when play/pause is not supported? See
        // https://crbug.com/667500
        if (mMediaNotificationInfo.supportsPlayPause()) {
            actions.addAll(mMediaNotificationInfo.mediaSessionActions);
            if (mMediaNotificationInfo.isPaused) {
                actions.remove(MediaSessionAction.PAUSE);
                actions.add(MediaSessionAction.PLAY);
            } else {
                actions.remove(MediaSessionAction.PLAY);
                actions.add(MediaSessionAction.PAUSE);
            }
        }

        if (mMediaNotificationInfo.supportsStop()) {
            actions.add(CUSTOM_MEDIA_SESSION_ACTION_STOP);
        }

        List<Integer> bigViewActions = computeBigViewActions(actions);

        for (int action : bigViewActions) {
            MediaButtonInfo buttonInfo = mActionToButtonInfo.get(action);
            builder.addAction(buttonInfo.iconResId,
                    mContext.getResources().getString(buttonInfo.descriptionResId),
                    createPendingIntent(buttonInfo.intentString));
        }

        // Only apply MediaStyle when NotificationInfo supports play/pause.
        if (mMediaNotificationInfo.supportsPlayPause()) {
            NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle();
            style.setMediaSession(mMediaSession.getSessionToken());

            int[] compactViewActionIndices = computeCompactViewActionIndices(bigViewActions);

            style.setShowActionsInCompactView(compactViewActionIndices);
            style.setCancelButtonIntent(createPendingIntent(ListenerService.ACTION_CANCEL));
            style.setShowCancelButton(true);
            builder.setStyle(style);
        }
    }

    private Bitmap drawableToBitmap(Drawable drawable) {
        if (!(drawable instanceof BitmapDrawable)) return null;

        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        return bitmapDrawable.getBitmap();
    }

    private void setMediaStyleNotificationText(NotificationCompat.Builder builder) {
        builder.setContentTitle(mMediaNotificationInfo.metadata.getTitle());
        String artistAndAlbumText = getArtistAndAlbumText(mMediaNotificationInfo.metadata);
        if (isRunningN() || !artistAndAlbumText.isEmpty()) {
            builder.setContentText(artistAndAlbumText);
            builder.setSubText(mMediaNotificationInfo.origin);
        } else {
            // Leaving ContentText empty looks bad, so move origin up to the ContentText.
            builder.setContentText(mMediaNotificationInfo.origin);
        }
    }

    private String getArtistAndAlbumText(MediaMetadata metadata) {
        String artist = (metadata.getArtist() == null) ? "" : metadata.getArtist();
        String album = (metadata.getAlbum() == null) ? "" : metadata.getAlbum();
        if (artist.isEmpty() || album.isEmpty()) {
            return artist + album;
        }
        return artist + " - " + album;
    }

    /**
     * Compute the actions to be shown in BigView media notification.
     *
     * The method assumes STOP cannot coexist with switch track actions and seeking actions. It also
     * assumes PLAY and PAUSE cannot coexist.
     *
     * TODO(zqzhang): get UX feedback to decide which actions to select when the number of actions
     * is greater than that can be displayed. See https://crbug.com/667500
     */
    private List<Integer> computeBigViewActions(Set<Integer> actions) {
        // STOP cannot coexist with switch track actions and seeking actions.
        assert !actions.contains(CUSTOM_MEDIA_SESSION_ACTION_STOP)
                || !(actions.contains(MediaSessionAction.PREVIOUS_TRACK)
                        && actions.contains(MediaSessionAction.NEXT_TRACK)
                        && actions.contains(MediaSessionAction.SEEK_BACKWARD)
                        && actions.contains(MediaSessionAction.SEEK_FORWARD));
        // PLAY and PAUSE cannot coexist.
        assert !actions.contains(MediaSessionAction.PLAY)
                || !actions.contains(MediaSessionAction.PAUSE);

        int[] actionByOrder = {
                MediaSessionAction.PREVIOUS_TRACK,
                MediaSessionAction.SEEK_BACKWARD,
                MediaSessionAction.PLAY,
                MediaSessionAction.PAUSE,
                MediaSessionAction.SEEK_FORWARD,
                MediaSessionAction.NEXT_TRACK,
                CUSTOM_MEDIA_SESSION_ACTION_STOP,
        };

        // First, select at most |BIG_VIEW_ACTIONS_COUNT| actions by priority.
        Set<Integer> selectedActions;
        if (actions.size() <= BIG_VIEW_ACTIONS_COUNT) {
            selectedActions = actions;
        } else {
            selectedActions = new HashSet<>();
            if (actions.contains(CUSTOM_MEDIA_SESSION_ACTION_STOP)) {
                selectedActions.add(CUSTOM_MEDIA_SESSION_ACTION_STOP);
            } else {
                if (actions.contains(MediaSessionAction.PLAY)) {
                    selectedActions.add(MediaSessionAction.PLAY);
                } else {
                    selectedActions.add(MediaSessionAction.PAUSE);
                }
                if (actions.contains(MediaSessionAction.PREVIOUS_TRACK)
                        && actions.contains(MediaSessionAction.NEXT_TRACK)) {
                    selectedActions.add(MediaSessionAction.PREVIOUS_TRACK);
                    selectedActions.add(MediaSessionAction.NEXT_TRACK);
                } else {
                    selectedActions.add(MediaSessionAction.SEEK_BACKWARD);
                    selectedActions.add(MediaSessionAction.SEEK_FORWARD);
                }
            }
        }

        // Second, sort the selected actions.
        List<Integer> sortedActions = new ArrayList<>();
        for (int action : actionByOrder) {
            if (selectedActions.contains(action)) sortedActions.add(action);
        }

        return sortedActions;
    }

    /**
     * Compute the actions to be shown in CompactView media notification.
     *
     * The method assumes STOP cannot coexist with switch track actions and seeking actions. It also
     * assumes PLAY and PAUSE cannot coexist.
     *
     * Actions in pairs are preferred if there are more actions than |COMPACT_VIEW_ACTIONS_COUNT|.
     */
    @VisibleForTesting
    static int[] computeCompactViewActionIndices(List<Integer> actions) {
        // STOP cannot coexist with switch track actions and seeking actions.
        assert !actions.contains(CUSTOM_MEDIA_SESSION_ACTION_STOP)
                || !(actions.contains(MediaSessionAction.PREVIOUS_TRACK)
                        && actions.contains(MediaSessionAction.NEXT_TRACK)
                        && actions.contains(MediaSessionAction.SEEK_BACKWARD)
                        && actions.contains(MediaSessionAction.SEEK_FORWARD));
        // PLAY and PAUSE cannot coexist.
        assert !actions.contains(MediaSessionAction.PLAY)
                || !actions.contains(MediaSessionAction.PAUSE);

        if (actions.size() <= COMPACT_VIEW_ACTIONS_COUNT) {
            // If the number of actions is less than |COMPACT_VIEW_ACTIONS_COUNT|, just return an
            // array of 0, 1, ..., |actions.size()|-1.
            int[] actionsArray = new int[actions.size()];
            for (int i = 0; i < actions.size(); ++i) actionsArray[i] = i;
            return actionsArray;
        }

        if (actions.contains(CUSTOM_MEDIA_SESSION_ACTION_STOP)) {
            List<Integer> compactActions = new ArrayList<>();
            if (actions.contains(MediaSessionAction.PLAY)) {
                compactActions.add(actions.indexOf(MediaSessionAction.PLAY));
            }
            compactActions.add(actions.indexOf(CUSTOM_MEDIA_SESSION_ACTION_STOP));
            return convertIntegerListToIntArray(compactActions);
        }

        int[] actionsArray = new int[COMPACT_VIEW_ACTIONS_COUNT];
        if (actions.contains(MediaSessionAction.PREVIOUS_TRACK)
                && actions.contains(MediaSessionAction.NEXT_TRACK)) {
            actionsArray[0] = actions.indexOf(MediaSessionAction.PREVIOUS_TRACK);
            if (actions.contains(MediaSessionAction.PLAY)) {
                actionsArray[1] = actions.indexOf(MediaSessionAction.PLAY);
            } else {
                actionsArray[1] = actions.indexOf(MediaSessionAction.PAUSE);
            }
            actionsArray[2] = actions.indexOf(MediaSessionAction.NEXT_TRACK);
            return actionsArray;
        }

        assert actions.contains(MediaSessionAction.SEEK_BACKWARD)
                && actions.contains(MediaSessionAction.SEEK_FORWARD);
        actionsArray[0] = actions.indexOf(MediaSessionAction.SEEK_BACKWARD);
        if (actions.contains(MediaSessionAction.PLAY)) {
            actionsArray[1] = actions.indexOf(MediaSessionAction.PLAY);
        } else {
            actionsArray[1] = actions.indexOf(MediaSessionAction.PAUSE);
        }
        actionsArray[2] = actions.indexOf(MediaSessionAction.SEEK_FORWARD);

        return actionsArray;
    }

    static int[] convertIntegerListToIntArray(List<Integer> intList) {
        int[] intArray = new int[intList.size()];
        for (int i = 0; i < intList.size(); ++i) intArray[i] = i;
        return intArray;
    }
}
