Home | History | Annotate | Download | only in one
      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;
     18 
     19 import android.content.Context;
     20 import android.hardware.camera2.CameraAccessException;
     21 import android.hardware.camera2.CameraCharacteristics;
     22 import android.hardware.camera2.CameraManager;
     23 import android.os.Handler;
     24 import android.util.DisplayMetrics;
     25 import android.view.WindowManager;
     26 
     27 import com.android.camera.CameraActivity;
     28 import com.android.camera.debug.Log;
     29 import com.android.camera.debug.Log.Tag;
     30 import com.android.camera.one.OneCamera.Facing;
     31 import com.android.camera.one.OneCamera.OpenCallback;
     32 import com.android.camera.util.ApiHelper;
     33 import com.android.camera.util.Size;
     34 
     35 /**
     36  * The camera manager is responsible for instantiating {@link OneCamera}
     37  * instances.
     38  */
     39 public abstract class OneCameraManager {
     40     private static Tag TAG = new Tag("OneCameraManager");
     41 
     42     /**
     43      * Attempts to open the camera facing the given direction with the given
     44      * capture size.
     45      *
     46      * Exactly one call will always be made to a single method in the provided
     47      * {@link OpenCallback}.
     48      *
     49      * @param facing which camera to open. The first camera found in the given
     50      *            direction will be opened.
     51      * @param enableHdr if an HDR feature exists, open a camera that supports it
     52      * @param captureSize the capture size. This must be one of the supported
     53      *            sizes.
     54      * @param callback this listener is called when the camera was opened or
     55      *            when it failed to open.
     56      * @param handler the handler on which callback methods are invoked.
     57      */
     58     public abstract void open(Facing facing, boolean enableHdr, Size captureSize,
     59             OpenCallback callback, Handler handler);
     60 
     61     /**
     62      * Returns whether the device has a camera facing the given direction.
     63      */
     64     public abstract boolean hasCameraFacing(Facing facing);
     65 
     66     /**
     67      * Creates a camera manager that is based on Camera2 API, if available, or
     68      * otherwise uses the portability layer API.
     69      *
     70      * @throws OneCameraException Thrown if an error occurred while trying to
     71      *             access the camera.
     72      */
     73     public static OneCameraManager get(CameraActivity activity) throws OneCameraException {
     74         return create(activity);
     75     }
     76 
     77     /**
     78      * Creates a new camera manager that is based on Camera2 API, if available,
     79      * or otherwise uses the portability API.
     80      *
     81      * @throws OneCameraException Thrown if an error occurred while trying to
     82      *             access the camera.
     83      */
     84     private static OneCameraManager create(CameraActivity activity) throws OneCameraException {
     85         DisplayMetrics displayMetrics = getDisplayMetrics(activity);
     86         CameraManager cameraManager = null;
     87 
     88         try {
     89             cameraManager = ApiHelper.HAS_CAMERA_2_API ? (CameraManager) activity
     90                     .getSystemService(Context.CAMERA_SERVICE) : null;
     91         } catch (IllegalStateException ex) {
     92             cameraManager = null;
     93             Log.e(TAG, "Could not get camera service v2", ex);
     94         }
     95         if (cameraManager != null && isCamera2Supported(cameraManager)) {
     96             int maxMemoryMB = activity.getServices().getMemoryManager()
     97                     .getMaxAllowedNativeMemoryAllocation();
     98             return new com.android.camera.one.v2.OneCameraManagerImpl(
     99                     activity.getAndroidContext(), cameraManager, maxMemoryMB,
    100                     displayMetrics, activity.getSoundPlayer());
    101         } else {
    102             return new com.android.camera.one.v1.OneCameraManagerImpl();
    103         }
    104     }
    105 
    106     /**
    107      * Returns whether the device fully supports API2
    108      *
    109      * @param cameraManager the Camera2 API manager.
    110      * @return If this device is only emulating Camera2 API on top of an older
    111      *         HAL (such as the Nexus 4, 7 or 10), this method returns false. It
    112      *         only returns true, if Camera2 is fully supported through newer
    113      *         HALs.
    114      * @throws OneCameraException Thrown if an error occurred while trying to
    115      *             access the camera.
    116      */
    117     private static boolean isCamera2Supported(CameraManager cameraManager)
    118             throws OneCameraException {
    119         if (!ApiHelper.HAS_CAMERA_2_API) {
    120             return false;
    121         }
    122         try {
    123             String[] cameraIds = cameraManager.getCameraIdList();
    124             if (cameraIds.length == 0) {
    125                 throw new OneCameraException("Camera 2 API supported but no devices available.");
    126             }
    127             final String id = cameraIds[0];
    128             // TODO: We should check for all the flags we need to ensure the
    129             // device is capable of taking Camera2 API shots. For now, let's
    130             // accept all device that are either 'partial' or 'full' devices
    131             // (but not legacy).
    132             return cameraManager.getCameraCharacteristics(id).get(
    133                     CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
    134                 != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
    135         } catch (CameraAccessException ex) {
    136             Log.e(TAG, "Could not access camera to determine hardware-level API support.");
    137             return false;
    138         }
    139     }
    140 
    141     private static DisplayMetrics getDisplayMetrics(Context context) {
    142         DisplayMetrics displayMetrics = new DisplayMetrics();
    143         WindowManager wm = (WindowManager)
    144                 context.getSystemService(Context.WINDOW_SERVICE);
    145         if (wm != null) {
    146             displayMetrics = new DisplayMetrics();
    147             wm.getDefaultDisplay().getMetrics(displayMetrics);
    148         }
    149         return displayMetrics;
    150     }
    151 }
    152