1 /* 2 * Copyright (C) 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.permission.cts; 18 19 import static com.android.ex.camera2.blocking.BlockingStateCallback.*; 20 21 import android.content.Context; 22 import android.hardware.camera2.CameraCharacteristics; 23 import android.hardware.camera2.CameraCharacteristics.Key; 24 import android.hardware.camera2.CameraDevice; 25 import android.hardware.camera2.CameraManager; 26 import android.os.Handler; 27 import android.os.HandlerThread; 28 import android.platform.test.annotations.Presubmit; 29 import android.test.AndroidTestCase; 30 import android.util.Log; 31 32 import com.android.ex.camera2.blocking.BlockingCameraManager; 33 import com.android.ex.camera2.blocking.BlockingStateCallback; 34 35 import java.util.ArrayList; 36 import java.util.List; 37 38 /** 39 * Tests for Camera2 API related Permissions. Currently, this means 40 * android.permission.CAMERA. 41 */ 42 public class Camera2PermissionTest extends AndroidTestCase { 43 private static final String TAG = "Camera2PermissionTest"; 44 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 45 private static final int CAMERA_CLOSE_TIMEOUT_MS = 2000; 46 47 private CameraManager mCameraManager; 48 private CameraDevice mCamera; 49 private BlockingStateCallback mCameraListener; 50 private String[] mCameraIds; 51 protected Handler mHandler; 52 protected HandlerThread mHandlerThread; 53 54 @Override setContext(Context context)55 public void setContext(Context context) { 56 super.setContext(context); 57 mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 58 assertNotNull("Can't connect to camera manager!", mCameraManager); 59 } 60 61 /** 62 * Set up the camera2 test case required environments, including CameraManager, 63 * HandlerThread, Camera IDs, and CameraStateCallback etc. 64 */ 65 @Override setUp()66 protected void setUp() throws Exception { 67 super.setUp(); 68 mCameraIds = mCameraManager.getCameraIdList(); 69 assertNotNull("Camera ids shouldn't be null", mCameraIds); 70 mHandlerThread = new HandlerThread(TAG); 71 mHandlerThread.start(); 72 mHandler = new Handler(mHandlerThread.getLooper()); 73 mCameraListener = new BlockingStateCallback(); 74 } 75 76 @Override tearDown()77 protected void tearDown() throws Exception { 78 mHandlerThread.quitSafely(); 79 mHandler = null; 80 81 super.tearDown(); 82 } 83 84 /** 85 * Attempt to open camera. Requires Permission: 86 * {@link android.Manifest.permission#CAMERA}. 87 */ testCameraOpen()88 public void testCameraOpen() throws Exception { 89 for (String id : mCameraIds) { 90 try { 91 openCamera(id); 92 fail("Was able to open camera " + id + " with no permission"); 93 } 94 catch (SecurityException e) { 95 // expected 96 } finally { 97 closeCamera(); 98 } 99 } 100 } 101 102 /** 103 * Check that no system cameras can be discovered without 104 * {@link android.Manifest.permission#CAMERA} and android.permission.SYSTEM_CAMERA 105 */ testSystemCameraDiscovery()106 public void testSystemCameraDiscovery() throws Exception { 107 for (String id : mCameraIds) { 108 Log.i(TAG, "testSystemCameraDiscovery for camera id " + id); 109 CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(id); 110 assertNotNull("Camera characteristics shouldn't be null", characteristics); 111 int[] availableCapabilities = 112 characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES); 113 assertTrue("Camera capabilities shouldn't be null", availableCapabilities != null); 114 List<Integer> capList = toList(availableCapabilities); 115 assertFalse("System camera device " + id + " should not be public", 116 capList.contains( 117 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA)); 118 } 119 } 120 121 /** 122 * Check the absence of camera characteristics keys that require Permission: 123 * {@link android.Manifest.permission#CAMERA}. 124 */ testCameraCharacteristicsNeedingPermission()125 public void testCameraCharacteristicsNeedingPermission() throws Exception { 126 for (String id : mCameraIds) { 127 CameraCharacteristics capabilities = mCameraManager.getCameraCharacteristics(id); 128 assertNotNull("Camera characteristics shouldn't be null", capabilities); 129 List<Key<?>> keysNeedingPermission = capabilities.getKeysNeedingPermission(); 130 if (keysNeedingPermission == null) { 131 continue; 132 } 133 List<Key<?>> keys = capabilities.getKeys(); 134 assertNotNull("Camera characteristics key list shouldn't be null", keys); 135 for (Key<?> key : keysNeedingPermission) { 136 assertEquals("Key " + key.getName() + " needing permission is part of the" + 137 " available characteristics keys", -1, keys.indexOf(key)); 138 assertNull("Key " + key.getName() + " needing permission must not present" + 139 " in camera characteristics", capabilities.get(key)); 140 } 141 } 142 } 143 144 /** 145 * Add and remove availability listeners should work without permission. 146 */ 147 @Presubmit testAvailabilityCallback()148 public void testAvailabilityCallback() throws Exception { 149 DummyCameraListener availabilityListener = new DummyCameraListener(); 150 // Remove a not-registered listener is a no-op. 151 mCameraManager.unregisterAvailabilityCallback(availabilityListener); 152 mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler); 153 mCameraManager.unregisterAvailabilityCallback(availabilityListener); 154 mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler); 155 mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler); 156 mCameraManager.unregisterAvailabilityCallback(availabilityListener); 157 // Remove a previously-added listener second time is a no-op. 158 mCameraManager.unregisterAvailabilityCallback(availabilityListener); 159 } 160 161 private class DummyCameraListener extends CameraManager.AvailabilityCallback { 162 @Override onCameraAvailable(String cameraId)163 public void onCameraAvailable(String cameraId) { 164 } 165 166 @Override onCameraUnavailable(String cameraId)167 public void onCameraUnavailable(String cameraId) { 168 } 169 } 170 openCamera(String cameraId)171 private void openCamera(String cameraId) throws Exception { 172 mCamera = (new BlockingCameraManager(mCameraManager)).openCamera( 173 cameraId, mCameraListener, mHandler); 174 } 175 toList(int[] array)176 private static List<Integer> toList(int[] array) { 177 List<Integer> list = new ArrayList<Integer>(); 178 for (int i : array) { 179 list.add(i); 180 } 181 return list; 182 } 183 closeCamera()184 private void closeCamera() { 185 if (mCamera != null) { 186 mCamera.close(); 187 mCameraListener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS); 188 mCamera = null; 189 } 190 } 191 } 192