From 9547fa73ccd86bf43b6555fa42d726f0c01574e8 Mon Sep 17 00:00:00 2001 From: Raff Tsai Date: Tue, 5 Nov 2019 13:24:08 +0800 Subject: [PATCH] Fix Settings crashed on tapping on notification animation video - When preference goes back from pause state, it doesn't call through onBindViewHolder, caused surface view doesn't attach to Mediaplayer. Call attachView in initAnimationController and set SurfaceView to MediaPlayer when onSurfaceTextureUpdated to fix the issue. Fixes: 143905693 Test: manual, robolectric Change-Id: I0eceead2e4c90ca176ef0f35937898f9b9be6232 --- .../widget/MediaAnimationController.java | 14 +++++--- .../settings/widget/VideoPreference.java | 16 +++++++--- .../res/xml-mcc999/video_preference.xml | 32 +++++++++++++++++++ .../settings/widget/VideoPreferenceTest.java | 28 ++++++++++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 tests/robotests/res/xml-mcc999/video_preference.xml diff --git a/src/com/android/settings/widget/MediaAnimationController.java b/src/com/android/settings/widget/MediaAnimationController.java index eb7b3e042c1..87a53658031 100644 --- a/src/com/android/settings/widget/MediaAnimationController.java +++ b/src/com/android/settings/widget/MediaAnimationController.java @@ -33,6 +33,7 @@ import android.view.View; class MediaAnimationController implements VideoPreference.AnimationController { private MediaPlayer mMediaPlayer; private boolean mVideoReady; + private Surface mSurface; MediaAnimationController(Context context, int videoId) { final Uri videoPath = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) @@ -86,10 +87,7 @@ class MediaAnimationController implements VideoPreference.AnimationController { @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { - if (mMediaPlayer != null) { - final Surface surface = new Surface(surfaceTexture); - mMediaPlayer.setSurface(surface); - } + setSurface(surfaceTexture); } @Override @@ -105,6 +103,7 @@ class MediaAnimationController implements VideoPreference.AnimationController { @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + setSurface(surfaceTexture); if (mVideoReady) { if (preview.getVisibility() == View.VISIBLE) { preview.setVisibility(View.GONE); @@ -146,4 +145,11 @@ class MediaAnimationController implements VideoPreference.AnimationController { mMediaPlayer.start(); } } + + private void setSurface(SurfaceTexture surfaceTexture) { + if (mMediaPlayer != null && mSurface == null) { + mSurface = new Surface(surfaceTexture); + mMediaPlayer.setSurface(mSurface); + } + } } diff --git a/src/com/android/settings/widget/VideoPreference.java b/src/com/android/settings/widget/VideoPreference.java index d23bea96b16..006c13ac8f6 100644 --- a/src/com/android/settings/widget/VideoPreference.java +++ b/src/com/android/settings/widget/VideoPreference.java @@ -50,6 +50,9 @@ public class VideoPreference extends Preference { private int mAnimationId; private int mVectorAnimationId; private int mHeight = LinearLayout.LayoutParams.MATCH_PARENT - 1; // video height in pixels + private TextureView mVideo; + private ImageView mPreviewImage; + private ImageView mPlayButton; public VideoPreference(Context context) { super(context); @@ -108,19 +111,19 @@ public class VideoPreference extends Preference { return; } - final TextureView video = (TextureView) holder.findViewById(R.id.video_texture_view); - final ImageView previewImage = (ImageView) holder.findViewById(R.id.video_preview_image); - final ImageView playButton = (ImageView) holder.findViewById(R.id.video_play_button); + mVideo = (TextureView) holder.findViewById(R.id.video_texture_view); + mPreviewImage = (ImageView) holder.findViewById(R.id.video_preview_image); + mPlayButton = (ImageView) holder.findViewById(R.id.video_play_button); final AspectRatioFrameLayout layout = (AspectRatioFrameLayout) holder.findViewById( R.id.video_container); - previewImage.setImageResource(mPreviewId); + mPreviewImage.setImageResource(mPreviewId); layout.setAspectRatio(mAspectRatio); if (mHeight >= LinearLayout.LayoutParams.MATCH_PARENT) { layout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, mHeight)); } - mAnimationController.attachView(video, previewImage, playButton); + mAnimationController.attachView(mVideo, mPreviewImage, mPlayButton); } @Override @@ -164,6 +167,9 @@ public class VideoPreference extends Preference { } if (mAnimationId != 0) { mAnimationController = new MediaAnimationController(mContext, mAnimationId); + if (mVideo != null) { + mAnimationController.attachView(mVideo, mPreviewImage, mPlayButton); + } } } diff --git a/tests/robotests/res/xml-mcc999/video_preference.xml b/tests/robotests/res/xml-mcc999/video_preference.xml new file mode 100644 index 00000000000..647a82fa915 --- /dev/null +++ b/tests/robotests/res/xml-mcc999/video_preference.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java index 09ee615e0e3..3439ca40377 100644 --- a/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java @@ -27,11 +27,13 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.graphics.SurfaceTexture; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.TextureView; import android.view.View; import android.widget.ImageView; +import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceViewHolder; import com.android.settings.R; @@ -45,6 +47,7 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.shadows.androidx.fragment.FragmentController; @RunWith(RobolectricTestRunner.class) @Config(shadows = ShadowSettingsMediaPlayer.class) @@ -135,4 +138,29 @@ public class VideoPreferenceTest { verify(fakePreview).setVisibility(eq(View.GONE)); assertThat(mAnimationController.isPlaying()).isTrue(); } + + @Test + @Config(qualifiers = "mcc999") + public void onViewVisible_createAnimationController() { + final PreferenceFragmentCompat fragment = FragmentController.of( + new VideoPreferenceTest.TestFragment(), + new Bundle()) + .create() + .start() + .resume() + .get(); + + final VideoPreference vp1 = fragment.findPreference("video1"); + final VideoPreference vp2 = fragment.findPreference("video2"); + + assertThat(vp1.mAnimationController instanceof MediaAnimationController).isTrue(); + assertThat(vp2.mAnimationController instanceof VectorAnimationController).isTrue(); + } + + public static class TestFragment extends PreferenceFragmentCompat { + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.video_preference); + } + } }