1 /*
2  * Copyright (C) 2024 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.virtualdevice.cts.defaultcameraaccesstestbase;
18 
19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.junit.Assume.assumeNotNull;
24 
25 import android.app.Activity;
26 import android.companion.virtual.VirtualDeviceManager.VirtualDevice;
27 import android.hardware.camera2.CameraAccessException;
28 import android.hardware.camera2.CameraDevice;
29 import android.hardware.camera2.CameraManager;
30 import android.hardware.display.DisplayManager;
31 import android.hardware.display.VirtualDisplay;
32 import android.os.ConditionVariable;
33 import android.virtualdevice.cts.common.VirtualDeviceRule;
34 
35 import androidx.annotation.NonNull;
36 import androidx.test.platform.app.InstrumentationRegistry;
37 
38 import org.junit.Rule;
39 
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.concurrent.TimeUnit;
43 
44 public abstract class DefaultCameraAccessTestBase {
45 
46     private static final long TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(3);
47     private static final int NO_ERROR = 0;
48 
49     @Rule
50     public VirtualDeviceRule virtualDeviceRule = VirtualDeviceRule.createDefault();
51 
verifyCameraAccessAllowed(VirtualDevice virtualDevice)52     protected void verifyCameraAccessAllowed(VirtualDevice virtualDevice) throws Exception {
53         Activity activity = setupWithVirtualDevice(virtualDevice);
54         String[] cameras = getCameraIds();
55         for (String cameraId : cameras) {
56             assertThat(accessCameraFromActivity(activity, cameraId)).isEqualTo(NO_ERROR);
57         }
58     }
59 
verifyCameraAccessBlocked(VirtualDevice virtualDevice)60     protected void verifyCameraAccessBlocked(VirtualDevice virtualDevice) throws Exception {
61         Activity activity = setupWithVirtualDevice(virtualDevice);
62         String[] cameras = getCameraIds();
63         for (String cameraId : cameras) {
64             assertThat(accessCameraFromActivity(activity, cameraId)).isGreaterThan(NO_ERROR);
65         }
66     }
67 
setupWithVirtualDevice(VirtualDevice virtualDevice)68     private Activity setupWithVirtualDevice(VirtualDevice virtualDevice) {
69         VirtualDisplay virtualDisplay = virtualDeviceRule.createManagedVirtualDisplayWithFlags(
70                 virtualDevice,
71                 DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
72                         | DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED
73                         | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
74         return virtualDeviceRule.startActivityOnDisplaySync(
75                 virtualDisplay, Activity.class);
76     }
77 
getCameraIds()78     private String[] getCameraIds() throws Exception {
79         CameraManager manager = getApplicationContext().getSystemService(CameraManager.class);
80         String[] cameras = manager.getCameraIdList();
81         assumeNotNull((Object) cameras);
82         return cameras;
83     }
84 
accessCameraFromActivity(Activity activity, String cameraId)85     private int accessCameraFromActivity(Activity activity, String cameraId) {
86         ConditionVariable cond = new ConditionVariable();
87         final CameraManager cameraManager = activity.getSystemService(CameraManager.class);
88         final int[] cameraError = {NO_ERROR};
89         final List<CameraDevice> cameraDevices = new ArrayList<>();
90         final CameraDevice.StateCallback cameraCallback = new CameraDevice.StateCallback() {
91             @Override
92             public void onOpened(@NonNull CameraDevice cameraDevice) {
93                 cameraDevices.add(cameraDevice);
94             }
95 
96             @Override
97             public void onDisconnected(@NonNull CameraDevice cameraDevice) {
98                 cameraError[0] = CameraDevice.StateCallback.ERROR_CAMERA_DISABLED;
99                 cond.open();
100             }
101 
102             @Override
103             public void onError(@NonNull CameraDevice cameraDevice, int error) {
104                 cameraError[0] = error;
105                 cond.open();
106             }
107         };
108 
109         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
110             try {
111                 cameraManager.openCamera(cameraId, cameraCallback, null);
112             } catch (CameraAccessException e) {
113                 cameraError[0] = CameraDevice.StateCallback.ERROR_CAMERA_DISABLED;
114             }
115         });
116         cond.block(TIMEOUT_MILLIS);
117         for (CameraDevice device : cameraDevices) {
118             device.close();
119         }
120         return cameraError[0];
121     }
122 }
123