147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang/*
247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * Copyright 2018 The Android Open Source Project
347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang *
447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * Licensed under the Apache License, Version 2.0 (the "License");
547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * you may not use this file except in compliance with the License.
647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * You may obtain a copy of the License at
747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang *
847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang *      http://www.apache.org/licenses/LICENSE-2.0
947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang *
1047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * Unless required by applicable law or agreed to in writing, software
1147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * distributed under the License is distributed on an "AS IS" BASIS,
1247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * See the License for the specific language governing permissions and
1447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * limitations under the License.
1547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang */
1647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
1747740510281e2d2c5a535c31d52ac970d32951c6Insun Kangpackage androidx.media.widget;
1847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
1947740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
2047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
2147740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.content.Context;
2247740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.content.pm.ActivityInfo;
2347740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.content.res.Resources;
2447740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.graphics.Bitmap;
2547740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.graphics.BitmapFactory;
2647740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.graphics.Point;
2747740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.graphics.drawable.BitmapDrawable;
2847740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.graphics.drawable.Drawable;
2947740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.media.AudioAttributes;
3047740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.media.AudioFocusRequest;
3147740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.media.AudioManager;
3247740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.media.MediaMetadataRetriever;
3347740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.media.MediaPlayer;
3447740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.media.PlaybackParams;
3547740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.net.Uri;
3647740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.os.Bundle;
3747740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.os.ResultReceiver;
3847740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.support.v4.media.MediaMetadataCompat;
3947740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.support.v4.media.session.MediaControllerCompat;
4047740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.support.v4.media.session.MediaControllerCompat.PlaybackInfo;
4147740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.support.v4.media.session.MediaSessionCompat;
4247740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.support.v4.media.session.PlaybackStateCompat;
4347740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.util.AttributeSet;
4447740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.util.DisplayMetrics;
4547740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.util.Log;
4647740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.util.Pair;
4747740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.view.LayoutInflater;
4847740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.view.MotionEvent;
4947740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.view.View;
5047740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.view.ViewGroup.LayoutParams;
5147740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.view.WindowManager;
5247740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.view.accessibility.AccessibilityManager;
5347740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.widget.ImageView;
5447740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport android.widget.TextView;
5547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
5647740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.annotation.NonNull;
5747740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.annotation.Nullable;
5847740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.annotation.RequiresApi;
5947740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.annotation.RestrictTo;
601ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport androidx.media.AudioAttributesCompat;
6147740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.media.DataSourceDesc;
6247740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.media.MediaItem2;
6347740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.media.MediaMetadata2;
6447740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.media.SessionToken2;
6547740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.mediarouter.media.MediaControlIntent;
6647740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.mediarouter.media.MediaItemStatus;
6747740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.mediarouter.media.MediaRouteSelector;
6847740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.mediarouter.media.MediaRouter;
6947740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport androidx.palette.graphics.Palette;
7047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
7147740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport java.io.IOException;
7247740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport java.util.ArrayList;
7347740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport java.util.List;
7447740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport java.util.Map;
7547740510281e2d2c5a535c31d52ac970d32951c6Insun Kangimport java.util.concurrent.Executor;
7647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
7747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang/**
7847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang * Base implementation of VideoView2.
7947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang */
8047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang@RequiresApi(21) // TODO correct minSdk API use incompatibilities and remove before release.
8147740510281e2d2c5a535c31d52ac970d32951c6Insun Kangclass VideoView2ImplBaseWithMp1
8247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        implements VideoView2Impl, VideoViewInterfaceWithMp1.SurfaceListener {
8347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final String TAG = "VideoView2ImplBase_1";
8447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
8547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final long DEFAULT_SHOW_CONTROLLER_INTERVAL_MS = 2000;
8647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
8747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int STATE_ERROR = -1;
8847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int STATE_IDLE = 0;
8947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int STATE_PREPARING = 1;
9047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int STATE_PREPARED = 2;
9147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int STATE_PLAYING = 3;
9247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int STATE_PAUSED = 4;
9347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int STATE_PLAYBACK_COMPLETED = 5;
9447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
9547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int INVALID_TRACK_INDEX = -1;
9647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final float INVALID_SPEED = 0f;
9747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
9847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int SIZE_TYPE_EMBEDDED = 0;
9947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int SIZE_TYPE_FULL = 1;
10047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private static final int SIZE_TYPE_MINIMAL = 2;
10147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
10247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private AccessibilityManager mAccessibilityManager;
10347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private AudioManager mAudioManager;
10447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private AudioAttributes mAudioAttributes;
10547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
10647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private boolean mAudioFocused = false;
10747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
10847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private Pair<Executor, VideoView2.OnCustomActionListener> mCustomActionListenerRecord;
10947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private VideoView2.OnViewTypeChangedListener mViewTypeChangedListener;
11047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
11147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private VideoViewInterfaceWithMp1 mCurrentView;
11247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private VideoTextureViewWithMp1 mTextureView;
11347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private VideoSurfaceViewWithMp1 mSurfaceView;
11447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
11547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected MediaPlayer mMediaPlayer;
11647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private DataSourceDesc mDsd;
11747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private Uri mUri;
11847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private Map<String, String> mHeaders;
11947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaControlView2 mMediaControlView;
12047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected MediaSessionCompat mMediaSession;
12147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaControllerCompat mMediaController;
12247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaMetadata2 mMediaMetadata;
12347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaMetadataRetriever mRetriever;
12447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private boolean mNeedUpdateMediaType;
12547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private Bundle mMediaTypeData;
12647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private String mTitle;
12747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
12847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private WindowManager mManager;
12947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private Resources mResources;
13047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private View mMusicView;
13147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private Drawable mMusicAlbumDrawable;
13247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private String mMusicTitleText;
13347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private String mMusicArtistText;
13447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mPrevWidth;
13547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mPrevHeight;
13647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mDominantColor;
13747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mSizeType;
13847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
13947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private PlaybackStateCompat.Builder mStateBuilder;
14047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private List<PlaybackStateCompat.CustomAction> mCustomActionList;
14147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
14247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mTargetState = STATE_IDLE;
14347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mCurrentState = STATE_IDLE;
14447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mCurrentBufferPercentage;
14547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private long mSeekWhenPrepared;  // recording the seek position while preparing
14647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
14747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mVideoWidth;
14847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mVideoHeight;
14947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
15047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected ArrayList<Integer> mVideoTrackIndices;
15147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected ArrayList<Integer> mAudioTrackIndices;
15247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
15347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    // selected video/audio/subtitle track index as MediaPlayer returns
15447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected int mSelectedVideoTrackIndex;
15547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected int mSelectedAudioTrackIndex;
15647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
15747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private float mSpeed;
15847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private float mFallbackSpeed;  // keep the original speed before 'pause' is called.
15947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private float mVolumeLevelFloat;
16047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int mVolumeLevel;
16147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected VideoView2 mInstance;
16247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
16347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private long mShowControllerIntervalMs;
16447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
16547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaRouter mMediaRouter;
16647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaRouteSelector mRouteSelector;
16747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaRouter.RouteInfo mRoute;
16847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private RoutePlayer mRoutePlayer;
16947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
17047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private final MediaRouter.Callback mRouterCallback = new MediaRouter.Callback() {
17147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
17247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
17347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
17447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                // Stop local playback (if necessary)
17547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                resetPlayer();
17647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoute = route;
17747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoutePlayer = new RoutePlayer(mInstance.getContext(), route);
17847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoutePlayer.setPlayerEventCallback(new RoutePlayer.PlayerEventCallback() {
17947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    @Override
18047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    public void onPlayerStateChanged(MediaItemStatus itemStatus) {
18147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        PlaybackStateCompat.Builder psBuilder = new PlaybackStateCompat.Builder();
18247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        psBuilder.setActions(RoutePlayer.PLAYBACK_ACTIONS);
18347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        long position = itemStatus.getContentPosition();
18447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        switch (itemStatus.getPlaybackState()) {
18547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            case MediaItemStatus.PLAYBACK_STATE_PENDING:
18647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                psBuilder.setState(PlaybackStateCompat.STATE_NONE, position, 0);
18747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                mCurrentState = STATE_IDLE;
18847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                break;
18947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            case MediaItemStatus.PLAYBACK_STATE_PLAYING:
19047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                psBuilder.setState(PlaybackStateCompat.STATE_PLAYING, position, 1);
19147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                mCurrentState = STATE_PLAYING;
19247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                break;
19347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            case MediaItemStatus.PLAYBACK_STATE_PAUSED:
19447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                psBuilder.setState(PlaybackStateCompat.STATE_PAUSED, position, 0);
19547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                mCurrentState = STATE_PAUSED;
19647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                break;
19747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            case MediaItemStatus.PLAYBACK_STATE_BUFFERING:
19847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                psBuilder.setState(
19947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                        PlaybackStateCompat.STATE_BUFFERING, position, 0);
20047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                mCurrentState = STATE_PAUSED;
20147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                break;
20247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            case MediaItemStatus.PLAYBACK_STATE_FINISHED:
20347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                psBuilder.setState(PlaybackStateCompat.STATE_STOPPED, position, 0);
20447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                mCurrentState = STATE_PLAYBACK_COMPLETED;
20547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                break;
20647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        }
20747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
20847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        PlaybackStateCompat pbState = psBuilder.build();
20947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaSession.setPlaybackState(pbState);
21047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
21147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        MediaMetadataCompat.Builder mmBuilder = new MediaMetadataCompat.Builder();
21247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mmBuilder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION,
21347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                itemStatus.getContentDuration());
21447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaSession.setMetadata(mmBuilder.build());
21547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
21647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                });
21747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                // Start remote playback (if necessary)
21847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                // TODO: b/77556429
21947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoutePlayer.openVideo(mUri);
22047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
22147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
22247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
22347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
22447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route, int reason) {
22547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mRoute != null && mRoutePlayer != null) {
22647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoutePlayer.release();
22747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoutePlayer = null;
22847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
22947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mRoute == route) {
23047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoute = null;
23147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
23247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) {
23347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                // TODO: Resume local playback  (if necessary)
23447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                // TODO: b/77556429
23547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                openVideo(mUri, mHeaders);
23647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
23747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
23847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
23947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
24047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
24147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void initialize(
24247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            VideoView2 instance, Context context,
24347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            @Nullable AttributeSet attrs, int defStyleAttr) {
24447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance = instance;
24547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
24647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mVideoWidth = 0;
24747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mVideoHeight = 0;
24847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mSpeed = 1.0f;
24947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mFallbackSpeed = mSpeed;
25047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mShowControllerIntervalMs = DEFAULT_SHOW_CONTROLLER_INTERVAL_MS;
25147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
25247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
25347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Context.ACCESSIBILITY_SERVICE);
25447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
25547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
2561ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang        mAudioAttributes = new AudioAttributes.Builder()
2571ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang                .setUsage(AudioAttributes.USAGE_MEDIA)
25847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE).build();
25947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
26047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.setFocusable(true);
26147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.setFocusableInTouchMode(true);
26247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.requestFocus();
26347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
26447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mTextureView = new VideoTextureViewWithMp1(context);
26547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mSurfaceView = new VideoSurfaceViewWithMp1(context);
26647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
26747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                LayoutParams.MATCH_PARENT);
26847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mTextureView.setLayoutParams(params);
26947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mSurfaceView.setLayoutParams(params);
27047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mTextureView.setSurfaceListener(this);
27147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mSurfaceView.setSurfaceListener(this);
27247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
27347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.addView(mTextureView);
27447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.addView(mSurfaceView);
27547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
27647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        boolean enableControlView = (attrs == null) || attrs.getAttributeBooleanValue(
27747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                "http://schemas.android.com/apk/res/android",
27847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                "enableControlView", true);
27947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (enableControlView) {
28047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaControlView = new MediaControlView2(context);
28147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
28247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
28347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Choose surface view by default
28447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        int viewType = (attrs == null) ? VideoView2.VIEW_TYPE_SURFACEVIEW
28547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                : attrs.getAttributeIntValue(
28647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                "http://schemas.android.com/apk/res/android",
28747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                "viewType", VideoView2.VIEW_TYPE_SURFACEVIEW);
28847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
28947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "viewType attribute is surfaceView.");
29047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTextureView.setVisibility(View.GONE);
29147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mSurfaceView.setVisibility(View.VISIBLE);
29247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentView = mSurfaceView;
29347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
29447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "viewType attribute is textureView.");
29547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTextureView.setVisibility(View.VISIBLE);
29647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mSurfaceView.setVisibility(View.GONE);
29747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentView = mTextureView;
29847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
29947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
30047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        MediaRouteSelector.Builder builder = new MediaRouteSelector.Builder();
30147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        builder.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
30247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO);
30347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO);
30447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mRouteSelector = builder.build();
30547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
30647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
30747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
30847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets MediaControlView2 instance. It will replace the previously assigned MediaControlView2
30947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * instance if any.
31047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
31147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param mediaControlView a media control view2 instance.
31247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param intervalMs a time interval in milliseconds until VideoView2 hides MediaControlView2.
31347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
31447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
31547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setMediaControlView2(MediaControlView2 mediaControlView, long intervalMs) {
31647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaControlView = mediaControlView;
31747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mShowControllerIntervalMs = intervalMs;
31847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaControlView.setRouteSelector(mRouteSelector);
31947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
32047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mInstance.isAttachedToWindow()) {
32147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            attachMediaControlView();
32247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
32347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
32447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
32547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
32647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Returns MediaControlView2 instance which is currently attached to VideoView2 by default or by
32747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * {@link #setMediaControlView2} method.
32847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
32947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
33047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public MediaControlView2 getMediaControlView2() {
33147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mMediaControlView;
33247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
33347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
33447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
33547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets MediaMetadata2 instance. It will replace the previously assigned MediaMetadata2 instance
33647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * if any.
33747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
33847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param metadata a MediaMetadata2 instance.
33947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
34047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
34147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
34247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
34347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setMediaMetadata(MediaMetadata2 metadata) {
34447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang      //mProvider.setMediaMetadata_impl(metadata);
34547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
34647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
34747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
34847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Returns MediaMetadata2 instance which is retrieved from MediaPlayer inside VideoView2 by
34947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * default or by {@link #setMediaMetadata} method.
35047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
35147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
35247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
35347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
35447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public MediaMetadata2 getMediaMetadata() {
35547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mMediaMetadata;
35647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
35747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
35847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
35947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Returns MediaController instance which is connected with MediaSession that VideoView2 is
36047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * using. This method should be called when VideoView2 is attached to window, or it throws
36147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * IllegalStateException, since internal MediaSession instance is not available until
36247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * this view is attached to window. Please check {@link View#isAttachedToWindow}
36347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * before calling this method.
36447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
36547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @throws IllegalStateException if interal MediaSession is not created yet.
36647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide  TODO: remove
36747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
36847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
36947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
37047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public MediaControllerCompat getMediaController() {
37147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaSession == null) {
37247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            throw new IllegalStateException("MediaSession instance is not available.");
37347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
37447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mMediaController;
37547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
37647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
37747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
37847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Returns {@link SessionToken2} so that developers create their own
37947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * {@link androidx.media.MediaController2} instance. This method should be called when
38047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * VideoView2 is attached to window, or it throws IllegalStateException.
38147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
38247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @throws IllegalStateException if interal MediaSession is not created yet.
38347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
38447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
38547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
38647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
38747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public SessionToken2 getMediaSessionToken() {
38847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        //return mProvider.getMediaSessionToken_impl();
38947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return null;
39047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
39147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
39247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
39347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Shows or hides closed caption or subtitles if there is any.
39447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * The first subtitle track will be chosen if there multiple subtitle tracks exist.
39547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Default behavior of VideoView2 is not showing subtitle.
39647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param enable shows closed caption or subtitles if this value is true, or hides.
39747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
39847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
39947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setSubtitleEnabled(boolean enable) {
40047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // No-op on API < 28
40147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
40247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
40347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
40447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Returns true if showing subtitle feature is enabled or returns false.
40547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Although there is no subtitle track or closed caption, it can return true, if the feature
40647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * has been enabled by {@link #setSubtitleEnabled}.
40747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
40847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
40947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public boolean isSubtitleEnabled() {
41047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Not supported on API < 28
41147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return false;
41247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
41347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
41447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
41547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets playback speed.
41647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
41747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * It is expressed as a multiplicative factor, where normal speed is 1.0f. If it is less than
41847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * or equal to zero, it will be just ignored and nothing will be changed. If it exceeds the
41947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * maximum speed that internal engine supports, system will determine best handling or it will
42047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * be reset to the normal speed 1.0f.
42147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param speed the playback speed. It should be positive.
42247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
42347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
42447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setSpeed(float speed) {
42547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (speed <= 0.0f) {
42647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.e(TAG, "Unsupported speed (" + speed + ") is ignored.");
42747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return;
42847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
42947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mSpeed = speed;
43047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
43147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            applySpeed();
43247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
43347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        updatePlaybackState();
43447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
43547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
43647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
43747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Returns playback speed.
43847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
43947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * It returns the same value that has been set by {@link #setSpeed}, if it was available value.
44047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * If {@link #setSpeed} has not been called before, then the normal speed 1.0f will be returned.
44147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
44247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
44347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public float getSpeed() {
44447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mSpeed;
44547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
44647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
44747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
44847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets which type of audio focus will be requested during the playback, or configures playback
44947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * to not request audio focus. Valid values for focus requests are
45047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
45147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
45247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
45347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
45447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * requested when playback starts. You can for instance use this when playing a silent animation
45547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * through this class, and you don't want to affect other audio applications playing in the
45647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * background.
45747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
45847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param focusGain the type of audio focus gain that will be requested, or
45947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                  {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during
46047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                  playback.
46147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
46247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
46347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setAudioFocusRequest(int focusGain) {
46447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (focusGain != AudioManager.AUDIOFOCUS_NONE
46547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && focusGain != AudioManager.AUDIOFOCUS_GAIN
46647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
46747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
46847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
46947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            throw new IllegalArgumentException("Illegal audio focus type " + focusGain);
47047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
47147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mAudioFocusType = focusGain;
47247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
47347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
47447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
4751ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang     * Sets the {@link AudioAttributesCompat} to be used during the playback of the video.
47647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
4771ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang     * @param attributes non-null <code>AudioAttributesCompat</code>.
47847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
47947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
4801ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang    public void setAudioAttributes(@NonNull AudioAttributesCompat attributes) {
48147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (attributes == null) {
4821ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang            throw new IllegalArgumentException("Illegal null AudioAttributesCompat");
48347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
4841ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang        mAudioAttributes = (AudioAttributes) attributes.unwrap();
48547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
48647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
48747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
48847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets video path.
48947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
49047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param path the path of the video.
49147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
49247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
49347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
49447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
49547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
49647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setVideoPath(String path) {
49747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        setVideoUri(Uri.parse(path));
49847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
49947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
50047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
50147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets video URI.
50247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
50347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param uri the URI of the video.
50447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
50547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
50647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
50747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
50847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
50947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setVideoUri(Uri uri) {
51047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        setVideoUri(uri, null);
51147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
51247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
51347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
51447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets video URI using specific headers.
51547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
51647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param uri     the URI of the video.
51747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param headers the headers for the URI request.
51847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                Note that the cross domain redirection is allowed by default, but that can be
51947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                changed with key/value pairs through the headers parameter with
52047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
52147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                to disallow or allow cross domain redirection.
52247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
52347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
52447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setVideoUri(Uri uri, @Nullable Map<String, String> headers) {
52547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mSeekWhenPrepared = 0;
52647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        openVideo(uri, headers);
52747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
52847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
52947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
53047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets {@link MediaItem2} object to render using VideoView2. Alternative way to set media
53147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * object to VideoView2 is {@link #setDataSource}.
53247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param mediaItem the MediaItem2 to play
53347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @see #setDataSource
53447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
53547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
53647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
53747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
53847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
53947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setMediaItem(@NonNull MediaItem2 mediaItem) {
54047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
54147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
54247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
54347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets {@link DataSourceDesc} object to render using VideoView2.
54447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param dataSource the {@link DataSourceDesc} object to play.
54547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @see #setMediaItem
54647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
54747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
54847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
54947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
55047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setDataSource(@NonNull DataSourceDesc dataSource) {
55147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
55247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
55347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
55447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Selects which view will be used to render video between SurfacView and TextureView.
55547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
55647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param viewType the view type to render video
55747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * <ul>
55847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * <li>{@link #VideoView2.VIEW_TYPE_SURFACEVIEW}
55947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * <li>{@link #VideoView2.VIEW_TYPE_TEXTUREVIEW}
56047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * </ul>
56147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
56247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
56347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setViewType(@VideoView2.ViewType int viewType) {
56447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (viewType == mCurrentView.getViewType()) {
56547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return;
56647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
56747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        VideoViewInterfaceWithMp1 targetView;
56847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (viewType == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
56947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "switching to TextureView");
57047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            targetView = mTextureView;
57147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else if (viewType == VideoView2.VIEW_TYPE_SURFACEVIEW) {
57247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "switching to SurfaceView");
57347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            targetView = mSurfaceView;
57447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else {
57547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            throw new IllegalArgumentException("Unknown view type: " + viewType);
57647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
57747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        ((View) targetView).setVisibility(View.VISIBLE);
57847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        targetView.takeOver(mCurrentView);
57947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.requestLayout();
58047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
58147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
58247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
58347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Returns view type.
58447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
58547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @return view type. See {@see setViewType}.
58647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
58747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
58847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @VideoView2.ViewType
58947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public int getViewType() {
59047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mCurrentView.getViewType();
59147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
59247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
59347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
59447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Sets custom actions which will be shown as custom buttons in {@link MediaControlView2}.
59547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *
59647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param actionList A list of {@link PlaybackStateCompat.CustomAction}. The return value of
59747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                   {@link PlaybackStateCompat.CustomAction#getIcon()} will be used to draw
59847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     *                   buttons in {@link MediaControlView2}.
59947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param executor executor to run callbacks on.
60047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param listener A listener to be called when a custom button is clicked.
60147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
60247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
60347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
60447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
60547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setCustomActions(List<PlaybackStateCompat.CustomAction> actionList,
60647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Executor executor, VideoView2.OnCustomActionListener listener) {
60747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mCustomActionList = actionList;
60847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mCustomActionListenerRecord = new Pair<>(executor, listener);
60947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
61047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Create a new playback builder in order to clear existing the custom actions.
61147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mStateBuilder = null;
61247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        updatePlaybackState();
61347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
61447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
61547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
61647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Registers a callback to be invoked when a view type change is done.
61747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * {@see #setViewType(int)}
61847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @param l The callback that will be run
61947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * @hide
62047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
62147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @RestrictTo(LIBRARY_GROUP)
62247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
62347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void setOnViewTypeChangedListener(VideoView2.OnViewTypeChangedListener l) {
62447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mViewTypeChangedListener = l;
62547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
62647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
62747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
62847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onAttachedToWindowImpl() {
62947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Create MediaSession
63047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaSession = new MediaSessionCompat(mInstance.getContext(), "VideoView2MediaSession");
63147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaSession.setCallback(new MediaSessionCallback());
63247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaSession.setActive(true);
63347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaController = mMediaSession.getController();
63447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        attachMediaControlView();
63547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mCurrentState == STATE_PREPARED) {
63647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            extractTracks();
63747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            extractMetadata();
63847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            extractAudioMetadata();
63947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mNeedUpdateMediaType) {
64047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaSession.sendSessionEvent(
64147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS,
64247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaTypeData);
64347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mNeedUpdateMediaType = false;
64447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
64547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
64647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
64747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaRouter = MediaRouter.getInstance(mInstance.getContext());
64847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaRouter.setMediaSessionCompat(mMediaSession);
64947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaRouter.addCallback(mRouteSelector, mRouterCallback,
65047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
65147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
65247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
65347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
65447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onDetachedFromWindowImpl() {
65547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaSession.release();
65647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaSession = null;
65747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaController = null;
65847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
65947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
66047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
66147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onTouchEventImpl(MotionEvent ev) {
66247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (DEBUG) {
66347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "onTouchEvent(). mCurrentState=" + mCurrentState
66447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    + ", mTargetState=" + mTargetState);
66547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
66647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
66747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (!isMusicMediaType() || mSizeType != SIZE_TYPE_FULL) {
66847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                toggleMediaControlViewVisibility();
66947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
67047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
67147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
67247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
67347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
67447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onTrackballEventImpl(MotionEvent ev) {
67547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
67647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (!isMusicMediaType() || mSizeType != SIZE_TYPE_FULL) {
67747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                toggleMediaControlViewVisibility();
67847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
67947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
68047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
68147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
68247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
68347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onMeasureImpl(int widthMeasureSpec, int heightMeasureSpec) {
68447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (isMusicMediaType()) {
68547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            int currWidth = mInstance.getMeasuredWidth();
68647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            int currHeight = mInstance.getMeasuredHeight();
68747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mPrevWidth != currWidth || mPrevHeight != currHeight) {
68847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Point screenSize = new Point();
68947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mManager.getDefaultDisplay().getSize(screenSize);
69047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                int screenWidth = screenSize.x;
69147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                int screenHeight = screenSize.y;
69247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
69347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (currWidth == screenWidth && currHeight == screenHeight) {
69447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    int orientation = retrieveOrientation();
69547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
69647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        inflateMusicView(R.layout.full_landscape_music);
69747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    } else {
69847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        inflateMusicView(R.layout.full_portrait_music);
69947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
70047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
70147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (mSizeType != SIZE_TYPE_FULL) {
70247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mSizeType = SIZE_TYPE_FULL;
70347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        // Remove existing mFadeOut callback
70447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaControlView.removeCallbacks(mFadeOut);
70547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaControlView.setVisibility(View.VISIBLE);
70647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
70747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                } else {
70847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (mSizeType != SIZE_TYPE_EMBEDDED) {
70947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mSizeType = SIZE_TYPE_EMBEDDED;
71047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        inflateMusicView(R.layout.embedded_music);
71147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        // Add new mFadeOut callback
71247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
71347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
71447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
71547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mPrevWidth = currWidth;
71647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mPrevHeight = currHeight;
71747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
71847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
71947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
72047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
72147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    ///////////////////////////////////////////////////
72247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    // Implements VideoViewInterfaceWithMp1.SurfaceListener
72347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    ///////////////////////////////////////////////////
72447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
72547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
72647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onSurfaceCreated(View view, int width, int height) {
72747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (DEBUG) {
72847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "onSurfaceCreated(). mCurrentState=" + mCurrentState
72947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    + ", mTargetState=" + mTargetState + ", width/height: " + width + "/" + height
73047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    + ", " + view.toString());
73147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
73247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (needToStart()) {
73347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaController.getTransportControls().play();
73447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
73547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
73647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
73747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
73847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onSurfaceDestroyed(View view) {
73947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (DEBUG) {
74047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "onSurfaceDestroyed(). mCurrentState=" + mCurrentState
74147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    + ", mTargetState=" + mTargetState + ", " + view.toString());
74247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
74347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
74447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
74547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
74647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onSurfaceChanged(View view, int width, int height) {
74747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (DEBUG) {
74847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "onSurfaceChanged(). width/height: " + width + "/" + height
74947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    + ", " + view.toString());
75047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
75147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
75247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
75347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @Override
75447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    public void onSurfaceTakeOverDone(VideoViewInterfaceWithMp1 view) {
75547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (DEBUG) {
75647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "onSurfaceTakeOverDone(). Now current view is: " + view);
75747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
75847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mCurrentView = view;
75947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mViewTypeChangedListener != null) {
76047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mViewTypeChangedListener.onViewTypeChanged(mInstance, view.getViewType());
76147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
76247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (needToStart()) {
76347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaController.getTransportControls().play();
76447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
76547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
76647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
76747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    ///////////////////////////////////////////////////
76847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    // Protected or private methods
76947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    ///////////////////////////////////////////////////
77047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
77147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void attachMediaControlView() {
77247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Get MediaController from MediaSession and set it inside MediaControlView
77347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaControlView.setController(mMediaSession.getController());
77447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
77547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        LayoutParams params =
77647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
77747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.addView(mMediaControlView, params);
77847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
77947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
78047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected boolean isInPlaybackState() {
78147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return (mMediaPlayer != null || mRoutePlayer != null)
78247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && mCurrentState != STATE_ERROR
78347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && mCurrentState != STATE_IDLE
78447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && mCurrentState != STATE_PREPARING;
78547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
78647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
78747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private boolean needToStart() {
78847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return (mMediaPlayer != null || mRoutePlayer != null)
78947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && isAudioGranted()
79047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && isWaitingPlayback();
79147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
79247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
79347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private boolean isMusicMediaType() {
79447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mVideoTrackIndices != null && mVideoTrackIndices.size() == 0;
79547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
79647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
79747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private boolean isWaitingPlayback() {
79847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mCurrentState != STATE_PLAYING && mTargetState == STATE_PLAYING;
79947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
80047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
80147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private boolean isAudioGranted() {
80247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return mAudioFocused || mAudioFocusType == AudioManager.AUDIOFOCUS_NONE;
80347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
80447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
80547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private AudioManager.OnAudioFocusChangeListener mAudioFocusListener =
80647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            new AudioManager.OnAudioFocusChangeListener() {
80747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
80847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onAudioFocusChange(int focusChange) {
80947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            switch (focusChange) {
81047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                case AudioManager.AUDIOFOCUS_GAIN:
81147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mAudioFocused = true;
81247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (needToStart()) {
81347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaController.getTransportControls().play();
81447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
81547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    break;
81647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                case AudioManager.AUDIOFOCUS_LOSS:
81747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
81847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
81947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mAudioFocused = false;
82047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (isInPlaybackState() && mMediaPlayer.isPlaying()) {
82147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaController.getTransportControls().pause();
82247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    } else {
82347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mTargetState = STATE_PAUSED;
82447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
82547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
82647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
82747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
82847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
82947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @SuppressWarnings("deprecation")
83047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void requestAudioFocus(int focusType) {
83147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        int result;
83247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (android.os.Build.VERSION.SDK_INT >= 26) {
83347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            AudioFocusRequest focusRequest;
83447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            focusRequest = new AudioFocusRequest.Builder(focusType)
83547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    .setAudioAttributes(mAudioAttributes)
83647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    .setOnAudioFocusChangeListener(mAudioFocusListener)
83747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    .build();
83847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            result = mAudioManager.requestAudioFocus(focusRequest);
83947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else {
84047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            result = mAudioManager.requestAudioFocus(mAudioFocusListener,
84147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    AudioManager.STREAM_MUSIC,
84247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    focusType);
84347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
84447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
84547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mAudioFocused = false;
84647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
84747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mAudioFocused = true;
84847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else if (result == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
84947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mAudioFocused = false;
85047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
85147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
85247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
85347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    // Creates a MediaPlayer instance and prepare playback.
85447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void openVideo(Uri uri, Map<String, String> headers) {
85547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        resetPlayer();
85647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mUri = uri;
85747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (isRemotePlayback()) {
85847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            // TODO: b/77556429
85947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mRoutePlayer.openVideo(uri);
86047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return;
86147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
86247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
86347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        try {
86447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.d(TAG, "openVideo(): creating new MediaPlayer instance.");
86547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaPlayer = new MediaPlayer();
86647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            final Context context = mInstance.getContext();
86747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            setupMediaPlayer(context, uri, headers);
86847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
86947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            // we don't set the target state here either, but preserve the
87047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            // target state that was there before.
87147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentState = STATE_PREPARING;
87247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaPlayer.prepareAsync();
87347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
87447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            // Save file name as title since the file may not have a title Metadata.
87547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTitle = uri.getPath();
87647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            String scheme = uri.getScheme();
87747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (scheme != null && scheme.equals("file")) {
87847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mTitle = uri.getLastPathSegment();
87947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRetriever = new MediaMetadataRetriever();
88047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRetriever.setDataSource(context, uri);
88147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
88247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
88347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (DEBUG) {
88447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Log.d(TAG, "openVideo(). mCurrentState=" + mCurrentState
88547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        + ", mTargetState=" + mTargetState);
88647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
88747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } catch (IOException | IllegalArgumentException ex) {
88847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Log.w(TAG, "Unable to open content: " + uri, ex);
88947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentState = STATE_ERROR;
89047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTargetState = STATE_ERROR;
89147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mErrorListener.onError(mMediaPlayer,
89247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    MediaPlayer.MEDIA_ERROR_UNKNOWN, MediaPlayer.MEDIA_ERROR_IO);
89347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
89447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
89547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
89647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /**
89747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Used in openVideo(). Setup MediaPlayer and related objects before calling prepare.
89847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
89947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected void setupMediaPlayer(Context context, Uri uri, Map<String, String> headers)
90047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            throws IOException {
90147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mSurfaceView.setMediaPlayer(mMediaPlayer);
90247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mTextureView.setMediaPlayer(mMediaPlayer);
90347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mCurrentView.assignSurfaceToMediaPlayer(mMediaPlayer);
90447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
90547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setOnPreparedListener(mPreparedListener);
90647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
90747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setOnCompletionListener(mCompletionListener);
90847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
90947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setOnErrorListener(mErrorListener);
91047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setOnInfoListener(mInfoListener);
91147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
91247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
91347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mCurrentBufferPercentage = -1;
91447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setDataSource(context, uri, headers);
91547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaPlayer.setAudioAttributes(mAudioAttributes);
91647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
91747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
91847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    /*
91947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     * Reset the media player in any state
92047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang     */
92147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @SuppressWarnings("deprecation")
92247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void resetPlayer() {
92347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaPlayer != null) {
92447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaPlayer.reset();
92547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaPlayer.release();
92647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaPlayer = null;
92747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTextureView.setMediaPlayer(null);
92847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mSurfaceView.setMediaPlayer(null);
92947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentState = STATE_IDLE;
93047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTargetState = STATE_IDLE;
93147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
93247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mAudioManager.abandonAudioFocus(null);
93347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
93447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
93547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mVideoWidth = 0;
93647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mVideoHeight = 0;
93747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
93847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
93947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void updatePlaybackState() {
94047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mStateBuilder == null) {
94147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            long playbackActions = PlaybackStateCompat.ACTION_PLAY
94247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    | PlaybackStateCompat.ACTION_PAUSE
94347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    | PlaybackStateCompat.ACTION_REWIND | PlaybackStateCompat.ACTION_FAST_FORWARD
94447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    | PlaybackStateCompat.ACTION_SEEK_TO;
94547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mStateBuilder = new PlaybackStateCompat.Builder();
94647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mStateBuilder.setActions(playbackActions);
94747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
94847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mCustomActionList != null) {
94947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                for (PlaybackStateCompat.CustomAction action : mCustomActionList) {
95047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mStateBuilder.addCustomAction(action);
95147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
95247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
95347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
95447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mStateBuilder.setState(getCorrespondingPlaybackState(),
95547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaPlayer.getCurrentPosition(), mSpeed);
95647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mCurrentState != STATE_ERROR
95747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && mCurrentState != STATE_IDLE
95847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && mCurrentState != STATE_PREPARING) {
95947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mCurrentBufferPercentage == -1) {
96047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mStateBuilder.setBufferedPosition(-1);
96147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            } else {
96247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mStateBuilder.setBufferedPosition(
96347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        (long) (mCurrentBufferPercentage / 100.0 * mMediaPlayer.getDuration()));
96447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
96547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
96647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
96747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Set PlaybackState for MediaSession
96847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaSession != null) {
96947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            PlaybackStateCompat state = mStateBuilder.build();
97047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaSession.setPlaybackState(state);
97147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
97247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
97347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
97447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int getCorrespondingPlaybackState() {
97547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        switch (mCurrentState) {
97647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            case STATE_ERROR:
97747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return PlaybackStateCompat.STATE_ERROR;
97847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            case STATE_IDLE:
97947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return PlaybackStateCompat.STATE_NONE;
98047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            case STATE_PREPARING:
98147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return PlaybackStateCompat.STATE_CONNECTING;
98247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            case STATE_PREPARED:
98347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return PlaybackStateCompat.STATE_PAUSED;
98447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            case STATE_PLAYING:
98547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return PlaybackStateCompat.STATE_PLAYING;
98647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            case STATE_PAUSED:
98747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return PlaybackStateCompat.STATE_PAUSED;
98847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            case STATE_PLAYBACK_COMPLETED:
98947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return PlaybackStateCompat.STATE_STOPPED;
99047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            default:
99147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                return -1;
99247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
99347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
99447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
99547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private final Runnable mFadeOut = new Runnable() {
99647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
99747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void run() {
99847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mCurrentState == STATE_PLAYING) {
99947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaControlView.setVisibility(View.GONE);
100047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
100147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
100247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
100347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
100447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void showController() {
100547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaControlView == null || !isInPlaybackState()
100647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                || (isMusicMediaType() && mSizeType == SIZE_TYPE_FULL)) {
100747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return;
100847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
100947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaControlView.removeCallbacks(mFadeOut);
101047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaControlView.setVisibility(View.VISIBLE);
101147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mShowControllerIntervalMs != 0
101247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && !mAccessibilityManager.isTouchExplorationEnabled()) {
101347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
101447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
101547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
101647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
101747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void toggleMediaControlViewVisibility() {
101847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaControlView.getVisibility() == View.VISIBLE) {
101947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaControlView.removeCallbacks(mFadeOut);
102047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaControlView.setVisibility(View.GONE);
102147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else {
102247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            showController();
102347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
102447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
102547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
102647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void applySpeed() {
102747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (android.os.Build.VERSION.SDK_INT < 23) {
102847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return;
102947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
103047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        PlaybackParams params = mMediaPlayer.getPlaybackParams().allowDefaults();
103147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mSpeed != params.getSpeed()) {
103247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            try {
103347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                params.setSpeed(mSpeed);
103447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaPlayer.setPlaybackParams(params);
103547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mFallbackSpeed = mSpeed;
103647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            } catch (IllegalArgumentException e) {
103747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Log.e(TAG, "PlaybackParams has unsupported value: " + e);
103847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                float fallbackSpeed = mMediaPlayer.getPlaybackParams().allowDefaults().getSpeed();
103947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (fallbackSpeed > 0.0f) {
104047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mFallbackSpeed = fallbackSpeed;
104147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
104247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mSpeed = mFallbackSpeed;
104347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
104447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
104547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
104647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
104747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private boolean isRemotePlayback() {
104847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaController == null) {
104947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return false;
105047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
105147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        PlaybackInfo playbackInfo = mMediaController.getPlaybackInfo();
105247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return playbackInfo != null
105347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                && playbackInfo.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
105447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
105547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
105647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected void extractTracks() {
105747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
105847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mVideoTrackIndices = new ArrayList<>();
105947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mAudioTrackIndices = new ArrayList<>();
106047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        for (int i = 0; i < trackInfos.length; ++i) {
106147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            int trackType = trackInfos[i].getTrackType();
106247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
106347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mVideoTrackIndices.add(i);
106447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
106547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mAudioTrackIndices.add(i);
106647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
106747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
106847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Select first tracks as default
106947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mVideoTrackIndices.size() > 0) {
107047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mSelectedVideoTrackIndex = 0;
107147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
107247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mAudioTrackIndices.size() > 0) {
107347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mSelectedAudioTrackIndex = 0;
107447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
107547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
107647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        Bundle data = new Bundle();
107747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        data.putInt(MediaControlView2.KEY_VIDEO_TRACK_COUNT, mVideoTrackIndices.size());
107847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        data.putInt(MediaControlView2.KEY_AUDIO_TRACK_COUNT, mAudioTrackIndices.size());
107947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaSession.sendSessionEvent(MediaControlView2.EVENT_UPDATE_TRACK_STATUS, data);
108047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
108147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
108247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected void doShowSubtitleCommand(Bundle args) {
108347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // No-op
108447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
108547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
108647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    protected void doHideSubtitleCommand() {
108747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // No-op
108847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
108947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
109047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void extractMetadata() {
109147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mRetriever == null) {
109247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return;
109347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
109447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Get and set duration and title values as MediaMetadata for MediaControlView2
109547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
109647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
109747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (title != null) {
109847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTitle = title;
109947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
110047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
110147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        builder.putLong(
110247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
110347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
110447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mMediaSession != null) {
110547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMediaSession.setMetadata(builder.build());
110647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
110747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
110847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
110947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    @SuppressWarnings("deprecation")
111047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void extractAudioMetadata() {
111147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (mRetriever == null || !isMusicMediaType()) {
111247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return;
111347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
111447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
111547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mResources = mInstance.getResources();
111647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mManager = (WindowManager) mInstance.getContext().getApplicationContext()
111747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                .getSystemService(Context.WINDOW_SERVICE);
111847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
111947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        byte[] album = mRetriever.getEmbeddedPicture();
112047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (album != null) {
112147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Bitmap bitmap = BitmapFactory.decodeByteArray(album, 0, album.length);
112247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMusicAlbumDrawable = new BitmapDrawable(bitmap);
112347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
112447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            Palette.Builder builder = Palette.from(bitmap);
112547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            builder.generate(new Palette.PaletteAsyncListener() {
112647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                @Override
112747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                public void onGenerated(Palette palette) {
112847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mDominantColor = palette.getDominantColor(0);
112947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (mMusicView != null) {
113047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMusicView.setBackgroundColor(mDominantColor);
113147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
113247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
113347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            });
113447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else {
113547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMusicAlbumDrawable = mResources.getDrawable(R.drawable.ic_default_album_image);
113647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
113747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
113847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        String title = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
113947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (title != null) {
114047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMusicTitleText = title;
114147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else {
114247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMusicTitleText = mResources.getString(R.string.mcv2_music_title_unknown_text);
114347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
114447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
114547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        String artist = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
114647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (artist != null) {
114747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMusicArtistText = artist;
114847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        } else {
114947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mMusicArtistText = mResources.getString(R.string.mcv2_music_artist_unknown_text);
115047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
115147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
115247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Send title and artist string to MediaControlView2
115347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
115447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mMusicTitleText);
115547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, mMusicArtistText);
115647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMediaSession.setMetadata(builder.build());
115747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
115847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        // Display Embedded mode as default
115947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.removeView(mSurfaceView);
116047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.removeView(mTextureView);
116147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        inflateMusicView(R.layout.embedded_music);
116247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
116347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
116447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private int retrieveOrientation() {
116547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        DisplayMetrics dm = Resources.getSystem().getDisplayMetrics();
116647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        int width = dm.widthPixels;
116747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        int height = dm.heightPixels;
116847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
116947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        return (height > width)
117047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
117147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
117247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
117347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
117447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private void inflateMusicView(int layoutId) {
117547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.removeView(mMusicView);
117647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
117747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        LayoutInflater inflater = (LayoutInflater) mInstance.getContext()
117847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
117947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        View v = inflater.inflate(layoutId, null);
118047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        v.setBackgroundColor(mDominantColor);
118147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
118247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        ImageView albumView = v.findViewById(R.id.album);
118347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (albumView != null) {
118447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            albumView.setImageDrawable(mMusicAlbumDrawable);
118547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
118647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
118747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        TextView titleView = v.findViewById(R.id.title);
118847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (titleView != null) {
118947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            titleView.setText(mMusicTitleText);
119047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
119147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
119247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        TextView artistView = v.findViewById(R.id.artist);
119347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        if (artistView != null) {
119447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            artistView.setText(mMusicArtistText);
119547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
119647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
119747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mMusicView = v;
119847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        mInstance.addView(mMusicView, 0);
119947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
120047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
120147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
120247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            new MediaPlayer.OnVideoSizeChangedListener() {
120347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                @Override
120447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                public void onVideoSizeChanged(
120547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        MediaPlayer mp, int width, int height) {
120647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (DEBUG) {
120747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        Log.d(TAG, "onVideoSizeChanged(): size: " + width + "/" + height);
120847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
120947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mVideoWidth = mp.getVideoWidth();
121047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mVideoHeight = mp.getVideoHeight();
121147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (DEBUG) {
121247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        Log.d(TAG, "onVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/"
121347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                + mVideoHeight);
121447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
121547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (mVideoWidth != 0 && mVideoHeight != 0) {
121647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mInstance.requestLayout();
121747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
121847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
121947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            };
122047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
122147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaPlayer.OnPreparedListener mPreparedListener =
122247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            new MediaPlayer.OnPreparedListener() {
122347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
122447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onPrepared(MediaPlayer mp) {
122547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (DEBUG) {
122647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Log.d(TAG, "OnPreparedListener(). mCurrentState=" + mCurrentState
122747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        + ", mTargetState=" + mTargetState);
122847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
122947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentState = STATE_PREPARED;
123047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            // Create and set playback state for MediaControlView2
123147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            updatePlaybackState();
123247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
123347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mMediaSession != null) {
123447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                extractTracks();
123547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                extractMetadata();
123647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                extractAudioMetadata();
123747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
123847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
123947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mMediaControlView != null) {
124047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaControlView.setEnabled(true);
124147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
124247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            int videoWidth = mp.getVideoWidth();
124347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            int videoHeight = mp.getVideoHeight();
124447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
124547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            // mSeekWhenPrepared may be changed after seekTo() call
124647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            long seekToPosition = mSeekWhenPrepared;
124747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (seekToPosition != 0) {
124847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaController.getTransportControls().seekTo(seekToPosition);
124947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
125047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
125147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (videoWidth != 0 && videoHeight != 0) {
125247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (videoWidth != mVideoWidth || videoHeight != mVideoHeight) {
125347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mVideoWidth = videoWidth;
125447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mVideoHeight = videoHeight;
125547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mInstance.requestLayout();
125647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
125747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
125847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (needToStart()) {
125947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mMediaController.getTransportControls().play();
126047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
126147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            } else {
126247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                // We don't know the video size yet, but should start anyway.
126347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                // The video size might be reported to us later.
126447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (needToStart()) {
126547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mMediaController.getTransportControls().play();
126647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
126747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
126847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            // Get and set duration and title values as MediaMetadata for MediaControlView2
126947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
127047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
127147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mTitle);
127247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
127347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
127447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mMediaSession != null) {
127547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaSession.setMetadata(builder.build());
127647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
127747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (mNeedUpdateMediaType) {
127847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mMediaSession.sendSessionEvent(
127947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            MediaControlView2.EVENT_UPDATE_MEDIA_TYPE_STATUS, mMediaTypeData);
128047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mNeedUpdateMediaType = false;
128147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
128247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
128347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
128447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
128547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
128647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaPlayer.OnSeekCompleteListener mSeekCompleteListener =
128747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            new MediaPlayer.OnSeekCompleteListener() {
128847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                @Override
128947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                public void onSeekComplete(MediaPlayer mp) {
129047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    updatePlaybackState();
129147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
129247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
129347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
129447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaPlayer.OnCompletionListener mCompletionListener =
129547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            new MediaPlayer.OnCompletionListener() {
129647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
129747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @SuppressWarnings("deprecation")
129847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onCompletion(MediaPlayer mp) {
129947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentState = STATE_PLAYBACK_COMPLETED;
130047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTargetState = STATE_PLAYBACK_COMPLETED;
130147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            updatePlaybackState();
130247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
130347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mAudioManager.abandonAudioFocus(null);
130447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
130547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
130647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
130747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
130847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
130947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
131047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public boolean onInfo(MediaPlayer mp, int what, int extra) {
131147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
131247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                extractTracks();
131347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
131447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return true;
131547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
131647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
131747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
131847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
131947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
132047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public boolean onError(MediaPlayer mp, int frameworkErr, int implErr) {
132147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (DEBUG) {
132247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
132347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
132447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentState = STATE_ERROR;
132547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTargetState = STATE_ERROR;
132647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            updatePlaybackState();
132747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
132847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (mMediaControlView != null) {
132947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mMediaControlView.setVisibility(View.GONE);
133047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
133147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            return true;
133247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
133347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
133447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
133547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
133647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            new MediaPlayer.OnBufferingUpdateListener() {
133747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
133847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onBufferingUpdate(MediaPlayer mp, int percent) {
133947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCurrentBufferPercentage = percent;
134047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            updatePlaybackState();
134147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
134247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    };
134347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
134447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    private class MediaSessionCallback extends MediaSessionCompat.Callback {
134547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
134647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onCommand(String command, Bundle args, ResultReceiver receiver) {
134747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (isRemotePlayback()) {
134847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoutePlayer.onCommand(command, args, receiver);
134947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            } else {
135047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                switch (command) {
135147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    case MediaControlView2.COMMAND_SHOW_SUBTITLE:
135247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        doShowSubtitleCommand(args);
135347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        break;
135447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    case MediaControlView2.COMMAND_HIDE_SUBTITLE:
135547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        doHideSubtitleCommand();
135647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        break;
135747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    case MediaControlView2.COMMAND_SELECT_AUDIO_TRACK:
135847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        int audioIndex = args.getInt(MediaControlView2.KEY_SELECTED_AUDIO_INDEX,
135947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                INVALID_TRACK_INDEX);
136047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        if (audioIndex != INVALID_TRACK_INDEX) {
136147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            int audioTrackIndex = mAudioTrackIndices.get(audioIndex);
136247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            if (audioTrackIndex != mSelectedAudioTrackIndex) {
136347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                mSelectedAudioTrackIndex = audioTrackIndex;
136447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                mMediaPlayer.selectTrack(mSelectedAudioTrackIndex);
136547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            }
136647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        }
136747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        break;
136847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    case MediaControlView2.COMMAND_SET_PLAYBACK_SPEED:
136947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        float speed = args.getFloat(
137047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                                MediaControlView2.KEY_PLAYBACK_SPEED, INVALID_SPEED);
137147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        if (speed != INVALID_SPEED && speed != mSpeed) {
137247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            setSpeed(speed);
137347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                            mSpeed = speed;
137447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        }
137547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        break;
137647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    case MediaControlView2.COMMAND_MUTE:
137747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mVolumeLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
137847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
137947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        break;
138047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    case MediaControlView2.COMMAND_UNMUTE:
138147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mVolumeLevel, 0);
138247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        break;
138347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
138447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
138547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            showController();
138647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
138747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
138847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
138947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onCustomAction(final String action, final Bundle extras) {
139047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mCustomActionListenerRecord.first.execute(new Runnable() {
139147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                @Override
139247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                public void run() {
139347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mCustomActionListenerRecord.second.onCustomAction(action, extras);
139447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
139547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            });
139647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            showController();
139747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
139847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
139947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
140047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onPlay() {
140147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (!isAudioGranted()) {
140247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                requestAudioFocus(mAudioFocusType);
140347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
140447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
140547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if ((isInPlaybackState() && mCurrentView.hasAvailableSurface()) || isMusicMediaType()) {
140647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (isRemotePlayback()) {
140747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mRoutePlayer.onPlay();
140847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                } else {
140947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    applySpeed();
141047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mMediaPlayer.start();
141147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mCurrentState = STATE_PLAYING;
141247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    updatePlaybackState();
141347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
141447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mCurrentState = STATE_PLAYING;
141547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
141647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTargetState = STATE_PLAYING;
141747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (DEBUG) {
141847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Log.d(TAG, "onPlay(). mCurrentState=" + mCurrentState
141947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        + ", mTargetState=" + mTargetState);
142047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
142147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            showController();
142247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
142347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
142447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
142547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onPause() {
142647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (isInPlaybackState()) {
142747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (isRemotePlayback()) {
142847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mRoutePlayer.onPlay();
142947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mCurrentState = STATE_PAUSED;
143047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                } else if (mMediaPlayer.isPlaying()) {
143147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mMediaPlayer.pause();
143247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mCurrentState = STATE_PAUSED;
143347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    updatePlaybackState();
143447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
143547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
143647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            mTargetState = STATE_PAUSED;
143747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (DEBUG) {
143847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                Log.d(TAG, "onPause(). mCurrentState=" + mCurrentState
143947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        + ", mTargetState=" + mTargetState);
144047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
144147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            showController();
144247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
144347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
144447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
144547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onSeekTo(long pos) {
144647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (isInPlaybackState()) {
144747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                if (isRemotePlayback()) {
144847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mRoutePlayer.onPlay();
144947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                } else {
145047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    if (android.os.Build.VERSION.SDK_INT < 26) {
145147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaPlayer.seekTo((int) pos);
145247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    } else {
145347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                        mMediaPlayer.seekTo(pos, MediaPlayer.SEEK_PREVIOUS_SYNC);
145447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    }
145547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                    mSeekWhenPrepared = 0;
145647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                }
145747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            } else {
145847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mSeekWhenPrepared = pos;
145947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
146047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            showController();
146147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
146247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang
146347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        @Override
146447740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        public void onStop() {
146547740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            if (isRemotePlayback()) {
146647740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                mRoutePlayer.onPlay();
146747740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            } else {
146847740510281e2d2c5a535c31d52ac970d32951c6Insun Kang                resetPlayer();
146947740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            }
147047740510281e2d2c5a535c31d52ac970d32951c6Insun Kang            showController();
147147740510281e2d2c5a535c31d52ac970d32951c6Insun Kang        }
147247740510281e2d2c5a535c31d52ac970d32951c6Insun Kang    }
147347740510281e2d2c5a535c31d52ac970d32951c6Insun Kang}
1474