From 953da2ee40d077251a26c4aff263e86a8bb0e3ff Mon Sep 17 00:00:00 2001 From: Raff Tsai Date: Thu, 31 Oct 2019 14:03:34 +0800 Subject: [PATCH] Add AnimatedVectorDrawable support for VideoPreference - We are planning to use animation vector drawable to replace mp4 file to reduce apk size - Add vectorAnimation attr in VideoPreference - Delegate VideoPreference media control to AnimationController Bug: 143270527 Test: manual, robolectric Change-Id: Ia5859f928a9082085cdf715c762f964e1c99e003 --- res/values/attrs.xml | 1 + .../widget/MediaAnimationController.java | 149 +++++++++++++ .../widget/VectorAnimationController.java | 111 ++++++++++ .../settings/widget/VideoPreference.java | 197 +++++++----------- .../shadow/ShadowSettingsMediaPlayer.java | 51 +++++ .../settings/widget/VideoPreferenceTest.java | 59 +++--- 6 files changed, 422 insertions(+), 146 deletions(-) create mode 100644 src/com/android/settings/widget/MediaAnimationController.java create mode 100644 src/com/android/settings/widget/VectorAnimationController.java create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsMediaPlayer.java diff --git a/res/values/attrs.xml b/res/values/attrs.xml index b2cd1a5a7c4..42167b74789 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -119,6 +119,7 @@ + diff --git a/src/com/android/settings/widget/MediaAnimationController.java b/src/com/android/settings/widget/MediaAnimationController.java new file mode 100644 index 00000000000..eb7b3e042c1 --- /dev/null +++ b/src/com/android/settings/widget/MediaAnimationController.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.widget; + +import android.content.ContentResolver; +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.media.MediaPlayer; +import android.net.Uri; +import android.view.Surface; +import android.view.TextureView; +import android.view.View; + +/** + * A {@link VideoPreference.AnimationController} containing a {@link + * MediaPlayer}. The controller is used by {@link VideoPreference} to display + * a mp4 resource. + */ +class MediaAnimationController implements VideoPreference.AnimationController { + private MediaPlayer mMediaPlayer; + private boolean mVideoReady; + + MediaAnimationController(Context context, int videoId) { + final Uri videoPath = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) + .authority(context.getPackageName()) + .appendPath(String.valueOf(videoId)) + .build(); + mMediaPlayer = MediaPlayer.create(context, videoPath); + // when the playback res is invalid or others, MediaPlayer create may fail + // and return null, so need add the null judgement. + if (mMediaPlayer != null) { + mMediaPlayer.seekTo(0); + mMediaPlayer.setOnSeekCompleteListener(mp -> mVideoReady = true); + mMediaPlayer.setOnPreparedListener(mediaPlayer -> mediaPlayer.setLooping(true)); + } + } + + @Override + public int getVideoWidth() { + return mMediaPlayer.getVideoWidth(); + } + + @Override + public int getVideoHeight() { + return mMediaPlayer.getVideoHeight(); + } + + @Override + public void pause() { + mMediaPlayer.pause(); + } + + @Override + public void start() { + mMediaPlayer.start(); + } + + @Override + public boolean isPlaying() { + return mMediaPlayer.isPlaying(); + } + + @Override + public int getDuration() { + return mMediaPlayer.getDuration(); + } + + @Override + public void attachView(TextureView video, View preview, View playButton) { + updateViewStates(preview, playButton); + video.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, + int height) { + if (mMediaPlayer != null) { + final Surface surface = new Surface(surfaceTexture); + mMediaPlayer.setSurface(surface); + } + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, + int height) { + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { + preview.setVisibility(View.VISIBLE); + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + if (mVideoReady) { + if (preview.getVisibility() == View.VISIBLE) { + preview.setVisibility(View.GONE); + } + if (mMediaPlayer != null + && !mMediaPlayer.isPlaying()) { + mMediaPlayer.start(); + playButton.setVisibility(View.GONE); + } + } + if (mMediaPlayer != null && !mMediaPlayer.isPlaying() + && playButton.getVisibility() != View.VISIBLE) { + playButton.setVisibility(View.VISIBLE); + } + } + }); + video.setOnClickListener(v -> updateViewStates(preview, playButton)); + } + + @Override + public void release() { + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + mMediaPlayer.reset(); + mMediaPlayer.release(); + mMediaPlayer = null; + mVideoReady = false; + } + } + + private void updateViewStates(View imageView, View playButton) { + if (mMediaPlayer.isPlaying()) { + mMediaPlayer.pause(); + playButton.setVisibility(View.VISIBLE); + imageView.setVisibility(View.VISIBLE); + } else { + imageView.setVisibility(View.GONE); + playButton.setVisibility(View.GONE); + mMediaPlayer.start(); + } + } +} diff --git a/src/com/android/settings/widget/VectorAnimationController.java b/src/com/android/settings/widget/VectorAnimationController.java new file mode 100644 index 00000000000..b6f0d0793a3 --- /dev/null +++ b/src/com/android/settings/widget/VectorAnimationController.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.TextureView; +import android.view.View; + +import androidx.vectordrawable.graphics.drawable.Animatable2Compat; +import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; + +/** + * A {@link VideoPreference.AnimationController} containing a {@link + * AnimatedVectorDrawableCompat}. The controller is used by {@link VideoPreference} + * to display AnimatedVectorDrawable content. + */ +class VectorAnimationController implements VideoPreference.AnimationController { + private AnimatedVectorDrawableCompat mAnimatedVectorDrawableCompat; + private Drawable mPreviewDrawable; + private Animatable2Compat.AnimationCallback mAnimationCallback; + + /** + * Called by a preference panel fragment to finish itself. + * + * @param context Application Context + * @param animationId An {@link android.graphics.drawable.AnimationDrawable} resource id + */ + VectorAnimationController(Context context, int animationId) { + mAnimatedVectorDrawableCompat = AnimatedVectorDrawableCompat.create(context, animationId); + mAnimationCallback = new Animatable2Compat.AnimationCallback() { + @Override + public void onAnimationEnd(Drawable drawable) { + mAnimatedVectorDrawableCompat.start(); + } + }; + } + + @Override + public int getVideoWidth() { + return mAnimatedVectorDrawableCompat.getIntrinsicWidth(); + } + + @Override + public int getVideoHeight() { + return mAnimatedVectorDrawableCompat.getIntrinsicHeight(); + } + + @Override + public void pause() { + mAnimatedVectorDrawableCompat.stop(); + } + + @Override + public void start() { + mAnimatedVectorDrawableCompat.start(); + } + + @Override + public boolean isPlaying() { + return mAnimatedVectorDrawableCompat.isRunning(); + } + + @Override + public int getDuration() { + // We can't get duration from AnimatedVectorDrawable, just return a non zero value. + return 5000; + } + + @Override + public void attachView(TextureView video, View preview, View playButton) { + mPreviewDrawable = preview.getForeground(); + video.setVisibility(View.GONE); + updateViewStates(preview, playButton); + preview.setOnClickListener(v -> updateViewStates(preview, playButton)); + } + + @Override + public void release() { + mAnimatedVectorDrawableCompat.stop(); + mAnimatedVectorDrawableCompat.clearAnimationCallbacks(); + } + + private void updateViewStates(View imageView, View playButton) { + if (mAnimatedVectorDrawableCompat.isRunning()) { + mAnimatedVectorDrawableCompat.stop(); + mAnimatedVectorDrawableCompat.clearAnimationCallbacks(); + playButton.setVisibility(View.VISIBLE); + imageView.setForeground(mPreviewDrawable); + } else { + playButton.setVisibility(View.GONE); + imageView.setForeground(mAnimatedVectorDrawableCompat); + mAnimatedVectorDrawableCompat.start(); + mAnimatedVectorDrawableCompat.registerAnimationCallback(mAnimationCallback); + } + } +} diff --git a/src/com/android/settings/widget/VideoPreference.java b/src/com/android/settings/widget/VideoPreference.java index 11a6478f23d..73b63b110f9 100644 --- a/src/com/android/settings/widget/VideoPreference.java +++ b/src/com/android/settings/widget/VideoPreference.java @@ -16,16 +16,11 @@ package com.android.settings.widget; -import android.content.ContentResolver; import android.content.Context; import android.content.res.TypedArray; -import android.graphics.SurfaceTexture; -import android.media.MediaPlayer; -import android.net.Uri; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; -import android.view.Surface; import android.view.TextureView; import android.view.View; import android.widget.ImageView; @@ -34,30 +29,27 @@ import android.widget.LinearLayout; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; +import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; import com.android.settings.R; /** - * A full width preference that hosts a MP4 video. + * A full width preference that hosts a MP4 video or a {@link AnimatedVectorDrawableCompat}. */ public class VideoPreference extends Preference { private static final String TAG = "VideoPreference"; private final Context mContext; - private Uri mVideoPath; @VisibleForTesting - MediaPlayer mMediaPlayer; + AnimationController mAnimationController; @VisibleForTesting boolean mAnimationAvailable; - @VisibleForTesting - boolean mVideoReady; private boolean mVideoPaused; private float mAspectRatio = 1.0f; - private int mPreviewResource; - private boolean mViewVisible; - private Surface mSurface; + private int mPreviewId; private int mAnimationId; + private int mVectorAnimationId; private int mHeight = LinearLayout.LayoutParams.MATCH_PARENT - 1; // video height in pixels public VideoPreference(Context context) { @@ -84,19 +76,17 @@ public class VideoPreference extends Preference { mAnimationId = mAnimationId == 0 ? attributes.getResourceId(R.styleable.VideoPreference_animation, 0) : mAnimationId; - mVideoPath = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) - .authority(context.getPackageName()) - .appendPath(String.valueOf(mAnimationId)) - .build(); - mPreviewResource = mPreviewResource == 0 - ? attributes.getResourceId(R.styleable.VideoPreference_preview, 0) - : mPreviewResource; - if (mPreviewResource == 0 && mAnimationId == 0) { + mPreviewId = mPreviewId == 0 + ? attributes.getResourceId(R.styleable.VideoPreference_preview, 0) + : mPreviewId; + mVectorAnimationId = attributes.getResourceId( + R.styleable.VideoPreference_vectorAnimation, 0); + if (mPreviewId == 0 && mAnimationId == 0 && mVectorAnimationId == 0) { setVisible(false); return; } - initMediaPlayer(); - if (mMediaPlayer != null && mMediaPlayer.getDuration() > 0) { + initAnimationController(); + if (mAnimationController != null && mAnimationController.getDuration() > 0) { setVisible(true); setLayoutResource(R.layout.video_preference); mAnimationAvailable = true; @@ -120,135 +110,63 @@ public class VideoPreference extends Preference { } final TextureView video = (TextureView) holder.findViewById(R.id.video_texture_view); - final ImageView imageView = (ImageView) holder.findViewById(R.id.video_preview_image); + final ImageView previewImage = (ImageView) holder.findViewById(R.id.video_preview_image); final ImageView playButton = (ImageView) holder.findViewById(R.id.video_play_button); final AspectRatioFrameLayout layout = (AspectRatioFrameLayout) holder.findViewById( R.id.video_container); - imageView.setImageResource(mPreviewResource); + previewImage.setImageResource(mPreviewId); layout.setAspectRatio(mAspectRatio); if (mHeight >= LinearLayout.LayoutParams.MATCH_PARENT) { layout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, mHeight)); } - updateViewStates(imageView, playButton); - - video.setOnClickListener(v -> updateViewStates(imageView, playButton)); - - video.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, - int height) { - if (mMediaPlayer != null) { - mSurface = new Surface(surfaceTexture); - mMediaPlayer.setSurface(mSurface); - } - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, - int height) { - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { - imageView.setVisibility(View.VISIBLE); - return false; - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { - if (!mViewVisible) { - return; - } - if (mVideoReady) { - if (imageView.getVisibility() == View.VISIBLE) { - imageView.setVisibility(View.GONE); - } - if (!mVideoPaused && mMediaPlayer != null && !mMediaPlayer.isPlaying()) { - mMediaPlayer.start(); - playButton.setVisibility(View.GONE); - } - } - if (mMediaPlayer != null && !mMediaPlayer.isPlaying() && - playButton.getVisibility() != View.VISIBLE) { - playButton.setVisibility(View.VISIBLE); - } - } - }); - } - - @VisibleForTesting - void updateViewStates(ImageView imageView, ImageView playButton) { - if (mMediaPlayer != null) { - if (mMediaPlayer.isPlaying()) { - mMediaPlayer.pause(); - playButton.setVisibility(View.VISIBLE); - imageView.setVisibility(View.VISIBLE); - mVideoPaused = true; - } else { - imageView.setVisibility(View.GONE); - playButton.setVisibility(View.GONE); - mMediaPlayer.start(); - mVideoPaused = false; - } - } + mAnimationController.attachView(video, previewImage, playButton); } @Override public void onDetached() { - releaseMediaPlayer(); + releaseAnimationController(); super.onDetached(); } public void onViewVisible(boolean videoPaused) { - mViewVisible = true; mVideoPaused = videoPaused; - initMediaPlayer(); + initAnimationController(); } public void onViewInvisible() { - mViewVisible = false; - releaseMediaPlayer(); + releaseAnimationController(); } /** * Sets the video for this preference. If a previous video was set this one will override it * and properly release any resources and re-initialize the preference to play the new video. * - * @param videoId The raw res id of the video + * @param videoId The raw res id of the video * @param previewId The drawable res id of the preview image to use if the video fails to load. */ public void setVideo(int videoId, int previewId) { mAnimationId = videoId; - mPreviewResource = previewId; - releaseMediaPlayer(); + mPreviewId = previewId; + releaseAnimationController(); initialize(mContext, null); } - private void initMediaPlayer() { - if (mMediaPlayer == null) { - mMediaPlayer = MediaPlayer.create(mContext, mVideoPath); - // when the playback res is invalid or others, MediaPlayer create may fail - // and return null, so need add the null judgement. - if (mMediaPlayer != null) { - mMediaPlayer.seekTo(0); - mMediaPlayer.setOnSeekCompleteListener(mp -> mVideoReady = true); - mMediaPlayer.setOnPreparedListener(mediaPlayer -> mediaPlayer.setLooping(true)); - if (mSurface != null) { - mMediaPlayer.setSurface(mSurface); - } - } + private void initAnimationController() { + if (mVectorAnimationId != 0) { + mAnimationController = new VectorAnimationController(mContext, mVectorAnimationId); + return; + } + if (mAnimationId != 0) { + mAnimationController = new MediaAnimationController(mContext, mAnimationId); } } - private void releaseMediaPlayer() { - if (mMediaPlayer != null) { - mMediaPlayer.stop(); - mMediaPlayer.reset(); - mMediaPlayer.release(); - mMediaPlayer = null; - mVideoReady = false; + private void releaseAnimationController() { + if (mAnimationController != null) { + mAnimationController.release(); + mAnimationController = null; } } @@ -262,6 +180,7 @@ public class VideoPreference extends Preference { /** * sets the height of the video preference + * * @param height in dp */ public void setHeight(float height) { @@ -271,6 +190,52 @@ public class VideoPreference extends Preference { @VisibleForTesting void updateAspectRatio() { - mAspectRatio = mMediaPlayer.getVideoWidth() / (float) mMediaPlayer.getVideoHeight(); + mAspectRatio = mAnimationController.getVideoWidth() + / (float) mAnimationController.getVideoHeight(); + } + + /** + * Handle animation operations. + */ + interface AnimationController { + /** + * Pauses the animation. + */ + void pause(); + + /** + * Starts the animation. + */ + void start(); + + /** + * Releases the animation object. + */ + void release(); + + /** + * Attaches the animation to UI view. + */ + void attachView(TextureView video, View preview, View playButton); + + /** + * Returns the animation Width. + */ + int getVideoWidth(); + + /** + * Returns the animation Height. + */ + int getVideoHeight(); + + /** + * Returns the animation duration. + */ + int getDuration(); + + /** + * Returns if the animation is playing. + */ + boolean isPlaying(); } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsMediaPlayer.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsMediaPlayer.java new file mode 100644 index 00000000000..adb0d1842cf --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsMediaPlayer.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.testutils.shadow; + +import static org.robolectric.shadows.ShadowMediaPlayer.State.INITIALIZED; + +import android.content.Context; +import android.media.MediaPlayer; +import android.net.Uri; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowMediaPlayer; +import org.robolectric.shadows.util.DataSource; + +@Implements(MediaPlayer.class) +public class ShadowSettingsMediaPlayer extends ShadowMediaPlayer { + + @Implementation + public static MediaPlayer create(Context context, Uri uri) { + final DataSource ds = DataSource.toDataSource(context, uri); + addMediaInfo(ds, new ShadowMediaPlayer.MediaInfo()); + + final MediaPlayer mp = new MediaPlayer(); + final ShadowMediaPlayer shadow = Shadow.extract(mp); + try { + shadow.setDataSource(ds); + shadow.setState(INITIALIZED); + mp.prepare(); + } catch (Exception e) { + return null; + } + + return mp; + } +} diff --git a/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java index b53f3644575..4dad686d0c0 100644 --- a/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java @@ -18,26 +18,24 @@ package com.android.settings.widget; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.graphics.SurfaceTexture; -import android.media.MediaPlayer; import android.view.LayoutInflater; import android.view.TextureView; - import android.view.View; import android.widget.ImageView; + import androidx.preference.PreferenceViewHolder; import com.android.settings.R; +import com.android.settings.testutils.shadow.ShadowSettingsMediaPlayer; import org.junit.Before; import org.junit.Test; @@ -46,14 +44,15 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowSettingsMediaPlayer.class) public class VideoPreferenceTest { private static final int VIDEO_WIDTH = 100; private static final int VIDEO_HEIGHT = 150; - @Mock - private MediaPlayer mMediaPlayer; + private VideoPreference.AnimationController mAnimationController; @Mock private ImageView fakePreview; @Mock @@ -67,10 +66,12 @@ public class VideoPreferenceTest { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; + mAnimationController = spy( + new MediaAnimationController(mContext, R.raw.accessibility_screen_magnification)); mVideoPreference = new VideoPreference(mContext, null /* attrs */); - mVideoPreference.mMediaPlayer = mMediaPlayer; - when(mMediaPlayer.getVideoWidth()).thenReturn(VIDEO_WIDTH); - when(mMediaPlayer.getVideoHeight()).thenReturn(VIDEO_HEIGHT); + mVideoPreference.mAnimationController = mAnimationController; + when(mAnimationController.getVideoWidth()).thenReturn(VIDEO_WIDTH); + when(mAnimationController.getVideoHeight()).thenReturn(VIDEO_HEIGHT); mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests( LayoutInflater.from(mContext).inflate(R.layout.video_preference, null)); @@ -91,17 +92,17 @@ public class VideoPreferenceTest { @Test public void onSurfaceTextureUpdated_viewInvisible_shouldNotStartPlayingVideo() { final TextureView video = - (TextureView) mPreferenceViewHolder.findViewById(R.id.video_texture_view); + (TextureView) mPreferenceViewHolder.findViewById(R.id.video_texture_view); mVideoPreference.mAnimationAvailable = true; - mVideoPreference.mVideoReady = true; - mVideoPreference.onViewInvisible(); mVideoPreference.onBindViewHolder(mPreferenceViewHolder); - when(mMediaPlayer.isPlaying()).thenReturn(false); + mAnimationController.attachView(video, fakePreview, fakePlayButton); + when(mAnimationController.isPlaying()).thenReturn(false); final TextureView.SurfaceTextureListener listener = video.getSurfaceTextureListener(); + mVideoPreference.onViewInvisible(); listener.onSurfaceTextureUpdated(mock(SurfaceTexture.class)); - verify(mMediaPlayer, never()).start(); + verify(mAnimationController, never()).start(); } @Test @@ -110,32 +111,30 @@ public class VideoPreferenceTest { mVideoPreference.onViewInvisible(); - verify(mMediaPlayer).release(); + verify(mAnimationController).release(); } @Test public void updateViewStates_paused_updatesViews() { - when(mMediaPlayer.isPlaying()).thenReturn(true); - mVideoPreference.updateViewStates(fakePreview, fakePlayButton); + mAnimationController.start(); + + mVideoPreference.mAnimationController.attachView(new TextureView(mContext), fakePreview, + fakePlayButton); + verify(fakePlayButton).setVisibility(eq(View.VISIBLE)); verify(fakePreview).setVisibility(eq(View.VISIBLE)); - verify(mMediaPlayer).pause(); + assertThat(mAnimationController.isPlaying()).isFalse(); } @Test public void updateViewStates_playing_updatesViews() { - when(mMediaPlayer.isPlaying()).thenReturn(false); - mVideoPreference.updateViewStates(fakePreview, fakePlayButton); + mAnimationController.pause(); + + mVideoPreference.mAnimationController.attachView(new TextureView(mContext), fakePreview, + fakePlayButton); + verify(fakePlayButton).setVisibility(eq(View.GONE)); verify(fakePreview).setVisibility(eq(View.GONE)); - verify(mMediaPlayer).start(); - } - - @Test - public void updateViewStates_noMediaPlayer_skips() { - mVideoPreference.mMediaPlayer = null; - mVideoPreference.updateViewStates(fakePreview, fakePlayButton); - verify(fakePlayButton, never()).setVisibility(anyInt()); - verify(fakePreview, never()).setVisibility(anyInt()); + assertThat(mAnimationController.isPlaying()).isTrue(); } }