1 /*
2  * Copyright 2014 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.hardware.camera2.cts;
18 
19 import android.app.Activity;
20 import android.os.Bundle;
21 import android.os.ConditionVariable;
22 import android.os.SystemClock;
23 import android.util.Log;
24 import android.view.SurfaceHolder;
25 import android.view.SurfaceView;
26 import android.camera.cts.R;
27 
28 public class Camera2SurfaceViewCtsActivity extends Activity implements SurfaceHolder.Callback {
29     private final static String TAG = "Camera2SurfaceViewCtsActivity";
30     private final ConditionVariable surfaceChangedDone = new ConditionVariable();
31     private final ConditionVariable surfaceStateDone = new ConditionVariable();
32 
33     private SurfaceView mSurfaceView;
34     private int currentWidth = 0;
35     private int currentHeight = 0;
36     private boolean surfaceValid = false;
37 
38     private final Object surfaceLock = new Object();
39 
40 
41     @Override
onCreate(Bundle savedInstanceState)42     protected void onCreate(Bundle savedInstanceState) {
43         super.onCreate(savedInstanceState);
44 
45         setContentView(R.layout.surface_view_2);
46         mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
47         mSurfaceView.getHolder().addCallback(this);
48     }
49 
getSurfaceView()50     public SurfaceView getSurfaceView() {
51         return mSurfaceView;
52     }
53 
waitForSurfaceSizeChanged(int timeOutMs, int expectWidth, int expectHeight)54     public boolean waitForSurfaceSizeChanged(int timeOutMs, int expectWidth, int expectHeight) {
55         if (timeOutMs <= 0 || expectWidth <= 0 || expectHeight <= 0) {
56             throw new IllegalArgumentException(
57                     String.format(
58                             "timeout(%d), expectWidth(%d), and expectHeight(%d) " +
59                             "should all be positive numbers",
60                             timeOutMs, expectWidth, expectHeight));
61         }
62 
63         synchronized(surfaceLock) {
64             if (expectWidth == currentWidth && expectHeight == currentHeight) {
65                 return true;
66             }
67         }
68 
69         int waitTimeMs = timeOutMs;
70         boolean changeSucceeded = false;
71         while (!changeSucceeded && waitTimeMs > 0) {
72             long startTimeMs = SystemClock.elapsedRealtime();
73             changeSucceeded = surfaceChangedDone.block(waitTimeMs);
74             if (!changeSucceeded) {
75                 Log.e(TAG, "Wait for surface change timed out after " + timeOutMs + " ms");
76                 return false;
77             } else {
78                 // Get a surface change callback, need to check if the size is expected.
79                 surfaceChangedDone.close();
80                 synchronized(surfaceLock) {
81                     if (expectWidth == currentWidth && expectHeight == currentHeight) {
82                         return true;
83                     } else {
84                         Log.i(TAG, "Wait for surface changed to " + expectWidth + "x" +
85                                 "expectHeight. Got " + currentWidth + "x" + currentHeight +
86                                 ". Keep waiting");
87                     }
88                 }
89                 // Do a further iteration surface change check as surfaceChanged could be called
90                 // again.
91                 changeSucceeded = false;
92             }
93             waitTimeMs -= (SystemClock.elapsedRealtime() - startTimeMs);
94         }
95 
96         // Couldn't get expected surface size change.
97         Log.e(TAG, "Wait for surface change timed out after " + timeOutMs + " ms");
98         return false;
99     }
100 
101     /**
102      * Wait for surface state to become valid (surfaceCreated) / invalid (surfaceDestroyed)
103      */
waitForSurfaceState(int timeOutMs, boolean valid)104     public boolean waitForSurfaceState(int timeOutMs, boolean valid) {
105         if (timeOutMs <= 0) {
106             throw new IllegalArgumentException(
107                     String.format("timeout(%d) should be a positive number", timeOutMs));
108         }
109 
110         synchronized(surfaceLock) {
111             if (valid == surfaceValid) {
112                 return true;
113             }
114         }
115 
116         int waitTimeMs = timeOutMs;
117         boolean stateReached = false;
118         while (!stateReached && waitTimeMs > 0) {
119             long startTimeMs = SystemClock.elapsedRealtime();
120             stateReached = surfaceStateDone.block(waitTimeMs);
121             if (!stateReached) {
122                 Log.e(TAG, "Wait for surface state " + valid + " timed out after " + timeOutMs + " ms");
123                 return false;
124             } else {
125                 surfaceStateDone.close();
126                 synchronized(surfaceLock) {
127                     if (valid == surfaceValid) return true;
128                 }
129                 // Do a further iteration as surfaceDestroyed could be called
130                 // again.
131                 stateReached = false;
132             }
133             waitTimeMs -= (SystemClock.elapsedRealtime() - startTimeMs);
134         }
135 
136         // Couldn't get expected surface size change.
137         return false;
138     }
139 
140     @Override
surfaceCreated(SurfaceHolder holder)141     public void surfaceCreated(SurfaceHolder holder) {
142         Log.i(TAG, "Surface created");
143         synchronized (surfaceLock) {
144             surfaceValid = true;
145         }
146         surfaceStateDone.open();
147     }
148 
149     @Override
surfaceChanged(SurfaceHolder holder, int format, int width, int height)150     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
151         Log.i(TAG, "Surface Changed to: " + width + "x" + height);
152         synchronized (surfaceLock) {
153             currentWidth = width;
154             currentHeight = height;
155         }
156         surfaceChangedDone.open();
157     }
158 
159     @Override
surfaceDestroyed(SurfaceHolder holder)160     public void surfaceDestroyed(SurfaceHolder holder) {
161         Log.i(TAG, "Surface destroyed");
162         synchronized (surfaceLock) {
163             surfaceValid = false;
164         }
165         surfaceStateDone.open();
166     }
167 }
168