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 com.android.cts.devicepolicy;
18 
19 import android.hardware.camera2.CameraDevice;
20 import android.hardware.camera2.CameraManager;
21 import android.os.Handler;
22 import android.util.Log;
23 import java.util.concurrent.CountDownLatch;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.atomic.AtomicBoolean;
26 
27 /**
28  * A util class to help open camera in a blocking way.
29  */
30 public class CameraUtils {
31 
32     private static final String TAG = "CameraUtils";
33 
34     /**
35      * @return true if success to open camera, false otherwise.
36      */
blockUntilOpenCamera(CameraManager cameraManager, Handler handler)37     public static boolean blockUntilOpenCamera(CameraManager cameraManager, Handler handler) {
38         try {
39             String[] cameraIdList = cameraManager.getCameraIdList();
40             if (cameraIdList == null || cameraIdList.length == 0) {
41                 return false;
42             }
43             String cameraId = cameraIdList[0];
44             CameraCallback callback = new CameraCallback();
45             cameraManager.openCamera(cameraId, callback, handler);
46             return callback.waitForResult();
47         } catch (Exception ex) {
48             // No matter what is going wrong, it means fail to open camera.
49             ex.printStackTrace();
50             return false;
51         }
52     }
53 
54     /**
55      * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state.
56      */
57     private static class CameraCallback extends CameraDevice.StateCallback {
58 
59         private static final int OPEN_TIMEOUT_SECONDS = 5;
60 
61         private final CountDownLatch mLatch = new CountDownLatch(1);
62 
63         private AtomicBoolean mResult = new AtomicBoolean(false);
64 
65         @Override
onOpened(CameraDevice cameraDevice)66         public void onOpened(CameraDevice cameraDevice) {
67             Log.d(TAG, "open camera successfully");
68             mResult.set(true);
69             if (cameraDevice != null) {
70                 cameraDevice.close();
71             }
72             mLatch.countDown();
73         }
74 
75         @Override
onDisconnected(CameraDevice cameraDevice)76         public void onDisconnected(CameraDevice cameraDevice) {
77             Log.d(TAG, "disconnect camera");
78             mLatch.countDown();
79         }
80 
81         @Override
onError(CameraDevice cameraDevice, int error)82         public void onError(CameraDevice cameraDevice, int error) {
83             Log.e(TAG, "Fail to open camera, error code = " + error);
84             mLatch.countDown();
85         }
86 
waitForResult()87         public boolean waitForResult() throws InterruptedException {
88             mLatch.await(OPEN_TIMEOUT_SECONDS, TimeUnit.SECONDS);
89             return mResult.get();
90         }
91     }
92 }
93