Home | History | Annotate | Download | only in testingcamera2
      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 
     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      */
     74     public String[] getCamerasAndListen(CameraManager.AvailabilityCallback listener)
     75             throws CameraAccessException {
     76 
     77         mCameraManager.registerAvailabilityCallback(listener, /*handler*/null);
     78 
     79         return mCameraManager.getCameraIdList();
     80     }
     81 
     82     public void removeAvailabilityCallback(CameraManager.AvailabilityCallback listener) {
     83         mCameraManager.unregisterAvailabilityCallback(listener);
     84     }
     85 
     86     @Override
     87     public void onCameraAvailable(String cameraId) {
     88         TLog.i("Camera %s is now available", cameraId);
     89     }
     90 
     91     @Override
     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      */
    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 
    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 
    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 
    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 
    183         public DeviceStateCallback(CameraDevice.StateCallback clientListener) {
    184             mClientListener = clientListener;
    185         }
    186 
    187         @Override
    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
    195         public void onDisconnected(CameraDevice camera) {
    196             TLog.i("Camera %s now disconnected", camera.getId());
    197             mClientListener.onDisconnected(camera);
    198         }
    199 
    200         @Override
    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
    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