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 TLog.i("Requesting camera permissions"); 115 116 mDelayedOpenId = cameraId; 117 mDelayedOpenListener = listener; 118 119 mActivity.requestPermissions(new String[] {Manifest.permission.CAMERA}, 120 PERMISSIONS_REQUEST_CAMERA); 121 return false; 122 } 123 124 return doOpenCamera(cameraId, listener); 125 } 126 doOpenCamera(String cameraId, CameraDevice.StateCallback listener)127 private boolean doOpenCamera(String cameraId, CameraDevice.StateCallback listener) { 128 try { 129 DeviceStateCallback proxyListener = new DeviceStateCallback(listener); 130 mCameraManager.openCamera(cameraId, proxyListener, null); 131 } catch (CameraAccessException e) { 132 TLog.e("Unable to open camera %s.", e, cameraId); 133 return false; 134 } 135 136 return true; 137 } 138 onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)139 public void onRequestPermissionsResult (int requestCode, String[] permissions, 140 int[] grantResults) { 141 if (requestCode == PERMISSIONS_REQUEST_CAMERA) { 142 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 143 TLog.i("Camera permission granted"); 144 if (mDelayedOpenId != null && mDelayedOpenListener != null) { 145 doOpenCamera(mDelayedOpenId, mDelayedOpenListener); 146 } 147 mDelayedOpenId = null; 148 mDelayedOpenListener = null; 149 } else { 150 TLog.i("Camera permission denied, not opening camera"); 151 if (mDelayedOpenId != null && mDelayedOpenListener != null) { 152 mDelayedOpenListener.onError(null, 153 CameraDevice.StateCallback.ERROR_CAMERA_DISABLED); 154 mDelayedOpenId = null; 155 mDelayedOpenListener = null; 156 } 157 } 158 if (grantResults[1] == PackageManager.PERMISSION_GRANTED) { 159 TLog.i("Storage permission granted"); 160 } else { 161 TLog.i("Storage permission not granted; saving will not work"); 162 } 163 } 164 } 165 getCameraInfo(String cameraId)166 public CameraCharacteristics getCameraInfo(String cameraId) { 167 try { 168 return mCameraManager.getCameraCharacteristics(cameraId); 169 } catch (CameraAccessException e) { 170 TLog.e("Unable to get camera characteristics for camera %s.", e, cameraId); 171 } 172 return null; 173 } 174 175 private class DeviceStateCallback extends CameraDevice.StateCallback { 176 177 private final CameraDevice.StateCallback mClientListener; 178 DeviceStateCallback(CameraDevice.StateCallback clientListener)179 public DeviceStateCallback(CameraDevice.StateCallback clientListener) { 180 mClientListener = clientListener; 181 } 182 183 @Override onClosed(CameraDevice camera)184 public void onClosed(CameraDevice camera) { 185 mOpenCameras.remove(camera); 186 TLog.i("Camera %s now closed", camera.getId()); 187 mClientListener.onClosed(camera); 188 } 189 190 @Override onDisconnected(CameraDevice camera)191 public void onDisconnected(CameraDevice camera) { 192 TLog.i("Camera %s now disconnected", camera.getId()); 193 mClientListener.onDisconnected(camera); 194 } 195 196 @Override onError(CameraDevice camera, int error)197 public void onError(CameraDevice camera, int error) { 198 TLog.i("Camera %s encountered error: %d", camera.getId(), error); 199 mClientListener.onError(camera, error); 200 } 201 202 @Override onOpened(CameraDevice camera)203 public void onOpened(CameraDevice camera) { 204 mOpenCameras.add(camera); 205 TLog.i("Camera %s now open", camera.getId()); 206 mClientListener.onOpened(camera); 207 } 208 209 } 210 } 211