1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/* 2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2016 The Android Open Source Project 3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License. 6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at 7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software 11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and 14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License. 15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.dialer.callcomposer.camera; 18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context; 20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.hardware.Camera; 21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.hardware.Camera.CameraInfo; 22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.net.Uri; 23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.AsyncTask; 24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Looper; 25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull; 26fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanianimport android.support.annotation.Nullable; 27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.VisibleForTesting; 28ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.TextUtils; 29ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.MotionEvent; 30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.OrientationEventListener; 31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.Surface; 32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.View; 33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.WindowManager; 34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.callcomposer.camera.camerafocus.FocusOverlayManager; 35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.callcomposer.camera.camerafocus.RenderOverlay; 36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.Assert; 37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil; 38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.io.IOException; 39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.ArrayList; 40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Collections; 41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Comparator; 42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.List; 43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/** 45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Class which manages interactions with the camera, but does not do any UI. This class is designed 46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * to be a singleton to ensure there is one component managing the camera and releasing the native 47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * resources. In order to acquire a camera, a caller must: 48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <ul> 50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <li>Call selectCamera to select front or back camera 51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <li>Call setSurface to control where the preview is shown 52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <li>Call openCamera to request the camera start preview 53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * </ul> 54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Callers should call onPause and onResume to ensure that the camera is release while the activity 56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * is not active. This class is not thread safe. It should only be called from one thread (the UI 57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * thread or test thread) 58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic class CameraManager implements FocusOverlayManager.Listener { 60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Callbacks for the camera manager listener */ 61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public interface CameraManagerListener { 62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onCameraError(int errorCode, Exception e); 63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onCameraChanged(); 65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Callback when taking image or video */ 68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public interface MediaCallback { 69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian int MEDIA_CAMERA_CHANGED = 1; 70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian int MEDIA_NO_DATA = 2; 71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onMediaReady(Uri uriToMedia, String contentType, int width, int height); 73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onMediaFailed(Exception exception); 75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onMediaInfo(int what); 77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Error codes 80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int ERROR_OPENING_CAMERA = 1; 81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int ERROR_SHOWING_PREVIEW = 2; 82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int ERROR_HARDWARE_ACCELERATION_DISABLED = 3; 83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int ERROR_TAKING_PICTURE = 4; 84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int NO_CAMERA_SELECTED = -1; 86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final Camera.ShutterCallback DUMMY_SHUTTER_CALLBACK = 88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new Camera.ShutterCallback() { 89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onShutter() { 91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Do nothing 92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }; 94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static CameraManager sInstance; 96ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 97ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** The CameraInfo for the currently selected camera */ 98ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final CameraInfo mCameraInfo; 99ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 100ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** The index of the selected camera or NO_CAMERA_SELECTED if a camera hasn't been selected yet */ 101ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private int mCameraIndex; 102ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 103ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** True if the device has front and back cameras */ 104ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final boolean mHasFrontAndBackCamera; 105ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 106ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** True if the camera should be open (may not yet be actually open) */ 107ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mOpenRequested; 108ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 109ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** The preview view to show the preview on */ 110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private CameraPreview mCameraPreview; 111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 112ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** The helper classs to handle orientation changes */ 113ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private OrientationHandler mOrientationHandler; 114ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 115ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Tracks whether the preview has hardware acceleration */ 116ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mIsHardwareAccelerationSupported; 117ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 118ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 119ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * The task for opening the camera, so it doesn't block the UI thread Using AsyncTask rather than 120ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * SafeAsyncTask because the tasks need to be serialized, but don't need to be on the UI thread 12110ae593a59aa50963e1d3159747da2d65ca79bedEric Erfanian * TODO: If we have other AyncTasks (not SafeAsyncTasks) this may contend and we may need 122ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * to create a dedicated thread, or synchronize the threads in the thread pool 123ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 124ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private AsyncTask<Integer, Void, Camera> mOpenCameraTask; 125ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 126ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 127ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * The camera index that is queued to be opened, but not completed yet, or NO_CAMERA_SELECTED if 128ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * no open task is pending 129ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 130ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private int mPendingOpenCameraIndex = NO_CAMERA_SELECTED; 131ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 132ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** The instance of the currently opened camera */ 133ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private Camera mCamera; 134ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 135ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** The rotation of the screen relative to the camera's natural orientation */ 136ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private int mRotation; 137ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 138ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** The callback to notify when errors or other events occur */ 139ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private CameraManagerListener mListener; 140ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 141ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** True if the camera is currently in the process of taking an image */ 142ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mTakingPicture; 143ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 144ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Manages auto focus visual and behavior */ 145ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final FocusOverlayManager mFocusOverlayManager; 146ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 147ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private CameraManager() { 148ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraInfo = new CameraInfo(); 149ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraIndex = NO_CAMERA_SELECTED; 150ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 151ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Check to see if a front and back camera exist 152ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian boolean hasFrontCamera = false; 153ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian boolean hasBackCamera = false; 154ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final CameraInfo cameraInfo = new CameraInfo(); 155ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int cameraCount = Camera.getNumberOfCameras(); 156ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 157ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (int i = 0; i < cameraCount; i++) { 158ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Camera.getCameraInfo(i, cameraInfo); 159ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) { 160ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian hasFrontCamera = true; 161ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { 162ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian hasBackCamera = true; 163ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 164ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (hasFrontCamera && hasBackCamera) { 165ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 166ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 167ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 168ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 169ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CameraManager.CameraManager", "Unable to load camera info", e); 170ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 171ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mHasFrontAndBackCamera = hasFrontCamera && hasBackCamera; 172ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager = new FocusOverlayManager(this, Looper.getMainLooper()); 173ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 174ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Assume the best until we are proven otherwise 175ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mIsHardwareAccelerationSupported = true; 176ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 177ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 178ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Gets the singleton instance */ 179ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public static CameraManager get() { 180ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (sInstance == null) { 181ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian sInstance = new CameraManager(); 182ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 183ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return sInstance; 184ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 185ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 186ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 187ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Sets the surface to use to display the preview This must only be called AFTER the CameraPreview 188ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * has a texture ready 189ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 190ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param preview The preview surface view 191ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 192ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void setSurface(final CameraPreview preview) { 193ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (preview == mCameraPreview) { 194ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 195ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 196ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 197ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (preview != null) { 198ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.checkArgument(preview.isValid()); 199ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian preview.setOnTouchListener( 200ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new View.OnTouchListener() { 201ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 202ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public boolean onTouch(final View view, final MotionEvent motionEvent) { 203ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if ((motionEvent.getActionMasked() & MotionEvent.ACTION_UP) 204ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian == MotionEvent.ACTION_UP) { 205ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.setPreviewSize(view.getWidth(), view.getHeight()); 206ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.onSingleTapUp( 207ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian (int) motionEvent.getX() + view.getLeft(), 208ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian (int) motionEvent.getY() + view.getTop()); 209ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 210ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian view.performClick(); 211ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return true; 212ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 213ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }); 214ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 215ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraPreview = preview; 216ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian tryShowPreview(); 217ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 218ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 219ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void setRenderOverlay(final RenderOverlay renderOverlay) { 220ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.setFocusRenderer( 221ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian renderOverlay != null ? renderOverlay.getPieRenderer() : null); 222ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 223ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 224ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Convenience function to swap between front and back facing cameras */ 225ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void swapCamera() { 226ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.checkState(mCameraIndex >= 0); 227ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian selectCamera( 228ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT 229ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian ? CameraInfo.CAMERA_FACING_BACK 230ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian : CameraInfo.CAMERA_FACING_FRONT); 231ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 232ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 233ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 234ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Selects the first camera facing the desired direction, or the first camera if there is no 235ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * camera in the desired direction 236ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 237ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param desiredFacing One of the CameraInfo.CAMERA_FACING_* constants 238ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @return True if a camera was selected, or false if selecting a camera failed 239ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 240ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public boolean selectCamera(final int desiredFacing) { 241ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 242ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // We already selected a camera facing that direction 243ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCameraIndex >= 0 && mCameraInfo.facing == desiredFacing) { 244ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return true; 245ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 246ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 247ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int cameraCount = Camera.getNumberOfCameras(); 248ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.checkState(cameraCount > 0); 249ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 250ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraIndex = NO_CAMERA_SELECTED; 251ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian setCamera(null); 252ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final CameraInfo cameraInfo = new CameraInfo(); 253ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (int i = 0; i < cameraCount; i++) { 254ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Camera.getCameraInfo(i, cameraInfo); 255ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (cameraInfo.facing == desiredFacing) { 256ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraIndex = i; 257ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Camera.getCameraInfo(i, mCameraInfo); 258ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 259ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 260ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 261ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 262ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // There's no camera in the desired facing direction, just select the first camera 263ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // regardless of direction 264ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCameraIndex < 0) { 265ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraIndex = 0; 266ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Camera.getCameraInfo(0, mCameraInfo); 267ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 268ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 269ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mOpenRequested) { 270ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // The camera is open, so reopen with the newly selected camera 271ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian openCamera(); 272ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 273ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return true; 274ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 275ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CameraManager.selectCamera", "RuntimeException in CameraManager.selectCamera", e); 276ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mListener != null) { 277ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraError(ERROR_OPENING_CAMERA, e); 278ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 279ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return false; 280ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 281ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 282ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 283ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public int getCameraIndex() { 284ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return mCameraIndex; 285ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 286ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 287ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void selectCameraByIndex(final int cameraIndex) { 288ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCameraIndex == cameraIndex) { 289ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 290ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 291ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 292ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 293ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraIndex = cameraIndex; 294ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Camera.getCameraInfo(mCameraIndex, mCameraInfo); 295ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mOpenRequested) { 296ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian openCamera(); 297ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 298ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 299ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e( 300ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CameraManager.selectCameraByIndex", 301ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "RuntimeException in CameraManager.selectCameraByIndex", 302ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian e); 303ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mListener != null) { 304ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraError(ERROR_OPENING_CAMERA, e); 305ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 306ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 307ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 308ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 309fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian @Nullable 310ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @VisibleForTesting 311ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public CameraInfo getCameraInfo() { 312ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCameraIndex == NO_CAMERA_SELECTED) { 313ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return null; 314ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 315ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return mCameraInfo; 316ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 317ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 318ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** @return True if the device has both a front and back camera */ 319ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public boolean hasFrontAndBackCamera() { 320ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return mHasFrontAndBackCamera; 321ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 322ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 323ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Opens the camera on a separate thread and initiates the preview if one is available */ 324ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void openCamera() { 325ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCameraIndex == NO_CAMERA_SELECTED) { 326ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Ensure a selected camera if none is currently selected. This may happen if the 327ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // camera chooser is not the default media chooser. 328ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian selectCamera(CameraInfo.CAMERA_FACING_BACK); 329ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 330ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOpenRequested = true; 331ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // We're already opening the camera or already have the camera handle, nothing more to do 332ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mPendingOpenCameraIndex == mCameraIndex || mCamera != null) { 333ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 334ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 335ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 336ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // True if the task to open the camera has to be delayed until the current one completes 337ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian boolean delayTask = false; 338ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 339ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Cancel any previous open camera tasks 340ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mOpenCameraTask != null) { 341ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mPendingOpenCameraIndex = NO_CAMERA_SELECTED; 342ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian delayTask = true; 343ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 344ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 345ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mPendingOpenCameraIndex = mCameraIndex; 346ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOpenCameraTask = 347ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new AsyncTask<Integer, Void, Camera>() { 348ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private Exception mException; 349ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 350ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 351ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian protected Camera doInBackground(final Integer... params) { 352ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 353ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int cameraIndex = params[0]; 354ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.v("CameraManager.doInBackground", "Opening camera " + mCameraIndex); 355ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return Camera.open(cameraIndex); 356ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final Exception e) { 357ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CameraManager.doInBackground", "Exception while opening camera", e); 358ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mException = e; 359ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return null; 360ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 361ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 362ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 363ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 364ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian protected void onPostExecute(final Camera camera) { 365ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // If we completed, but no longer want this camera, then release the camera 366ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mOpenCameraTask != this || !mOpenRequested) { 367ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian releaseCamera(camera); 368ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian cleanup(); 369ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 370ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 371ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 372ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian cleanup(); 373ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 374ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.v( 375ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CameraManager.onPostExecute", 376ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "Opened camera " + mCameraIndex + " " + (camera != null)); 377ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian setCamera(camera); 378ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (camera == null) { 379ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mListener != null) { 380ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraError(ERROR_OPENING_CAMERA, mException); 381ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 382ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CameraManager.onPostExecute", "Error opening camera"); 383ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 384ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 385ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 386ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 387ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian protected void onCancelled() { 388ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian super.onCancelled(); 389ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian cleanup(); 390ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 391ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 392ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void cleanup() { 393ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mPendingOpenCameraIndex = NO_CAMERA_SELECTED; 394ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mOpenCameraTask != null && mOpenCameraTask.getStatus() == Status.PENDING) { 395ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // If there's another task waiting on this one to complete, start it now 396ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOpenCameraTask.execute(mCameraIndex); 397ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 398ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOpenCameraTask = null; 399ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 400ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 401ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }; 402ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.v("CameraManager.openCamera", "Start opening camera " + mCameraIndex); 403ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (!delayTask) { 404ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOpenCameraTask.execute(mCameraIndex); 405ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 406ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 407ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 408ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Closes the camera releasing the resources it uses */ 409ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void closeCamera() { 410ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOpenRequested = false; 411ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian setCamera(null); 412ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 413ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 414ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 415ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Sets the listener which will be notified of errors or other events in the camera 416ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 417ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param listener The listener to notify 418ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 419ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void setListener(final CameraManagerListener listener) { 420ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.isMainThread(); 421ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener = listener; 422ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (!mIsHardwareAccelerationSupported && mListener != null) { 423ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraError(ERROR_HARDWARE_ACCELERATION_DISABLED, null); 424ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 425ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 426ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 427ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void takePicture(final float heightPercent, @NonNull final MediaCallback callback) { 428ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.checkState(!mTakingPicture); 429ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.isNotNull(callback); 430ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraPreview.setFocusable(false); 431ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.cancelAutoFocus(); 432ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCamera == null) { 433ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // The caller should have checked isCameraAvailable first, but just in case, protect 434ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // against a null camera by notifying the callback that taking the picture didn't work 435ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian callback.onMediaFailed(null); 436ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 437ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 438ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Camera.PictureCallback jpegCallback = 439ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new Camera.PictureCallback() { 440ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 441ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onPictureTaken(final byte[] bytes, final Camera camera) { 442ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mTakingPicture = false; 443ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCamera != camera) { 444ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // This may happen if the camera was changed between front/back while the 445ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // picture is being taken. 446ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian callback.onMediaInfo(MediaCallback.MEDIA_CAMERA_CHANGED); 447ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 448ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 449ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 450ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (bytes == null) { 451ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian callback.onMediaInfo(MediaCallback.MEDIA_NO_DATA); 452ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 453ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 454ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 455ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Camera.Size size = camera.getParameters().getPictureSize(); 456ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian int width; 457ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian int height; 458ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mRotation == 90 || mRotation == 270) { 459ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Is rotated, so swapping dimensions is desired 460ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian //noinspection SuspiciousNameCombination 461ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian width = size.height; 462ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian //noinspection SuspiciousNameCombination 463ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian height = size.width; 464ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 465ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian width = size.width; 466ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian height = size.height; 467ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 468ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i( 469ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CameraManager.onPictureTaken", "taken picture size: " + bytes.length + " bytes"); 470ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new ImagePersistTask( 471ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian width, height, heightPercent, bytes, mCameraPreview.getContext(), callback) 472ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian .execute(); 473ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 474ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }; 475ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 476ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mTakingPicture = true; 477ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 478ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.takePicture( 479ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // A shutter callback is required to enable shutter sound 480ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DUMMY_SHUTTER_CALLBACK, null /* raw */, null /* postView */, jpegCallback); 481ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 482ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CameraManager.takePicture", "RuntimeException in CameraManager.takePicture", e); 483ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mTakingPicture = false; 484ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mListener != null) { 485ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraError(ERROR_TAKING_PICTURE, e); 486ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 487ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 488ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 489ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 490ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 491ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Asynchronously releases a camera 492ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 493ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param camera The camera to release 494ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 495ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void releaseCamera(final Camera camera) { 496ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (camera == null) { 497ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 498ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 499ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 500ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.onCameraReleased(); 501ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 502ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new AsyncTask<Void, Void, Void>() { 503ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 504ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian protected Void doInBackground(final Void... params) { 505ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.v("CameraManager.doInBackground", "Releasing camera " + mCameraIndex); 506ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian camera.release(); 507ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return null; 508ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 509ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }.execute(); 510ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 511ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 5122f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian /** 5132f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * Updates the orientation of the {@link Camera} w.r.t. the orientation of the device and the 5142f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * orientation that the physical camera is mounted on the device. 5152f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * 5162f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * @param camera that needs to be reorientated 5172f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * @param screenRotation rotation of the physical device 5182f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * @param cameraOrientation {@link CameraInfo#orientation} 5192f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * @param cameraIsFrontFacing {@link CameraInfo#CAMERA_FACING_FRONT} 5202f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * @return rotation that images returned from {@link 5212f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * android.hardware.Camera.PictureCallback#onPictureTaken(byte[], Camera)} will be rotated. 5222f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian */ 5232f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian @VisibleForTesting 5242f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian static int updateCameraRotation( 5252f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian @NonNull Camera camera, 5262f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian int screenRotation, 5272f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian int cameraOrientation, 5282f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian boolean cameraIsFrontFacing) { 5292f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian Assert.isNotNull(camera); 5302f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian Assert.checkArgument(cameraOrientation % 90 == 0); 5312f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 5322f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian int rotation = screenRotationToDegress(screenRotation); 5332f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian boolean portrait = rotation == 0 || rotation == 180; 5342f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 5352f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (!portrait && !cameraIsFrontFacing) { 5362f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian rotation += 180; 5372f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 5382f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian rotation += cameraOrientation; 5392f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian rotation %= 360; 5402f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 5412f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian // Rotate the camera 5422f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (portrait && cameraIsFrontFacing) { 5432f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian camera.setDisplayOrientation((rotation + 180) % 360); 5442f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } else { 5452f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian camera.setDisplayOrientation(rotation); 546ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 547ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 5482f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian // Rotate the images returned when a picture is taken 5492f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian Camera.Parameters params = camera.getParameters(); 5502f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian params.setRotation(rotation); 5512f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian camera.setParameters(params); 5522f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian return rotation; 5532f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 554ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 5552f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian private static int screenRotationToDegress(int screenRotation) { 5562f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian switch (screenRotation) { 557ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case Surface.ROTATION_0: 5582f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian return 0; 559ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case Surface.ROTATION_90: 5602f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian return 90; 561ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case Surface.ROTATION_180: 5622f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian return 180; 563ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case Surface.ROTATION_270: 5642f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian return 270; 565fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian default: 5662f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian throw Assert.createIllegalStateFailException("Invalid surface rotation."); 567ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 568ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 569ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 570ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Sets the current camera, releasing any previously opened camera */ 571ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void setCamera(final Camera camera) { 572ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCamera == camera) { 573ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 574ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 575ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 576ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian releaseCamera(mCamera); 577ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera = camera; 578ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian tryShowPreview(); 579ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mListener != null) { 580ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraChanged(); 581ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 582ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 583ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 584ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Shows the preview if the camera is open and the preview is loaded */ 585ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void tryShowPreview() { 586ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCameraPreview == null || mCamera == null) { 587ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mOrientationHandler != null) { 588ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOrientationHandler.disable(); 589ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOrientationHandler = null; 590ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 591ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.onPreviewStopped(); 592ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 593ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 594ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 595ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.stopPreview(); 5962f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (!mTakingPicture) { 5972f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mRotation = 5982f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian updateCameraRotation( 5992f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mCamera, 6002f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian getScreenRotation(), 6012f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mCameraInfo.orientation, 6022f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mCameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT); 6032f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 604ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 605ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Camera.Parameters params = mCamera.getParameters(); 606ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Camera.Size pictureSize = chooseBestPictureSize(); 607ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Camera.Size previewSize = chooseBestPreviewSize(pictureSize); 608ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian params.setPreviewSize(previewSize.width, previewSize.height); 609ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian params.setPictureSize(pictureSize.width, pictureSize.height); 610ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian logCameraSize("Setting preview size: ", previewSize); 611ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian logCameraSize("Setting picture size: ", pictureSize); 612ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraPreview.setSize(previewSize, mCameraInfo.orientation); 613ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (final String focusMode : params.getSupportedFocusModes()) { 614ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (TextUtils.equals(focusMode, Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 615ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Use continuous focus if available 616ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian params.setFocusMode(focusMode); 617ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 618ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 619ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 620ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 621ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.setParameters(params); 622ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraPreview.startPreview(mCamera); 623ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.startPreview(); 624ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.setAutoFocusMoveCallback( 625ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new Camera.AutoFocusMoveCallback() { 626ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 627ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onAutoFocusMoving(final boolean start, final Camera camera) { 628ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.onAutoFocusMoving(start); 629ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 630ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }); 631ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.setParameters(mCamera.getParameters()); 632ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.setMirror(mCameraInfo.facing == CameraInfo.CAMERA_FACING_BACK); 633ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.onPreviewStarted(); 634ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mOrientationHandler == null) { 635ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOrientationHandler = new OrientationHandler(mCameraPreview.getContext()); 636ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOrientationHandler.enable(); 637ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 638ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final IOException e) { 639ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CameraManager.tryShowPreview", "IOException in CameraManager.tryShowPreview", e); 640ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mListener != null) { 641ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraError(ERROR_SHOWING_PREVIEW, e); 642ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 643ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 644ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e( 645ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CameraManager.tryShowPreview", "RuntimeException in CameraManager.tryShowPreview", e); 646ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mListener != null) { 647ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListener.onCameraError(ERROR_SHOWING_PREVIEW, e); 648ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 649ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 650ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 651ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 6522f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian private int getScreenRotation() { 6532f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian return mCameraPreview 6542f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .getContext() 6552f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .getSystemService(WindowManager.class) 6562f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .getDefaultDisplay() 6572f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .getRotation(); 6582f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 6592f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 660ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public boolean isCameraAvailable() { 661ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return mCamera != null && !mTakingPicture && mIsHardwareAccelerationSupported; 662ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 663ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 664ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 665ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Choose the best picture size by trying to find a size close to the MmsConfig's max size, which 666ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * is closest to the screen aspect ratio. In case of RCS conversation returns default size. 667ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 668ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private Camera.Size chooseBestPictureSize() { 669ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return mCamera.getParameters().getPictureSize(); 670ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 671ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 672ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 673ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Chose the best preview size based on the picture size. Try to find a size with the same aspect 674ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * ratio and size as the picture if possible 675ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 676ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private Camera.Size chooseBestPreviewSize(final Camera.Size pictureSize) { 677ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final List<Camera.Size> sizes = 678ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new ArrayList<Camera.Size>(mCamera.getParameters().getSupportedPreviewSizes()); 679ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final float aspectRatio = pictureSize.width / (float) pictureSize.height; 680ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int capturePixels = pictureSize.width * pictureSize.height; 681ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 682ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Sort the sizes so the best size is first 683ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Collections.sort( 684ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian sizes, 685ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new SizeComparator(Integer.MAX_VALUE, Integer.MAX_VALUE, aspectRatio, capturePixels)); 686ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 687ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return sizes.get(0); 688ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 689ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 690ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private class OrientationHandler extends OrientationEventListener { 691ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian OrientationHandler(final Context context) { 692ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian super(context); 693ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 694ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 695ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 696ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onOrientationChanged(final int orientation) { 6972f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (!mTakingPicture) { 6982f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mRotation = 6992f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian updateCameraRotation( 7002f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mCamera, 7012f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian getScreenRotation(), 7022f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mCameraInfo.orientation, 7032f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian mCameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT); 7042f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 705ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 706ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 707ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 708ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static class SizeComparator implements Comparator<Camera.Size> { 709ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int PREFER_LEFT = -1; 710ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int PREFER_RIGHT = 1; 711ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 712ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // The max width/height for the preferred size. Integer.MAX_VALUE if no size limit 713ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final int mMaxWidth; 714ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final int mMaxHeight; 715ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 716ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // The desired aspect ratio 717ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final float mTargetAspectRatio; 718ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 719ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // The desired size (width x height) to try to match 720ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final int mTargetPixels; 721ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 722ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public SizeComparator( 723ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int maxWidth, 724ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int maxHeight, 725ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final float targetAspectRatio, 726ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int targetPixels) { 727ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mMaxWidth = maxWidth; 728ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mMaxHeight = maxHeight; 729ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mTargetAspectRatio = targetAspectRatio; 730ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mTargetPixels = targetPixels; 731ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 732ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 733ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 734ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Returns a negative value if left is a better choice than right, or a positive value if right 735ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * is a better choice is better than left. 0 if they are equal 736ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 737ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 738ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public int compare(final Camera.Size left, final Camera.Size right) { 739ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // If one size is less than the max size prefer it over the other 740ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if ((left.width <= mMaxWidth && left.height <= mMaxHeight) 741ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian != (right.width <= mMaxWidth && right.height <= mMaxHeight)) { 742ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return left.width <= mMaxWidth ? PREFER_LEFT : PREFER_RIGHT; 743ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 744ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 745ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // If one is closer to the target aspect ratio, prefer it. 746ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final float leftAspectRatio = left.width / (float) left.height; 747ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final float rightAspectRatio = right.width / (float) right.height; 748ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final float leftAspectRatioDiff = Math.abs(leftAspectRatio - mTargetAspectRatio); 749ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final float rightAspectRatioDiff = Math.abs(rightAspectRatio - mTargetAspectRatio); 750ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (leftAspectRatioDiff != rightAspectRatioDiff) { 751ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return (leftAspectRatioDiff - rightAspectRatioDiff) < 0 ? PREFER_LEFT : PREFER_RIGHT; 752ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 753ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 754ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // At this point they have the same aspect ratio diff and are either both bigger 755ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // than the max size or both smaller than the max size, so prefer the one closest 756ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // to target size 757ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int leftDiff = Math.abs((left.width * left.height) - mTargetPixels); 758ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int rightDiff = Math.abs((right.width * right.height) - mTargetPixels); 759ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return leftDiff - rightDiff; 760ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 761ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 762ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 763ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override // From FocusOverlayManager.Listener 764ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void autoFocus() { 765ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCamera == null) { 766ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 767ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 768ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 769ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 770ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.autoFocus( 771ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new Camera.AutoFocusCallback() { 772ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 773ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onAutoFocus(final boolean success, final Camera camera) { 774ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.onAutoFocus(success, false /* shutterDown */); 775ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 776ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }); 777ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 778ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CameraManager.autoFocus", "RuntimeException in CameraManager.autoFocus", e); 779ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // If autofocus fails, the camera should have called the callback with success=false, 780ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // but some throw an exception here 781ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mFocusOverlayManager.onAutoFocus(false /*success*/, false /*shutterDown*/); 782ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 783ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 784ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 785ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override // From FocusOverlayManager.Listener 786ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void cancelAutoFocus() { 787ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCamera == null) { 788ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 789ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 790ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 791ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.cancelAutoFocus(); 792ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 793ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Ignore 794ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e( 795ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CameraManager.cancelAutoFocus", "RuntimeException in CameraManager.cancelAutoFocus", e); 796ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 797ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 798ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 799ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override // From FocusOverlayManager.Listener 800ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public boolean capture() { 801ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return false; 802ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 803ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 804ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override // From FocusOverlayManager.Listener 805ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void setFocusParameters() { 806ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCamera == null) { 807ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 808ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 809ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian try { 810ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Camera.Parameters parameters = mCamera.getParameters(); 811ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian parameters.setFocusMode(mFocusOverlayManager.getFocusMode()); 812ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (parameters.getMaxNumFocusAreas() > 0) { 813ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Don't set focus areas (even to null) if focus areas aren't supported, camera may 814ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // crash 815ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian parameters.setFocusAreas(mFocusOverlayManager.getFocusAreas()); 816ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 817ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian parameters.setMeteringAreas(mFocusOverlayManager.getMeteringAreas()); 818ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.setParameters(parameters); 819ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } catch (final RuntimeException e) { 820ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // This occurs when the device is out of space or when the camera is locked 821ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e( 822ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CameraManager.setFocusParameters", 823ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "RuntimeException in CameraManager setFocusParameters"); 824ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 825ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 826ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 827ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void resetPreview() { 828ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCamera.startPreview(); 829ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCameraPreview != null) { 830ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCameraPreview.setFocusable(true); 831ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 832ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 833ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 834ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void logCameraSize(final String prefix, final Camera.Size size) { 835ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Log the camera size and aspect ratio for help when examining bug reports for camera 836ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // failures 837ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i( 838ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CameraManager.logCameraSize", 839ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian prefix + size.width + "x" + size.height + " (" + (size.width / (float) size.height) + ")"); 840ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 841ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 842ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @VisibleForTesting 843ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void resetCameraManager() { 844ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian sInstance = null; 845ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 846ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian} 847