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 changeSucceeded;
77             } else {
78                 // Get a surface change callback, need to check if the size is expected.
79                 surfaceChangedDone.close();
80                 if (currentWidth == expectWidth && currentHeight == expectHeight) {
81                     return changeSucceeded;
82                 }
83                 // Do a further iteration surface change check as surfaceChanged could be called
84                 // again.
85                 changeSucceeded = false;
86             }
87             waitTimeMs -= (SystemClock.elapsedRealtime() - startTimeMs);
88         }
89 
90         // Couldn't get expected surface size change.
91         return false;
92     }
93 
94     /**
95      * Wait for surface state to become valid (surfaceCreated) / invalid (surfaceDestroyed)
96      */
waitForSurfaceState(int timeOutMs, boolean valid)97     public boolean waitForSurfaceState(int timeOutMs, boolean valid) {
98         if (timeOutMs <= 0) {
99             throw new IllegalArgumentException(
100                     String.format("timeout(%d) should be a positive number", timeOutMs));
101         }
102 
103         synchronized(surfaceLock) {
104             if (valid == surfaceValid) {
105                 return true;
106             }
107         }
108 
109         int waitTimeMs = timeOutMs;
110         boolean stateReached = false;
111         while (!stateReached && waitTimeMs > 0) {
112             long startTimeMs = SystemClock.elapsedRealtime();
113             stateReached = surfaceStateDone.block(waitTimeMs);
114             if (!stateReached) {
115                 Log.e(TAG, "Wait for surface state " + valid + " timed out after " + timeOutMs + " ms");
116                 return false;
117             } else {
118                 surfaceStateDone.close();
119                 synchronized(surfaceLock) {
120                     if (valid == surfaceValid) return true;
121                 }
122                 // Do a further iteration as surfaceDestroyed could be called
123                 // again.
124                 stateReached = false;
125             }
126             waitTimeMs -= (SystemClock.elapsedRealtime() - startTimeMs);
127         }
128 
129         // Couldn't get expected surface size change.
130         return false;
131     }
132 
133     @Override
surfaceCreated(SurfaceHolder holder)134     public void surfaceCreated(SurfaceHolder holder) {
135         Log.i(TAG, "Surface created");
136         synchronized (surfaceLock) {
137             surfaceValid = true;
138         }
139         surfaceStateDone.open();
140     }
141 
142     @Override
surfaceChanged(SurfaceHolder holder, int format, int width, int height)143     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
144         Log.i(TAG, "Surface Changed to: " + width + "x" + height);
145         synchronized (surfaceLock) {
146             currentWidth = width;
147             currentHeight = height;
148         }
149         surfaceChangedDone.open();
150     }
151 
152     @Override
surfaceDestroyed(SurfaceHolder holder)153     public void surfaceDestroyed(SurfaceHolder holder) {
154         Log.i(TAG, "Surface destroyed");
155         synchronized (surfaceLock) {
156             surfaceValid = false;
157         }
158         surfaceStateDone.open();
159     }
160 }
161