1/* 2 * Copyright (C) 2016 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 */ 16package androidx.leanback.app; 17 18import static org.junit.Assert.assertEquals; 19import static org.junit.Assert.assertFalse; 20import static org.junit.Assert.assertNotNull; 21import static org.junit.Assert.assertNotSame; 22import static org.junit.Assert.assertTrue; 23 24import android.net.Uri; 25import android.os.Bundle; 26import android.os.SystemClock; 27import android.support.test.InstrumentationRegistry; 28import android.support.test.filters.LargeTest; 29import android.support.test.runner.AndroidJUnit4; 30import android.view.LayoutInflater; 31import android.view.SurfaceHolder; 32import android.view.View; 33import android.view.ViewGroup; 34 35import androidx.leanback.media.MediaPlayerGlue; 36import androidx.leanback.media.PlaybackGlue; 37import androidx.leanback.media.PlaybackGlueHost; 38import androidx.leanback.test.R; 39import androidx.leanback.testutils.PollingCheck; 40 41import org.junit.Test; 42import org.junit.runner.RunWith; 43 44@LargeTest 45@RunWith(AndroidJUnit4.class) 46public class VideoSupportFragmentTest extends SingleSupportFragmentTestBase { 47 48 public static class Fragment_setSurfaceViewCallbackBeforeCreate extends VideoSupportFragment { 49 boolean mSurfaceCreated; 50 @Override 51 public View onCreateView( 52 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 53 54 setSurfaceHolderCallback(new SurfaceHolder.Callback() { 55 @Override 56 public void surfaceCreated(SurfaceHolder holder) { 57 mSurfaceCreated = true; 58 } 59 60 @Override 61 public void surfaceChanged(SurfaceHolder holder, int format, int width, 62 int height) { 63 } 64 65 @Override 66 public void surfaceDestroyed(SurfaceHolder holder) { 67 mSurfaceCreated = false; 68 } 69 }); 70 71 return super.onCreateView(inflater, container, savedInstanceState); 72 } 73 } 74 75 @Test 76 public void setSurfaceViewCallbackBeforeCreate() { 77 final SingleSupportFragmentTestActivity activity = 78 launchAndWaitActivity(Fragment_setSurfaceViewCallbackBeforeCreate.class, 1000); 79 Fragment_setSurfaceViewCallbackBeforeCreate fragment1 = 80 (Fragment_setSurfaceViewCallbackBeforeCreate) activity.getTestFragment(); 81 assertNotNull(fragment1); 82 assertTrue(fragment1.mSurfaceCreated); 83 84 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 85 @Override 86 public void run() { 87 activity.getSupportFragmentManager().beginTransaction() 88 .replace(R.id.main_frame, new Fragment_setSurfaceViewCallbackBeforeCreate()) 89 .commitAllowingStateLoss(); 90 } 91 }); 92 SystemClock.sleep(500); 93 94 assertFalse(fragment1.mSurfaceCreated); 95 96 Fragment_setSurfaceViewCallbackBeforeCreate fragment2 = 97 (Fragment_setSurfaceViewCallbackBeforeCreate) activity.getTestFragment(); 98 assertNotNull(fragment2); 99 assertTrue(fragment2.mSurfaceCreated); 100 assertNotSame(fragment1, fragment2); 101 } 102 103 @Test 104 public void setSurfaceViewCallbackAfterCreate() { 105 SingleSupportFragmentTestActivity activity = launchAndWaitActivity(VideoSupportFragment.class, 1000); 106 VideoSupportFragment fragment = (VideoSupportFragment) activity.getTestFragment(); 107 108 assertNotNull(fragment); 109 110 final boolean[] surfaceCreated = new boolean[1]; 111 fragment.setSurfaceHolderCallback(new SurfaceHolder.Callback() { 112 @Override 113 public void surfaceCreated(SurfaceHolder holder) { 114 surfaceCreated[0] = true; 115 } 116 117 @Override 118 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 119 } 120 121 @Override 122 public void surfaceDestroyed(SurfaceHolder holder) { 123 surfaceCreated[0] = false; 124 } 125 }); 126 assertTrue(surfaceCreated[0]); 127 } 128 129 public static class Fragment_withVideoPlayer extends VideoSupportFragment { 130 MediaPlayerGlue mGlue; 131 int mOnCreateCalled; 132 int mOnCreateViewCalled; 133 int mOnDestroyViewCalled; 134 int mOnDestroyCalled; 135 int mGlueAttachedToHost; 136 int mGlueDetachedFromHost; 137 int mGlueOnReadyForPlaybackCalled; 138 139 public Fragment_withVideoPlayer() { 140 setRetainInstance(true); 141 } 142 143 @Override 144 public void onCreate(Bundle savedInstanceState) { 145 mOnCreateCalled++; 146 super.onCreate(savedInstanceState); 147 mGlue = new MediaPlayerGlue(getActivity()) { 148 @Override 149 protected void onDetachedFromHost() { 150 mGlueDetachedFromHost++; 151 super.onDetachedFromHost(); 152 } 153 154 @Override 155 protected void onAttachedToHost(PlaybackGlueHost host) { 156 super.onAttachedToHost(host); 157 mGlueAttachedToHost++; 158 } 159 }; 160 mGlue.setMode(MediaPlayerGlue.REPEAT_ALL); 161 mGlue.setArtist("Leanback"); 162 mGlue.setTitle("Leanback team at work"); 163 mGlue.setMediaSource( 164 Uri.parse("android.resource://androidx.leanback.test/raw/video")); 165 mGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() { 166 @Override 167 public void onPreparedStateChanged(PlaybackGlue glue) { 168 if (glue.isPrepared()) { 169 mGlueOnReadyForPlaybackCalled++; 170 mGlue.play(); 171 } 172 } 173 }); 174 mGlue.setHost(new VideoSupportFragmentGlueHost(this)); 175 } 176 177 @Override 178 public View onCreateView(LayoutInflater inflater, ViewGroup container, 179 Bundle savedInstanceState) { 180 mOnCreateViewCalled++; 181 return super.onCreateView(inflater, container, savedInstanceState); 182 } 183 184 @Override 185 public void onDestroyView() { 186 mOnDestroyViewCalled++; 187 super.onDestroyView(); 188 } 189 190 @Override 191 public void onDestroy() { 192 mOnDestroyCalled++; 193 super.onDestroy(); 194 } 195 } 196 197 @Test 198 public void mediaPlayerGlueInVideoSupportFragment() { 199 final SingleSupportFragmentTestActivity activity = 200 launchAndWaitActivity(Fragment_withVideoPlayer.class, 1000); 201 final Fragment_withVideoPlayer fragment = (Fragment_withVideoPlayer) 202 activity.getTestFragment(); 203 204 PollingCheck.waitFor(5000, new PollingCheck.PollingCheckCondition() { 205 @Override 206 public boolean canProceed() { 207 return fragment.mGlue.isMediaPlaying(); 208 } 209 }); 210 211 assertEquals(1, fragment.mOnCreateCalled); 212 assertEquals(1, fragment.mOnCreateViewCalled); 213 assertEquals(0, fragment.mOnDestroyViewCalled); 214 assertEquals(1, fragment.mGlueOnReadyForPlaybackCalled); 215 View fragmentViewBeforeRecreate = fragment.getView(); 216 217 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 218 @Override 219 public void run() { 220 activity.recreate(); 221 } 222 }); 223 224 PollingCheck.waitFor(5000, new PollingCheck.PollingCheckCondition() { 225 @Override 226 public boolean canProceed() { 227 return fragment.mOnCreateViewCalled == 2 && fragment.mGlue.isMediaPlaying(); 228 } 229 }); 230 View fragmentViewAfterRecreate = fragment.getView(); 231 232 assertNotSame(fragmentViewBeforeRecreate, fragmentViewAfterRecreate); 233 assertEquals(1, fragment.mOnCreateCalled); 234 assertEquals(2, fragment.mOnCreateViewCalled); 235 assertEquals(1, fragment.mOnDestroyViewCalled); 236 237 assertEquals(1, fragment.mGlueAttachedToHost); 238 assertEquals(0, fragment.mGlueDetachedFromHost); 239 assertEquals(1, fragment.mGlueOnReadyForPlaybackCalled); 240 241 activity.finish(); 242 PollingCheck.waitFor(5000, new PollingCheck.PollingCheckCondition() { 243 @Override 244 public boolean canProceed() { 245 return fragment.mGlueDetachedFromHost == 1; 246 } 247 }); 248 assertEquals(2, fragment.mOnDestroyViewCalled); 249 assertEquals(1, fragment.mOnDestroyCalled); 250 } 251 252} 253