• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 
17 package android.mediav2.common.cts;
18 
19 import android.app.Activity;
20 import android.os.Bundle;
21 import android.os.SystemClock;
22 import android.util.Log;
23 import android.util.Pair;
24 import android.view.Surface;
25 import android.view.SurfaceHolder;
26 import android.view.SurfaceView;
27 import android.view.View;
28 import android.view.WindowManager;
29 import android.widget.LinearLayout;
30 
31 import java.util.ArrayList;
32 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.locks.Condition;
34 import java.util.concurrent.locks.Lock;
35 import java.util.concurrent.locks.ReentrantLock;
36 
37 public class CodecDynamicTestActivity extends Activity implements SurfaceHolder.Callback {
38     private static final String LOG_TAG = CodecDynamicTestActivity.class.getSimpleName();
39 
40     private final int mMaxSurfaces = 32;
41     private LinearLayout mLayOutList;
42     private final ArrayList<SurfaceView> mSurfaceViews = new ArrayList<>();
43     private final ArrayList<SurfaceHolder> mHolders = new ArrayList<>();
44     private final ArrayList<Surface> mSurfaces = new ArrayList<>();
45     private final Lock[] mLocks = new Lock[mMaxSurfaces];
46     private final Condition[] mConditions = new Condition[mMaxSurfaces];
47     private final ReentrantLock mMutex = new ReentrantLock();
48     private final boolean[] mIsUsable = new boolean[mMaxSurfaces];
49 
addSurfaceView()50     public int addSurfaceView() {
51         if (mMaxSurfaces == mSurfaceViews.size()) {
52             throw new RuntimeException("number of surfaceViews exceed preconfigured limit");
53         }
54         View view = getLayoutInflater().inflate(R.layout.display_surface_layout, mLayOutList,
55                 false);
56         SurfaceView surfaceView = view.findViewById(R.id.add_surface);
57         SurfaceHolder holder = surfaceView.getHolder();
58         holder.addCallback(this);
59         int index = mSurfaceViews.size();
60         mLocks[index].lock();
61         mSurfaceViews.add(surfaceView);
62         mSurfaces.add(null);
63         mHolders.add(holder);
64         mLocks[index].unlock();
65         runOnUiThread(() -> mLayOutList.addView(view));
66         return index;
67     }
68 
69     @Override
onCreate(Bundle savedInstanceState)70     protected void onCreate(Bundle savedInstanceState) {
71         Log.v(LOG_TAG, "onCreate");
72         super.onCreate(savedInstanceState);
73 
74         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
75         setTurnScreenOn(true);
76         setShowWhenLocked(true);
77 
78         setContentView(R.layout.main_layout);
79         mLayOutList = findViewById(R.id.layout_list);
80         for (int i = 0; i < mMaxSurfaces; i++) {
81             mIsUsable[i] = false;
82             mLocks[i] = new ReentrantLock();
83             mConditions[i] = mLocks[i].newCondition();
84         }
85     }
86 
87     @Override
surfaceCreated(SurfaceHolder holder)88     public void surfaceCreated(SurfaceHolder holder) {
89         Log.v(LOG_TAG, "surface created");
90         int index = mHolders.indexOf(holder);
91         mLocks[index].lock();
92         mSurfaces.set(index, mHolders.get(index).getSurface());
93         mLocks[index].unlock();
94     }
95 
96     @Override
surfaceChanged(SurfaceHolder holder, int format, int width, int height)97     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
98         Log.v(LOG_TAG, "surface changed " + format + " " + width + " " + height);
99     }
100 
101     @Override
surfaceDestroyed(SurfaceHolder holder)102     public void surfaceDestroyed(SurfaceHolder holder) {
103         Log.v(LOG_TAG, "surface deleted");
104         int index = mHolders.indexOf(holder);
105         markSurface(index, false);
106         mLocks[index].lock();
107         mSurfaces.set(index, null);
108         mLocks[index].unlock();
109     }
110 
waitTillSurfaceIsCreated(int index)111     public void waitTillSurfaceIsCreated(int index) throws InterruptedException {
112         final long mWaitTimeMs = 1000;
113         final int retries = 3;
114         mLocks[index].lock();
115         final long start = SystemClock.elapsedRealtime();
116         while ((SystemClock.elapsedRealtime() - start) < (retries * mWaitTimeMs)
117                 && mSurfaces.get(index) == null) {
118             mConditions[index].await(mWaitTimeMs, TimeUnit.MILLISECONDS);
119         }
120         mLocks[index].unlock();
121         if (mSurfaces.get(index) == null) {
122             throw new InterruptedException("Taking too long to attach a SurfaceView to a window.");
123         }
124         markSurface(index, true);
125     }
126 
getSurface()127     public Pair<Integer, Surface> getSurface() {
128         Pair<Integer, Surface> obj = null;
129         mMutex.lock();
130         for (int index = 0; index < mSurfaces.size(); index++) {
131             if (mIsUsable[index]) {
132                 mIsUsable[index] = false;
133                 obj = Pair.create(index, mSurfaces.get(index));
134                 break;
135             }
136         }
137         mMutex.unlock();
138         return obj;
139     }
140 
markSurface(int index, boolean usable)141     public void markSurface(int index, boolean usable) {
142         mMutex.lock();
143         mIsUsable[index] = usable;
144         mMutex.unlock();
145     }
146 }
147