165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko/*
265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Copyright (C) 2016 The Android Open Source Project
365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko *
465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * you may not use this file except in compliance with the License.
665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * You may obtain a copy of the License at
765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko *
865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko *
1065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Unless required by applicable law or agreed to in writing, software
1165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
1265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * See the License for the specific language governing permissions and
1465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * limitations under the License
1565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */
1665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
17633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkopackage com.android.tv.dvr.ui.playback;
1865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
1965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.app.Activity;
20d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.content.Intent;
2165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.graphics.Bitmap;
2265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.graphics.BitmapFactory;
2365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.media.MediaMetadata;
2465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.media.session.MediaController;
2565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.media.session.MediaSession;
2665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.media.session.PlaybackState;
2765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.media.tv.TvContract;
2865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.os.AsyncTask;
2965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.annotation.Nullable;
3065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.text.TextUtils;
3165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.R;
32944779887775bd950cf1abf348d2df461593f6abLive Channels Teamimport com.android.tv.TvSingletons;
3365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.data.ChannelDataManager;
340cc0713c1bf8027642987b750b80217569d2932aLive Channels Teamimport com.android.tv.data.api.Channel;
35633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.dvr.DvrWatchedPositionManager;
36633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.dvr.data.RecordedProgram;
3765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.util.TimeShiftUtils;
38d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.util.Utils;
390cc0713c1bf8027642987b750b80217569d2932aLive Channels Teamimport com.android.tv.util.images.ImageLoader;
4065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
41633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoclass DvrPlaybackMediaSessionHelper {
4265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private static final String TAG = "DvrPlaybackMediaSessionHelper";
4365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private static final boolean DEBUG = false;
4465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
4565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private int mNowPlayingCardWidth;
4665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private int mNowPlayingCardHeight;
4765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private int mSpeedLevel;
4865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private long mProgramDurationMs;
4965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
5065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private Activity mActivity;
5165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private DvrPlayer mDvrPlayer;
5265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private MediaSession mMediaSession;
5365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private final DvrWatchedPositionManager mDvrWatchedPositionManager;
5465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private final ChannelDataManager mChannelDataManager;
5565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
5695961816a768da387f0b5523cf4363ace2044089Nick Chalko    public DvrPlaybackMediaSessionHelper(
5795961816a768da387f0b5523cf4363ace2044089Nick Chalko            Activity activity,
5895961816a768da387f0b5523cf4363ace2044089Nick Chalko            String mediaSessionTag,
5995961816a768da387f0b5523cf4363ace2044089Nick Chalko            DvrPlayer dvrPlayer,
6095961816a768da387f0b5523cf4363ace2044089Nick Chalko            DvrPlaybackOverlayFragment overlayFragment) {
6165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mActivity = activity;
6265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrPlayer = dvrPlayer;
6365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrWatchedPositionManager =
64944779887775bd950cf1abf348d2df461593f6abLive Channels Team                TvSingletons.getSingletons(activity).getDvrWatchedPositionManager();
65944779887775bd950cf1abf348d2df461593f6abLive Channels Team        mChannelDataManager = TvSingletons.getSingletons(activity).getChannelDataManager();
6695961816a768da387f0b5523cf4363ace2044089Nick Chalko        mDvrPlayer.setCallback(
6795961816a768da387f0b5523cf4363ace2044089Nick Chalko                new DvrPlayer.DvrPlayerCallback() {
6895961816a768da387f0b5523cf4363ace2044089Nick Chalko                    @Override
6995961816a768da387f0b5523cf4363ace2044089Nick Chalko                    public void onPlaybackStateChanged(int playbackState, int playbackSpeed) {
7095961816a768da387f0b5523cf4363ace2044089Nick Chalko                        updateMediaSessionPlaybackState();
7195961816a768da387f0b5523cf4363ace2044089Nick Chalko                    }
7265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
7395961816a768da387f0b5523cf4363ace2044089Nick Chalko                    @Override
7495961816a768da387f0b5523cf4363ace2044089Nick Chalko                    public void onPlaybackPositionChanged(long positionMs) {
7595961816a768da387f0b5523cf4363ace2044089Nick Chalko                        updateMediaSessionPlaybackState();
7695961816a768da387f0b5523cf4363ace2044089Nick Chalko                        if (mDvrPlayer.isPlaybackPrepared()) {
7795961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mDvrWatchedPositionManager.setWatchedPosition(
7895961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    mDvrPlayer.getProgram().getId(), positionMs);
7995961816a768da387f0b5523cf4363ace2044089Nick Chalko                        }
8095961816a768da387f0b5523cf4363ace2044089Nick Chalko                    }
81d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
8295961816a768da387f0b5523cf4363ace2044089Nick Chalko                    @Override
8395961816a768da387f0b5523cf4363ace2044089Nick Chalko                    public void onPlaybackEnded() {
8495961816a768da387f0b5523cf4363ace2044089Nick Chalko                        // TODO: Deal with watched over recordings in DVR library
8595961816a768da387f0b5523cf4363ace2044089Nick Chalko                        RecordedProgram nextEpisode =
8695961816a768da387f0b5523cf4363ace2044089Nick Chalko                                overlayFragment.getNextEpisode(mDvrPlayer.getProgram());
8795961816a768da387f0b5523cf4363ace2044089Nick Chalko                        if (nextEpisode == null) {
8895961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mDvrPlayer.reset();
8995961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mActivity.finish();
9095961816a768da387f0b5523cf4363ace2044089Nick Chalko                        } else {
9195961816a768da387f0b5523cf4363ace2044089Nick Chalko                            Intent intent = new Intent(activity, DvrPlaybackActivity.class);
9295961816a768da387f0b5523cf4363ace2044089Nick Chalko                            intent.putExtra(
9395961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, nextEpisode.getId());
9495961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mActivity.startActivity(intent);
9595961816a768da387f0b5523cf4363ace2044089Nick Chalko                        }
9695961816a768da387f0b5523cf4363ace2044089Nick Chalko                    }
9795961816a768da387f0b5523cf4363ace2044089Nick Chalko                });
9865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        initializeMediaSession(mediaSessionTag);
9965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
10065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
10195961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Stops DVR player and release media session. */
10265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void release() {
10365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mDvrPlayer != null) {
10465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mDvrPlayer.reset();
10565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
10665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mMediaSession != null) {
10765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mMediaSession.release();
108633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mMediaSession = null;
10965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
11065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
11165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
11295961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Updates media session's playback state and speed. */
11365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void updateMediaSessionPlaybackState() {
11495961816a768da387f0b5523cf4363ace2044089Nick Chalko        mMediaSession.setPlaybackState(
11595961816a768da387f0b5523cf4363ace2044089Nick Chalko                new PlaybackState.Builder()
11695961816a768da387f0b5523cf4363ace2044089Nick Chalko                        .setState(
11795961816a768da387f0b5523cf4363ace2044089Nick Chalko                                mDvrPlayer.getPlaybackState(),
11895961816a768da387f0b5523cf4363ace2044089Nick Chalko                                mDvrPlayer.getPlaybackPosition(),
11995961816a768da387f0b5523cf4363ace2044089Nick Chalko                                mSpeedLevel)
12095961816a768da387f0b5523cf4363ace2044089Nick Chalko                        .build());
12165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
12265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
12365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    /**
12465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko     * Sets the recorded program for playback.
12565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko     *
12665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko     * @param program The recorded program to play. {@code null} to reset the DVR player.
12765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko     */
12865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void setupPlayback(RecordedProgram program, long seekPositionMs) {
12965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (program != null) {
13065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mDvrPlayer.setProgram(program, seekPositionMs);
13165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            setupMediaSession(program);
13265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
13365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mDvrPlayer.reset();
13465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mMediaSession.setActive(false);
13565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
13665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
13765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
13895961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the recorded program now playing. */
13965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public RecordedProgram getProgram() {
14065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mDvrPlayer.getProgram();
14165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
14265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
14395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Checks if the recorded program is the same as now playing one. */
14465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public boolean isCurrentProgram(RecordedProgram program) {
145d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return program != null && program.equals(getProgram());
14665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
14765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
14895961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns playback state. */
14965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public int getPlaybackState() {
15065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mDvrPlayer.getPlaybackState();
15165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
15265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
15395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the underlying DVR player. */
15465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public DvrPlayer getDvrPlayer() {
15565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mDvrPlayer;
15665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
15765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
15865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void initializeMediaSession(String mediaSessionTag) {
15965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mMediaSession = new MediaSession(mActivity, mediaSessionTag);
16095961816a768da387f0b5523cf4363ace2044089Nick Chalko        mMediaSession.setFlags(
16195961816a768da387f0b5523cf4363ace2044089Nick Chalko                MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
16295961816a768da387f0b5523cf4363ace2044089Nick Chalko                        | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
16395961816a768da387f0b5523cf4363ace2044089Nick Chalko        mNowPlayingCardWidth =
16495961816a768da387f0b5523cf4363ace2044089Nick Chalko                mActivity.getResources().getDimensionPixelSize(R.dimen.notif_card_img_max_width);
16595961816a768da387f0b5523cf4363ace2044089Nick Chalko        mNowPlayingCardHeight =
16695961816a768da387f0b5523cf4363ace2044089Nick Chalko                mActivity.getResources().getDimensionPixelSize(R.dimen.notif_card_img_height);
16765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mMediaSession.setCallback(new MediaSessionCallback());
16865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mActivity.setMediaController(
16965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                new MediaController(mActivity, mMediaSession.getSessionToken()));
17065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        updateMediaSessionPlaybackState();
17165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
17265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
17365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void setupMediaSession(RecordedProgram program) {
17465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mProgramDurationMs = program.getDurationMillis();
17565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        String cardTitleText = program.getTitle();
17665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (TextUtils.isEmpty(cardTitleText)) {
17765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            Channel channel = mChannelDataManager.getChannel(program.getChannelId());
17895961816a768da387f0b5523cf4363ace2044089Nick Chalko            cardTitleText =
17995961816a768da387f0b5523cf4363ace2044089Nick Chalko                    (channel != null)
18095961816a768da387f0b5523cf4363ace2044089Nick Chalko                            ? channel.getDisplayName()
18195961816a768da387f0b5523cf4363ace2044089Nick Chalko                            : mActivity.getString(R.string.no_program_information);
18265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
18395961816a768da387f0b5523cf4363ace2044089Nick Chalko        final MediaMetadata currentMetadata =
18495961816a768da387f0b5523cf4363ace2044089Nick Chalko                updateMetadataTextInfo(
18595961816a768da387f0b5523cf4363ace2044089Nick Chalko                        program.getId(),
18695961816a768da387f0b5523cf4363ace2044089Nick Chalko                        cardTitleText,
18795961816a768da387f0b5523cf4363ace2044089Nick Chalko                        program.getDescription(),
18895961816a768da387f0b5523cf4363ace2044089Nick Chalko                        mProgramDurationMs);
18965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        String posterArtUri = program.getPosterArtUri();
19065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (posterArtUri == null) {
19165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            posterArtUri = TvContract.buildChannelLogoUri(program.getChannelId()).toString();
19265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
193633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        updatePosterArt(program, currentMetadata, null, posterArtUri);
19465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mMediaSession.setActive(true);
19565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
19665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
19795961816a768da387f0b5523cf4363ace2044089Nick Chalko    private void updatePosterArt(
19895961816a768da387f0b5523cf4363ace2044089Nick Chalko            RecordedProgram program,
19995961816a768da387f0b5523cf4363ace2044089Nick Chalko            MediaMetadata currentMetadata,
20095961816a768da387f0b5523cf4363ace2044089Nick Chalko            @Nullable Bitmap posterArt,
20195961816a768da387f0b5523cf4363ace2044089Nick Chalko            @Nullable String posterArtUri) {
20265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (posterArt != null) {
203633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            updateMetadataImageInfo(program, currentMetadata, posterArt, 0);
20465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else if (posterArtUri != null) {
20595961816a768da387f0b5523cf4363ace2044089Nick Chalko            ImageLoader.loadBitmap(
20695961816a768da387f0b5523cf4363ace2044089Nick Chalko                    mActivity,
20795961816a768da387f0b5523cf4363ace2044089Nick Chalko                    posterArtUri,
20895961816a768da387f0b5523cf4363ace2044089Nick Chalko                    mNowPlayingCardWidth,
209633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    mNowPlayingCardHeight,
210633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    new ProgramPosterArtCallback(mActivity, program, currentMetadata));
21165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
212633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            updateMetadataImageInfo(program, currentMetadata, null, R.drawable.default_now_card);
21365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
21465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
21565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
21695961816a768da387f0b5523cf4363ace2044089Nick Chalko    private class ProgramPosterArtCallback extends ImageLoader.ImageLoaderCallback<Activity> {
217633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        private final RecordedProgram mRecordedProgram;
218633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        private final MediaMetadata mCurrentMetadata;
21965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
22095961816a768da387f0b5523cf4363ace2044089Nick Chalko        public ProgramPosterArtCallback(
22195961816a768da387f0b5523cf4363ace2044089Nick Chalko                Activity activity, RecordedProgram program, MediaMetadata metadata) {
22265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            super(activity);
22365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mRecordedProgram = program;
224633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mCurrentMetadata = metadata;
22565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
22665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
22765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
22865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void onBitmapLoaded(Activity activity, @Nullable Bitmap posterArt) {
22965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (isCurrentProgram(mRecordedProgram)) {
230633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                updatePosterArt(mRecordedProgram, mCurrentMetadata, posterArt, null);
23165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
23265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
23595961816a768da387f0b5523cf4363ace2044089Nick Chalko    private MediaMetadata updateMetadataTextInfo(
23695961816a768da387f0b5523cf4363ace2044089Nick Chalko            final long programId, final String title, final String subtitle, final long duration) {
237633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        MediaMetadata.Builder builder = new MediaMetadata.Builder();
238633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        builder.putString(MediaMetadata.METADATA_KEY_MEDIA_ID, Long.toString(programId))
239633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                .putString(MediaMetadata.METADATA_KEY_TITLE, title)
240633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                .putLong(MediaMetadata.METADATA_KEY_DURATION, duration);
241633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (subtitle != null) {
242633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            builder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, subtitle);
243633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
244633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        MediaMetadata metadata = builder.build();
245633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        mMediaSession.setMetadata(metadata);
246633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return metadata;
247633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
248633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
24995961816a768da387f0b5523cf4363ace2044089Nick Chalko    private void updateMetadataImageInfo(
25095961816a768da387f0b5523cf4363ace2044089Nick Chalko            final RecordedProgram program,
25195961816a768da387f0b5523cf4363ace2044089Nick Chalko            final MediaMetadata currentMetadata,
25295961816a768da387f0b5523cf4363ace2044089Nick Chalko            final Bitmap posterArt,
25395961816a768da387f0b5523cf4363ace2044089Nick Chalko            final int imageResId) {
254633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (mMediaSession != null && (posterArt != null || imageResId != 0)) {
255633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            MediaMetadata.Builder builder = new MediaMetadata.Builder(currentMetadata);
256633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            if (posterArt != null) {
257633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
25865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mMediaSession.setMetadata(builder.build());
259633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            } else {
260633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                new AsyncTask<Void, Void, Bitmap>() {
261633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    @Override
262633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    protected Bitmap doInBackground(Void... arg0) {
263633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                        return BitmapFactory.decodeResource(mActivity.getResources(), imageResId);
264633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    }
265633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
266633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    @Override
267633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    protected void onPostExecute(Bitmap programPosterArt) {
26895961816a768da387f0b5523cf4363ace2044089Nick Chalko                        if (mMediaSession != null
26995961816a768da387f0b5523cf4363ace2044089Nick Chalko                                && programPosterArt != null
270633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                                && isCurrentProgram(program)) {
271633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                            builder.putBitmap(MediaMetadata.METADATA_KEY_ART, programPosterArt);
272633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                            mMediaSession.setMetadata(builder.build());
273633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                        }
274633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    }
275633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                }.execute();
27665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
277633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
27865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
27965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
28065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // An event was triggered by MediaController.TransportControls and must be handled here.
28165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // Here we update the media itself to act on the event that was triggered.
28265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private class MediaSessionCallback extends MediaSession.Callback {
28365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
28465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void onPrepare() {
28565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (!mDvrPlayer.isPlaybackPrepared()) {
28665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrPlayer.prepare(true);
28765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
28865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
28965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
29065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
29165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void onPlay() {
292d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (mDvrPlayer.isPlaybackPrepared()) {
293d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                mDvrPlayer.play();
294d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
29565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
29665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
29765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
29865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void onPause() {
299d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (mDvrPlayer.isPlaybackPrepared()) {
300d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                mDvrPlayer.pause();
301d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
30265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
30365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
30465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
30565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void onFastForward() {
306d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (!mDvrPlayer.isPlaybackPrepared()) {
307d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                return;
308d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
30965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (mDvrPlayer.getPlaybackState() == PlaybackState.STATE_FAST_FORWARDING) {
31065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (mSpeedLevel < TimeShiftUtils.MAX_SPEED_LEVEL) {
31165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    mSpeedLevel++;
31265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else {
31365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    return;
31465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
31565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
31665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mSpeedLevel = 0;
31765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
31865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mDvrPlayer.fastForward(
31965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    TimeShiftUtils.getPlaybackSpeed(mSpeedLevel, mProgramDurationMs));
32065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
32165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
32265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
32365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void onRewind() {
324d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (!mDvrPlayer.isPlaybackPrepared()) {
325d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                return;
326d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
32765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (mDvrPlayer.getPlaybackState() == PlaybackState.STATE_REWINDING) {
32865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (mSpeedLevel < TimeShiftUtils.MAX_SPEED_LEVEL) {
32965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    mSpeedLevel++;
33065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else {
33165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    return;
33265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
33365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
33465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mSpeedLevel = 0;
33565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
33665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mDvrPlayer.rewind(TimeShiftUtils.getPlaybackSpeed(mSpeedLevel, mProgramDurationMs));
33765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
33865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
33965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
34065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void onSeekTo(long positionMs) {
341d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (mDvrPlayer.isPlaybackPrepared()) {
342d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                mDvrPlayer.seekTo(positionMs);
343d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
34465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
34565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
34665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko}
347