2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.camera.one.v2;
19 import android.content.Context;
20 import android.hardware.camera2.CameraAccessException;
21 import android.hardware.camera2.CameraCharacteristics;
22 import android.hardware.camera2.CameraDevice;
23 import android.hardware.camera2.CameraManager;
24 import android.os.Handler;
25 import android.util.DisplayMetrics;
27 import com.android.camera.SoundPlayer;
28 import com.android.camera.debug.Log;
29 import com.android.camera.debug.Log.Tag;
30 import com.android.camera.one.OneCamera;
31 import com.android.camera.one.OneCamera.Facing;
32 import com.android.camera.one.OneCamera.OpenCallback;
33 import com.android.camera.one.OneCameraManager;
34 import com.android.camera.util.Size;
37 * The {@link OneCameraManager} implementation on top of Camera2 API.
39 public class OneCameraManagerImpl extends OneCameraManager {
40 private static final Tag TAG = new Tag("OneCameraMgrImpl2");
42 private final Context mContext;
43 private final CameraManager mCameraManager;
44 private final int mMaxMemoryMB;
45 private final DisplayMetrics mDisplayMetrics;
46 private final SoundPlayer mSoundPlayer;
49 * Instantiates a new {@link OneCameraManager} for Camera2 API.
51 * @param cameraManager the underlying Camera2 camera manager.
52 * @param maxMemoryMB maximum amount of memory opened cameras should consume
53 * during capture and processing, in megabytes.
55 public OneCameraManagerImpl(Context context, CameraManager cameraManager, int maxMemoryMB,
56 DisplayMetrics displayMetrics, SoundPlayer soundPlayer) {
58 mCameraManager = cameraManager;
59 mMaxMemoryMB = maxMemoryMB;
60 mDisplayMetrics = displayMetrics;
61 mSoundPlayer = soundPlayer;
65 public void open(Facing facing, final boolean useHdr, final Size pictureSize,
66 final OpenCallback openCallback, Handler handler) {
68 final String cameraId = getCameraId(facing);
69 Log.i(TAG, "Opening Camera ID " + cameraId);
70 mCameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
71 // We may get multiple calls to StateCallback, but only the
72 // first callback indicates the status of the camera-opening
73 // operation. For example, we may receive onOpened() and later
74 // onClosed(), but only the first should be relayed to
76 private boolean isFirstCallback = true;
79 public void onDisconnected(CameraDevice device) {
80 if (isFirstCallback) {
81 isFirstCallback = false;
82 // If the camera is disconnected before it is opened
83 // then we must call close.
85 openCallback.onCameraClosed();
90 public void onClosed(CameraDevice device) {
91 if (isFirstCallback) {
92 isFirstCallback = false;
93 openCallback.onCameraClosed();
98 public void onError(CameraDevice device, int error) {
99 if (isFirstCallback) {
100 isFirstCallback = false;
102 openCallback.onFailure();
107 public void onOpened(CameraDevice device) {
108 if (isFirstCallback) {
109 isFirstCallback = false;
111 CameraCharacteristics characteristics = mCameraManager
112 .getCameraCharacteristics(device.getId());
113 // TODO: Set boolean based on whether HDR+ is enabled.
114 OneCamera oneCamera = OneCameraCreator.create(mContext, useHdr, device,
115 characteristics, pictureSize, mMaxMemoryMB, mDisplayMetrics,
117 openCallback.onCameraOpened(oneCamera);
118 } catch (CameraAccessException e) {
119 Log.d(TAG, "Could not get camera characteristics");
120 openCallback.onFailure();
125 } catch (CameraAccessException ex) {
126 Log.e(TAG, "Could not open camera. " + ex.getMessage());
127 handler.post(new Runnable() {
130 openCallback.onFailure();
133 } catch (UnsupportedOperationException ex) {
134 Log.e(TAG, "Could not open camera. " + ex.getMessage());
135 handler.post(new Runnable() {
138 openCallback.onFailure();
145 public boolean hasCameraFacing(Facing facing) {
146 return getFirstCameraFacing(facing == Facing.FRONT ? CameraCharacteristics.LENS_FACING_FRONT
147 : CameraCharacteristics.LENS_FACING_BACK) != null;
150 /** Returns the ID of the first camera facing the given direction. */
151 private String getCameraId(Facing facing) {
152 if (facing == Facing.FRONT) {
153 return getFirstFrontCameraId();
155 return getFirstBackCameraId();
159 /** Returns the ID of the first back-facing camera. */
160 public String getFirstBackCameraId() {
161 Log.d(TAG, "Getting First BACK Camera");
162 String cameraId = getFirstCameraFacing(CameraCharacteristics.LENS_FACING_BACK);
163 if (cameraId == null) {
164 throw new RuntimeException("No back-facing camera found.");
169 /** Returns the ID of the first front-facing camera. */
170 public String getFirstFrontCameraId() {
171 Log.d(TAG, "Getting First FRONT Camera");
172 String cameraId = getFirstCameraFacing(CameraCharacteristics.LENS_FACING_FRONT);
173 if (cameraId == null) {
174 throw new RuntimeException("No front-facing camera found.");
179 /** Returns the ID of the first camera facing the given direction. */
180 private String getFirstCameraFacing(int facing) {
182 String[] cameraIds = mCameraManager.getCameraIdList();
183 for (String cameraId : cameraIds) {
184 CameraCharacteristics characteristics = mCameraManager
185 .getCameraCharacteristics(cameraId);
186 if (characteristics.get(CameraCharacteristics.LENS_FACING) == facing) {
191 } catch (CameraAccessException ex) {
192 throw new RuntimeException("Unable to get camera ID", ex);