/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.testingcamera2; import java.util.HashSet; import java.util.Set; import android.Manifest; import android.app.Activity; import android.content.pm.PackageManager; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraAccessException; /** * A central manager of camera devices and current clients for them. * */ public class CameraOps2 extends CameraManager.AvailabilityCallback { private final CameraManager mCameraManager; private final Activity mActivity; private final Set mOpenCameras = new HashSet(); // For persisting values for permission requests private static final int PERMISSIONS_REQUEST_CAMERA = 1; private String mDelayedOpenId = null; private CameraDevice.StateCallback mDelayedOpenListener = null; public CameraOps2(Activity activity) { mActivity = activity; mCameraManager = (CameraManager) activity.getSystemService(Activity.CAMERA_SERVICE); if (mCameraManager == null) { throw new AssertionError("Can't connect to camera manager!"); } try { String[] cameraIds = mCameraManager.getCameraIdList(); TLog.i("Camera count: %d", cameraIds.length); for (String cameraId : cameraIds) { TLog.i(" Camera %s", cameraId); } } catch (CameraAccessException e) { TLog.e("Unable to get camera list: %s", e); } mCameraManager.registerAvailabilityCallback(this, /*handler*/null); } /** * Add a listener for new camera addition events, and retrieve the list of * current cameras * * @param listener * A listener to notify on changes to camera availability * @return the current list of available cameras * @throws CameraAccessException * if the camera manager cannot be queried */ public String[] getCamerasAndListen(CameraManager.AvailabilityCallback listener) throws CameraAccessException { mCameraManager.registerAvailabilityCallback(listener, /*handler*/null); return mCameraManager.getCameraIdList(); } public void removeAvailabilityCallback(CameraManager.AvailabilityCallback listener) { mCameraManager.unregisterAvailabilityCallback(listener); } @Override public void onCameraAvailable(String cameraId) { TLog.i("Camera %s is now available", cameraId); } @Override public void onCameraUnavailable(String cameraId) { TLog.i("Camera %s is now unavailable", cameraId); } /** * Attempt to open a camera device. Returns false if the open call cannot be * made or the device is already open * * @param cameraId id of the camera to open * @param listener listener to notify of camera device state changes * @return true if open call was sent successfully. The client needs to wait * for its listener to be called to determine if open will succeed. */ public boolean openCamera(String cameraId, CameraDevice.StateCallback listener) { for (CameraDevice camera : mOpenCameras) { if (camera.getId() == cameraId) { TLog.e("Camera %s is already open", cameraId); return false; } } if (mActivity.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { TLog.i("Requesting camera permissions"); mDelayedOpenId = cameraId; mDelayedOpenListener = listener; mActivity.requestPermissions(new String[] {Manifest.permission.CAMERA}, PERMISSIONS_REQUEST_CAMERA); return false; } return doOpenCamera(cameraId, listener); } private boolean doOpenCamera(String cameraId, CameraDevice.StateCallback listener) { try { DeviceStateCallback proxyListener = new DeviceStateCallback(listener); mCameraManager.openCamera(cameraId, proxyListener, null); } catch (CameraAccessException e) { TLog.e("Unable to open camera %s.", e, cameraId); return false; } return true; } public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults) { if (requestCode == PERMISSIONS_REQUEST_CAMERA) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { TLog.i("Camera permission granted"); if (mDelayedOpenId != null && mDelayedOpenListener != null) { doOpenCamera(mDelayedOpenId, mDelayedOpenListener); } mDelayedOpenId = null; mDelayedOpenListener = null; } else { TLog.i("Camera permission denied, not opening camera"); if (mDelayedOpenId != null && mDelayedOpenListener != null) { mDelayedOpenListener.onError(null, CameraDevice.StateCallback.ERROR_CAMERA_DISABLED); mDelayedOpenId = null; mDelayedOpenListener = null; } } if (grantResults[1] == PackageManager.PERMISSION_GRANTED) { TLog.i("Storage permission granted"); } else { TLog.i("Storage permission not granted; saving will not work"); } } } public CameraCharacteristics getCameraInfo(String cameraId) { try { return mCameraManager.getCameraCharacteristics(cameraId); } catch (CameraAccessException e) { TLog.e("Unable to get camera characteristics for camera %s.", e, cameraId); } return null; } private class DeviceStateCallback extends CameraDevice.StateCallback { private final CameraDevice.StateCallback mClientListener; public DeviceStateCallback(CameraDevice.StateCallback clientListener) { mClientListener = clientListener; } @Override public void onClosed(CameraDevice camera) { mOpenCameras.remove(camera); TLog.i("Camera %s now closed", camera.getId()); mClientListener.onClosed(camera); } @Override public void onDisconnected(CameraDevice camera) { TLog.i("Camera %s now disconnected", camera.getId()); mClientListener.onDisconnected(camera); } @Override public void onError(CameraDevice camera, int error) { TLog.i("Camera %s encountered error: %d", camera.getId(), error); mClientListener.onError(camera, error); } @Override public void onOpened(CameraDevice camera) { mOpenCameras.add(camera); TLog.i("Camera %s now open", camera.getId()); mClientListener.onOpened(camera); } } }