1 /* 2 * Copyright (C) 2009 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 package android.media.cts; 17 18 import android.app.Activity; 19 import android.content.Intent; 20 import android.media.cts.R; 21 import android.os.Build; 22 import android.os.Bundle; 23 import android.os.SystemClock; 24 import android.util.Log; 25 import android.view.Surface; 26 import android.view.SurfaceHolder; 27 import android.view.SurfaceView; 28 import android.view.Window; 29 import android.view.WindowInsets; 30 import android.view.WindowInsetsController; 31 import android.view.WindowManager; 32 33 import androidx.test.filters.SdkSuppress; 34 35 import com.android.compatibility.common.util.ApiLevelUtil; 36 37 import java.util.concurrent.TimeUnit; 38 import java.util.concurrent.locks.Condition; 39 import java.util.concurrent.locks.Lock; 40 import java.util.concurrent.locks.ReentrantLock; 41 42 public class MediaStubActivity extends Activity { 43 private static final String TAG = "MediaStubActivity"; 44 public static final String INTENT_EXTRA_NO_TITLE = "NoTitle"; 45 46 private SurfaceHolder mHolder; 47 private SurfaceHolder mHolder2; 48 49 private final Lock mLock = new ReentrantLock(); 50 private final Condition mCondition = mLock.newCondition(); 51 52 @Override onCreate(Bundle savedInstanceState)53 protected void onCreate(Bundle savedInstanceState) { 54 super.onCreate(savedInstanceState); 55 56 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 57 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R)) { 58 Intent intent = getIntent(); 59 if (intent.getBooleanExtra(INTENT_EXTRA_NO_TITLE, false)) { 60 hideTitle(); 61 } 62 } 63 setTurnScreenOn(true); 64 setShowWhenLocked(true); 65 66 setContentView(R.layout.mediaplayer); 67 68 SurfaceView surfaceV = (SurfaceView)findViewById(R.id.surface); 69 mHolder = surfaceV.getHolder(); 70 71 SurfaceView surfaceV2 = (SurfaceView)findViewById(R.id.surface2); 72 mHolder2 = surfaceV2.getHolder(); 73 } 74 75 @Override onResume()76 protected void onResume() { 77 Log.i(TAG, "onResume"); 78 super.onResume(); 79 } 80 81 @Override onPause()82 protected void onPause() { 83 Log.i(TAG, "onPause"); 84 super.onPause(); 85 } 86 87 /* 88 * Wait until the surface associated with this SurfaceHolder 89 * is created. 90 */ waitTillSurfaceHolderIsCreated(Surface surface, long waitTimeMs)91 private void waitTillSurfaceHolderIsCreated(Surface surface, 92 long waitTimeMs) throws InterruptedException { 93 mLock.lock(); 94 try { 95 final long start = SystemClock.elapsedRealtime(); 96 97 while (!surface.isValid() && (SystemClock.elapsedRealtime() - start) < waitTimeMs) { 98 mCondition.await(waitTimeMs, TimeUnit.MILLISECONDS); 99 } 100 } finally { 101 mLock.unlock(); 102 } 103 if (!surface.isValid()) { 104 throw new InterruptedException("Taking too long to attach a SurfaceHolder the window."); 105 } 106 } 107 108 /* 109 * Get a valid Surface associated with the given SurfaceHolder. 110 * It will wait until the Surface is ready/created. 111 * 112 * If the surface is not ready after waiting for a predefined timeout, 113 * it will return null. 114 */ getSurface(SurfaceHolder holder)115 public Surface getSurface(SurfaceHolder holder) { 116 Surface surface = holder.getSurface(); 117 118 // Check if the surface has been create already. 119 if (surface.isValid()) { 120 return surface; 121 } 122 123 // register for information about changes to the surface 124 // so that we know when the surface associated with the SurfaceHolder 125 // is created. 126 holder.addCallback(new SurfaceHolder.Callback() { 127 @Override 128 public void surfaceCreated(SurfaceHolder surfaceHolder) { 129 Log.d(TAG, "surfaceCreated"); 130 mLock.lock(); 131 try { 132 mCondition.signalAll(); 133 } finally { 134 mLock.unlock(); 135 } 136 } 137 138 @Override 139 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 140 Log.v(TAG, "surfaceChanged: " + format + " " + width + " " + height); 141 } 142 143 @Override 144 public void surfaceDestroyed(SurfaceHolder holder) { 145 Log.d(TAG, "surfaceDestroyed"); 146 } 147 }); 148 149 // Wait until the surface is available. 150 try { 151 // Wait for at most 3 seconds for the surface to be ready. 152 waitTillSurfaceHolderIsCreated(surface, 3000); 153 } catch (InterruptedException e) { 154 Log.e(TAG, "Caught exception: " + e); 155 return null; 156 } 157 return surface; 158 } 159 getSurfaceHolder()160 public SurfaceHolder getSurfaceHolder() { 161 return mHolder; 162 } 163 getSurfaceHolder2()164 public SurfaceHolder getSurfaceHolder2() { 165 return mHolder2; 166 } 167 168 /** Note: Must be called from the thread used to create this activity. */ 169 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R) hideSystemBars()170 public void hideSystemBars() { 171 var surfaceV = (SurfaceView)findViewById(R.id.surface); 172 WindowInsetsController windowInsetsController = surfaceV.getWindowInsetsController(); 173 if (windowInsetsController == null) { 174 return; 175 } 176 // Configure the behavior of the hidden system bars 177 windowInsetsController.setSystemBarsBehavior( 178 WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); 179 // Hide both the status bar and the navigation bar 180 windowInsetsController.hide(WindowInsets.Type.systemBars()); 181 } 182 183 /** Note: Must be called before {@code setContentView}. */ 184 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R) hideTitle()185 private void hideTitle() { 186 getWindow().requestFeature(Window.FEATURE_NO_TITLE); 187 } 188 189 } 190