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 com.android.testingcamera2; 18 19 import java.util.HashSet; 20 import java.util.Set; 21 22 import android.Manifest; 23 import android.app.Activity; 24 import android.content.pm.PackageManager; 25 import android.hardware.camera2.CameraCharacteristics; 26 import android.hardware.camera2.CameraDevice; 27 import android.hardware.camera2.CameraManager; 28 import android.hardware.camera2.CameraAccessException; 29 30 /** 31 * A central manager of camera devices and current clients for them. 32 * 33 */ 34 public class CameraOps2 extends CameraManager.AvailabilityCallback { 35 36 private final CameraManager mCameraManager; 37 private final Activity mActivity; 38 private final Set<CameraDevice> mOpenCameras = new HashSet<CameraDevice>(); 39 40 // For persisting values for permission requests 41 private static final int PERMISSIONS_REQUEST_CAMERA = 1; 42 private String mDelayedOpenId = null; 43 private CameraDevice.StateCallback mDelayedOpenListener = null; 44 CameraOps2(Activity activity)45 public CameraOps2(Activity activity) { 46 mActivity = activity; 47 mCameraManager = (CameraManager) activity.getSystemService(Activity.CAMERA_SERVICE); 48 if (mCameraManager == null) { 49 throw new AssertionError("Can't connect to camera manager!"); 50 } 51 try { 52 String[] cameraIds = mCameraManager.getCameraIdList(); 53 TLog.i("Camera count: %d", cameraIds.length); 54 for (String cameraId : cameraIds) { 55 TLog.i(" Camera %s", cameraId); 56 } 57 } catch (CameraAccessException e) { 58 TLog.e("Unable to get camera list: %s", e); 59 } 60 61 mCameraManager.registerAvailabilityCallback(this, /*handler*/null); 62 } 63 64 /** 65 * Add a listener for new camera addition events, and retrieve the list of 66 * current cameras 67 * 68 * @param listener 69 * A listener to notify on changes to camera availability 70 * @return the current list of available cameras 71 * @throws CameraAccessException 72 * if the camera manager cannot be queried 73 */ getCamerasAndListen(CameraManager.AvailabilityCallback listener)74 public String[] getCamerasAndListen(CameraManager.AvailabilityCallback listener) 75 throws CameraAccessException { 76 77 mCameraManager.registerAvailabilityCallback(listener, /*handler*/null); 78 79 return mCameraManager.getCameraIdList(); 80 } 81 removeAvailabilityCallback(CameraManager.AvailabilityCallback listener)82 public void removeAvailabilityCallback(CameraManager.AvailabilityCallback listener) { 83 mCameraManager.unregisterAvailabilityCallback(listener); 84 } 85 86 @Override onCameraAvailable(String cameraId)87 public void onCameraAvailable(String cameraId) { 88 TLog.i("Camera %s is now available", cameraId); 89 } 90 91 @Override onCameraUnavailable(String cameraId)92 public void onCameraUnavailable(String cameraId) { 93 TLog.i("Camera %s is now unavailable", cameraId); 94 } 95 96 /** 97 * Attempt to open a camera device. Returns false if the open call cannot be 98 * made or the device is already open 99 * 100 * @param cameraId id of the camera to open 101 * @param listener listener to notify of camera device state changes 102 * @return true if open call was sent successfully. The client needs to wait 103 * for its listener to be called to determine if open will succeed. 104 */ openCamera(String cameraId, CameraDevice.StateCallback listener)105 public boolean openCamera(String cameraId, CameraDevice.StateCallback listener) { 106 for (CameraDevice camera : mOpenCameras) { 107 if (camera.getId() == cameraId) { 108 TLog.e("Camera %s is already open", cameraId); 109 return false; 110 } 111 } 112 if ((mActivity.checkSelfPermission(Manifest.permission.CAMERA) 113 != PackageManager.PERMISSION_GRANTED) 114 || (mActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) 115 != PackageManager.PERMISSION_GRANTED)) { 116 TLog.i("Requesting camera/storage permissions"); 117 118 mDelayedOpenId = cameraId; 119 mDelayedOpenListener = listener; 120 121 mActivity.requestPermissions(new String[] { 122 Manifest.permission.CAMERA, 123 Manifest.permission.WRITE_EXTERNAL_STORAGE }, 124 PERMISSIONS_REQUEST_CAMERA); 125 return false; 126 } 127 128 return doOpenCamera(cameraId, listener); 129 } 130 doOpenCamera(String cameraId, CameraDevice.StateCallback listener)131 private boolean doOpenCamera(String cameraId, CameraDevice.StateCallback listener) { 132 try { 133 DeviceStateCallback proxyListener = new DeviceStateCallback(listener); 134 mCameraManager.openCamera(cameraId, proxyListener, null); 135 } catch (CameraAccessException e) { 136 TLog.e("Unable to open camera %s.", e, cameraId); 137 return false; 138 } 139 140 return true; 141 } 142 onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)143 public void onRequestPermissionsResult (int requestCode, String[] permissions, 144 int[] grantResults) { 145 if (requestCode == PERMISSIONS_REQUEST_CAMERA) { 146 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 147 TLog.i("Camera permission granted"); 148 if (mDelayedOpenId != null && mDelayedOpenListener != null) { 149 doOpenCamera(mDelayedOpenId, mDelayedOpenListener); 150 } 151 mDelayedOpenId = null; 152 mDelayedOpenListener = null; 153 } else { 154 TLog.i("Camera permission denied, not opening camera"); 155 if (mDelayedOpenId != null && mDelayedOpenListener != null) { 156 mDelayedOpenListener.onError(null, 157 CameraDevice.StateCallback.ERROR_CAMERA_DISABLED); 158 mDelayedOpenId = null; 159 mDelayedOpenListener = null; 160 } 161 } 162 if (grantResults[1] == PackageManager.PERMISSION_GRANTED) { 163 TLog.i("Storage permission granted"); 164 } else { 165 TLog.i("Storage permission not granted; saving will not work"); 166 } 167 } 168 } 169 getCameraInfo(String cameraId)170 public CameraCharacteristics getCameraInfo(String cameraId) { 171 try { 172 return mCameraManager.getCameraCharacteristics(cameraId); 173 } catch (CameraAccessException e) { 174 TLog.e("Unable to get camera characteristics for camera %s.", e, cameraId); 175 } 176 return null; 177 } 178 179 private class DeviceStateCallback extends CameraDevice.StateCallback { 180 181 private final CameraDevice.StateCallback mClientListener; 182 DeviceStateCallback(CameraDevice.StateCallback clientListener)183 public DeviceStateCallback(CameraDevice.StateCallback clientListener) { 184 mClientListener = clientListener; 185 } 186 187 @Override onClosed(CameraDevice camera)188 public void onClosed(CameraDevice camera) { 189 mOpenCameras.remove(camera); 190 TLog.i("Camera %s now closed", camera.getId()); 191 mClientListener.onClosed(camera); 192 } 193 194 @Override onDisconnected(CameraDevice camera)195 public void onDisconnected(CameraDevice camera) { 196 TLog.i("Camera %s now disconnected", camera.getId()); 197 mClientListener.onDisconnected(camera); 198 } 199 200 @Override onError(CameraDevice camera, int error)201 public void onError(CameraDevice camera, int error) { 202 TLog.i("Camera %s encountered error: %d", camera.getId(), error); 203 mClientListener.onError(camera, error); 204 } 205 206 @Override onOpened(CameraDevice camera)207 public void onOpened(CameraDevice camera) { 208 mOpenCameras.add(camera); 209 TLog.i("Camera %s now open", camera.getId()); 210 mClientListener.onOpened(camera); 211 } 212 213 } 214 } 215