1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.widget;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.graphics.SurfaceTexture;
22 import android.media.MediaPlayer;
23 import android.net.Uri;
24 import android.view.Surface;
25 import android.view.TextureView;
26 import android.view.View;
27 
28 /**
29  * A {@link VideoPreference.AnimationController} containing a {@link
30  * MediaPlayer}. The controller is used by {@link VideoPreference} to display
31  * a mp4 resource.
32  */
33 class MediaAnimationController implements VideoPreference.AnimationController {
34     private MediaPlayer mMediaPlayer;
35     private boolean mVideoReady;
36     private Surface mSurface;
37 
MediaAnimationController(Context context, int videoId)38     MediaAnimationController(Context context, int videoId) {
39         final Uri videoPath = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
40                 .authority(context.getPackageName())
41                 .appendPath(String.valueOf(videoId))
42                 .build();
43         mMediaPlayer = MediaPlayer.create(context, videoPath);
44         // when the playback res is invalid or others, MediaPlayer create may fail
45         // and return null, so need add the null judgement.
46         if (mMediaPlayer != null) {
47             mMediaPlayer.seekTo(0);
48             mMediaPlayer.setOnSeekCompleteListener(mp -> mVideoReady = true);
49             mMediaPlayer.setOnPreparedListener(mediaPlayer -> mediaPlayer.setLooping(true));
50         }
51     }
52 
53     @Override
getVideoWidth()54     public int getVideoWidth() {
55         return mMediaPlayer.getVideoWidth();
56     }
57 
58     @Override
getVideoHeight()59     public int getVideoHeight() {
60         return mMediaPlayer.getVideoHeight();
61     }
62 
63     @Override
pause()64     public void pause() {
65         mMediaPlayer.pause();
66     }
67 
68     @Override
start()69     public void start() {
70         mMediaPlayer.start();
71     }
72 
73     @Override
isPlaying()74     public boolean isPlaying() {
75         return mMediaPlayer.isPlaying();
76     }
77 
78     @Override
getDuration()79     public int getDuration() {
80         return mMediaPlayer.getDuration();
81     }
82 
83     @Override
attachView(TextureView video, View preview, View playButton)84     public void attachView(TextureView video, View preview, View playButton) {
85         updateViewStates(preview, playButton);
86         video.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
87             @Override
88             public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
89                     int height) {
90                 setSurface(surfaceTexture);
91             }
92 
93             @Override
94             public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
95                     int height) {
96             }
97 
98             @Override
99             public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
100                 preview.setVisibility(View.VISIBLE);
101                 mSurface = null;
102                 return false;
103             }
104 
105             @Override
106             public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
107                 setSurface(surfaceTexture);
108                 if (mVideoReady) {
109                     if (preview.getVisibility() == View.VISIBLE) {
110                         preview.setVisibility(View.GONE);
111                     }
112                     if (mMediaPlayer != null
113                             && !mMediaPlayer.isPlaying()) {
114                         mMediaPlayer.start();
115                         playButton.setVisibility(View.GONE);
116                     }
117                 }
118                 if (mMediaPlayer != null && !mMediaPlayer.isPlaying()
119                         && playButton.getVisibility() != View.VISIBLE) {
120                     playButton.setVisibility(View.VISIBLE);
121                 }
122             }
123         });
124         video.setOnClickListener(v -> updateViewStates(preview, playButton));
125     }
126 
127     @Override
release()128     public void release() {
129         if (mMediaPlayer != null) {
130             mMediaPlayer.stop();
131             mMediaPlayer.reset();
132             mMediaPlayer.release();
133             mMediaPlayer = null;
134             mVideoReady = false;
135         }
136     }
137 
updateViewStates(View imageView, View playButton)138     private void updateViewStates(View imageView, View playButton) {
139         if (mMediaPlayer.isPlaying()) {
140             mMediaPlayer.pause();
141             playButton.setVisibility(View.VISIBLE);
142             imageView.setVisibility(View.VISIBLE);
143         } else {
144             imageView.setVisibility(View.GONE);
145             playButton.setVisibility(View.GONE);
146             mMediaPlayer.start();
147         }
148     }
149 
setSurface(SurfaceTexture surfaceTexture)150     private void setSurface(SurfaceTexture surfaceTexture) {
151         if (mMediaPlayer != null && mSurface == null) {
152             mSurface = new Surface(surfaceTexture);
153             mMediaPlayer.setSurface(mSurface);
154         }
155     }
156 }
157