Home | History | Annotate | Download | only in v2
      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.camera.one.v2;
     18 
     19 import android.annotation.TargetApi;
     20 import android.content.Context;
     21 import android.hardware.camera2.CameraAccessException;
     22 import android.hardware.camera2.CameraCharacteristics;
     23 import android.hardware.camera2.CameraDevice;
     24 import android.hardware.camera2.CameraManager;
     25 import android.os.Build;
     26 import android.os.Handler;
     27 import android.util.DisplayMetrics;
     28 
     29 import com.android.camera.FatalErrorHandler;
     30 import com.android.camera.SoundPlayer;
     31 import com.android.camera.async.MainThread;
     32 import com.android.camera.burst.BurstFacade;
     33 import com.android.camera.debug.Log;
     34 import com.android.camera.debug.Log.Tag;
     35 import com.android.camera.device.ActiveCameraDeviceTracker;
     36 import com.android.camera.device.CameraId;
     37 import com.android.camera.one.OneCamera;
     38 import com.android.camera.one.OneCamera.OpenCallback;
     39 import com.android.camera.one.OneCameraAccessException;
     40 import com.android.camera.one.OneCameraCaptureSetting;
     41 import com.android.camera.one.OneCameraOpener;
     42 import com.android.camera.one.config.OneCameraFeatureConfig;
     43 import com.android.camera.one.v2.photo.ImageRotationCalculator;
     44 import com.android.camera.util.AndroidServices;
     45 import com.android.camera.util.ApiHelper;
     46 import com.google.common.base.Optional;
     47 
     48 /**
     49  * The {@link com.android.camera.one.OneCameraOpener} implementation on top of Camera2 API.
     50  */
     51 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     52 public class Camera2OneCameraOpenerImpl implements OneCameraOpener {
     53     private static final Tag TAG = new Tag("OneCamera1Opnr");
     54 
     55     private final Context mContext;
     56     private final OneCameraFeatureConfig mFeatureConfig;
     57     private final ActiveCameraDeviceTracker mActiveCameraDeviceTracker;
     58     private final CameraManager mCameraManager;
     59     private final DisplayMetrics mDisplayMetrics;
     60 
     61     public static Optional<OneCameraOpener> create(
     62             OneCameraFeatureConfig featureConfig,
     63             Context context,
     64             ActiveCameraDeviceTracker activeCameraDeviceTracker,
     65             DisplayMetrics displayMetrics) {
     66         if (!ApiHelper.HAS_CAMERA_2_API) {
     67             return Optional.absent();
     68         }
     69         CameraManager cameraManager;
     70         try {
     71             cameraManager = AndroidServices.instance().provideCameraManager();
     72         } catch (IllegalStateException ex) {
     73             Log.e(TAG, "camera2.CameraManager is not available.");
     74             return Optional.absent();
     75         }
     76         OneCameraOpener oneCameraOpener = new Camera2OneCameraOpenerImpl(
     77                 featureConfig,
     78                 context,
     79                 cameraManager,
     80                 activeCameraDeviceTracker,
     81                 displayMetrics);
     82         return Optional.of(oneCameraOpener);
     83     }
     84 
     85     /**
     86      * Instantiates a new {@link com.android.camera.one.OneCameraOpener} for Camera2 API.
     87      *
     88      * @param cameraManager the underlying Camera2 camera manager.
     89      */
     90     public Camera2OneCameraOpenerImpl(OneCameraFeatureConfig featureConfig,
     91             Context context,
     92             CameraManager cameraManager,
     93             ActiveCameraDeviceTracker activeCameraDeviceTracker,
     94             DisplayMetrics displayMetrics) {
     95         mFeatureConfig = featureConfig;
     96         mContext = context;
     97         mCameraManager = cameraManager;
     98         mActiveCameraDeviceTracker = activeCameraDeviceTracker;
     99         mDisplayMetrics = displayMetrics;
    100     }
    101 
    102     @Override
    103     public void open(
    104             final CameraId cameraKey,
    105             final OneCameraCaptureSetting captureSetting,
    106             final Handler handler,
    107             final MainThread mainThread,
    108             final ImageRotationCalculator imageRotationCalculator,
    109             final BurstFacade burstController,
    110             final SoundPlayer soundPlayer,
    111             final OpenCallback openCallback,
    112             final FatalErrorHandler fatalErrorHandler) {
    113         try {
    114             Log.i(TAG, "Opening Camera: " + cameraKey);
    115 
    116             mActiveCameraDeviceTracker.onCameraOpening(cameraKey);
    117 
    118             mCameraManager.openCamera(cameraKey.getValue(), new CameraDevice.StateCallback() {
    119                 // We may get multiple calls to StateCallback, but only the
    120                 // first callback indicates the status of the camera-opening
    121                 // operation. For example, we may receive onOpened() and later
    122                 // onClosed(), but only the first should be relayed to
    123                 // openCallback.
    124                 private boolean isFirstCallback = true;
    125 
    126                 @Override
    127                 public void onDisconnected(CameraDevice device) {
    128                     if (isFirstCallback) {
    129                         isFirstCallback = false;
    130                         // If the camera is disconnected before it is opened
    131                         // then we must call close.
    132                         device.close();
    133                         openCallback.onCameraClosed();
    134                     }
    135                 }
    136 
    137                 @Override
    138                 public void onClosed(CameraDevice device) {
    139                     if (isFirstCallback) {
    140                         isFirstCallback = false;
    141                         openCallback.onCameraClosed();
    142                     }
    143                 }
    144 
    145                 @Override
    146                 public void onError(CameraDevice device, int error) {
    147                     if (isFirstCallback) {
    148                         isFirstCallback = false;
    149                         device.close();
    150                         openCallback.onFailure();
    151                     } else {
    152                         // Ensures we handle the case where an error occurs
    153                         // after the camera has been opened.
    154                         fatalErrorHandler.onGenericCameraAccessFailure();
    155                     }
    156                 }
    157 
    158                 @Override
    159                 public void onOpened(CameraDevice device) {
    160                     if (isFirstCallback) {
    161                         isFirstCallback = false;
    162                         try {
    163                             CameraCharacteristics characteristics = mCameraManager
    164                                     .getCameraCharacteristics(device.getId());
    165                             // TODO: Set boolean based on whether HDR+ is
    166                             // enabled.
    167                             OneCamera oneCamera = OneCameraCreator.create(
    168                                     device,
    169                                     characteristics,
    170                                     mFeatureConfig,
    171                                     captureSetting,
    172                                     mDisplayMetrics,
    173                                     mContext,
    174                                     mainThread,
    175                                     imageRotationCalculator,
    176                                     burstController,
    177                                     soundPlayer, fatalErrorHandler);
    178 
    179                             if (oneCamera != null) {
    180                                 openCallback.onCameraOpened(oneCamera);
    181                             } else {
    182                                 Log.d(TAG, "Could not construct a OneCamera object!");
    183                                 openCallback.onFailure();
    184                             }
    185                         } catch (CameraAccessException e) {
    186                             Log.d(TAG, "Could not get camera characteristics", e);
    187                             openCallback.onFailure();
    188                         } catch (OneCameraAccessException e) {
    189                             Log.d(TAG, "Could not create OneCamera", e);
    190                             openCallback.onFailure();
    191                         }
    192                     }
    193                 }
    194             }, handler);
    195         } catch (CameraAccessException ex) {
    196             Log.e(TAG, "Could not open camera. " + ex.getMessage());
    197             handler.post(new Runnable() {
    198                 @Override
    199                 public void run() {
    200                     openCallback.onFailure();
    201                 }
    202             });
    203         } catch (UnsupportedOperationException ex) {
    204             Log.e(TAG, "Could not open camera. " + ex.getMessage());
    205             handler.post(new Runnable() {
    206                 @Override
    207                 public void run() {
    208                     openCallback.onFailure();
    209                 }
    210             });
    211         } catch (SecurityException ex) {
    212             fatalErrorHandler.onCameraDisabledFailure();
    213         }
    214     }
    215 }
    216