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