1b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford/* 2b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Copyright (C) 2015 The Android Open Source Project 3b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * 4b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Licensed under the Apache License, Version 2.0 (the "License"); 5b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * you may not use this file except in compliance with the License. 6b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * You may obtain a copy of the License at 7b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * 8b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * http://www.apache.org/licenses/LICENSE-2.0 9b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * 10b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Unless required by applicable law or agreed to in writing, software 11b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * distributed under the License is distributed on an "AS IS" BASIS, 12b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * See the License for the specific language governing permissions and 14b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * limitations under the License. 15b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 16b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 17b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordpackage com.android.example.cannylive; 18b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 19b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.content.Context; 20b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.graphics.ImageFormat; 21b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.CameraAccessException; 22b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.CameraCaptureSession; 23b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.CameraCharacteristics; 24b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.CameraDevice; 25b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.CameraManager; 26b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.CaptureRequest; 27b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.TotalCaptureResult; 28b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.hardware.camera2.params.StreamConfigurationMap; 29b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.media.Image; 30b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.media.ImageReader; 31b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.os.ConditionVariable; 32b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.os.Handler; 33b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.os.HandlerThread; 34b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.os.Looper; 35b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.util.Log; 36b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.util.Range; 37b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.util.Size; 38b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.view.Surface; 39b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport android.view.SurfaceHolder; 40b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 41b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.io.IOException; 42b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.io.OutputStream; 43b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.nio.ByteBuffer; 44b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.util.ArrayList; 45b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.util.Arrays; 46b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.util.Collections; 47b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.util.Comparator; 48b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordimport java.util.List; 49b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 50b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford/** 51b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Simple interface for operating the camera, with major camera operations 52b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * all performed on a background handler thread. 53b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 54b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehofordpublic class CameraOps { 55b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 56b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private static final String TAG = "CameraOps"; 57b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private static final long ONE_SECOND = 1000000000; 58b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public static final long CAMERA_CLOSE_TIMEOUT = 2000; // ms 59b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 60b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final CameraManager mCameraManager; 61b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private CameraDevice mCameraDevice; 62b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private CameraCaptureSession mCameraSession; 63b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private List<Surface> mSurfaces; 64b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 65b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final ConditionVariable mCloseWaiter = new ConditionVariable(); 66b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 67b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private HandlerThread mCameraThread; 68b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private Handler mCameraHandler; 69b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 70b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final ErrorDisplayer mErrorDisplayer; 71b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 72b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final CameraReadyListener mReadyListener; 73b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final Handler mReadyHandler; 74b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 75b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private int mISOmax; 76b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private int mISOmin; 77b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private long mExpMax; 78b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private long mExpMin; 79b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private float mFocusMin; 80b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private float mFocusDist = 0; 81b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private int mIso; 82b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford boolean mAutoExposure = true; 83b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford boolean mAutoFocus = true; 84b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private long mExposure = ONE_SECOND / 33; 85b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 86b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private Object mAutoExposureTag = new Object(); 87b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 88b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private ImageReader mImageReader; 89b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private Handler mBackgroundHandler; 90b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private CameraCharacteristics mCameraInfo; 91b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private HandlerThread mBackgroundThread; 92b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CaptureRequest.Builder mHdrBuilder; 93b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private Surface mProcessingNormalSurface; 94b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CaptureRequest mPreviewRequest; 95b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private String mSaveFileName; 96b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private Context mContext; 97b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private int mCaptureMode; 98b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 99b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public String resume() { 100b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String errorMessage = "Unknown error"; 101b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford boolean foundCamera = false; 102b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 103b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // Find first back-facing camera that has necessary capability 104b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String[] cameraIds = mCameraManager.getCameraIdList(); 105b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford for (String id : cameraIds) { 106b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CameraCharacteristics info = mCameraManager.getCameraCharacteristics(id); 107b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford int facing = info.get(CameraCharacteristics.LENS_FACING); 108b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 109b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford int level = info.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); 110b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford boolean hasFullLevel 111b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford = (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL); 112b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 113b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford int[] capabilities = info.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES); 114b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford int syncLatency = info.get(CameraCharacteristics.SYNC_MAX_LATENCY); 115b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford boolean hasManualControl = hasCapability(capabilities, 116b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR); 117b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford boolean hasEnoughCapability = hasManualControl && 118b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford syncLatency == CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL; 119b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Range<Integer> irange; 120b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Range<Long> lrange; 121b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 122b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford irange = info.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE); 123b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (irange != null) { 124b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mISOmax = irange.getUpper(); 125b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mISOmin = irange.getLower(); 126b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford lrange = info.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE); 127b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mExpMax = lrange.getUpper(); 128b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mExpMin = lrange.getLower(); 129b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mFocusMin = info.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE); 130b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } else { 131b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mISOmax = 200; 132b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mISOmin = 100; 133b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mExpMax = 1000; 134b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 135b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mFocusDist = mFocusMin; 136b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford StreamConfigurationMap map = info.get( 137b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 138b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Size[] sizes = map.getOutputSizes(ImageFormat.JPEG); 139b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford List<Size> sizeList = Arrays.asList(sizes); 140b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Collections.sort(sizeList, new Comparator<Size>() { 141b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 142b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public int compare(Size lhs, Size rhs) { 143b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford int leftArea = lhs.getHeight() * lhs.getWidth(); 144b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford int rightArea = lhs.getHeight() * lhs.getWidth(); 145b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return Integer.compare(leftArea, rightArea); 146b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 147b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }); 148b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Size max = sizeList.get(0); 149b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford int check = 1; 150b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Size big = sizeList.get(check); 151b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford float aspect = 16/9f; 152b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG,"max big "+max.getWidth()+" x "+max.getHeight()); 153b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford for (int i = 0; i < sizeList.size(); i++) { 154b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Size s = sizeList.get(i); 155b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (s.getHeight() == 720) { 156b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford big = s; 157b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford break; 158b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 159b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 160b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG,"BIG wil be "+big.getWidth()+" x "+big.getHeight()); 161b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mImageReader = ImageReader.newInstance(big.getWidth(), big.getHeight(), 162b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford ImageFormat.JPEG, /*maxImages*/2); 163b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mImageReader.setOnImageAvailableListener( 164b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mOnImageAvailableListener, mBackgroundHandler); 165b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 166b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (facing == CameraCharacteristics.LENS_FACING_BACK && 167b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford (hasFullLevel || hasEnoughCapability)) { 168b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // Found suitable camera - get info, open, and set up outputs 169b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraInfo = info; 170b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford openCamera(id); 171b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford foundCamera = true; 172b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford break; 173b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 174b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 175b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (!foundCamera) { 176b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford errorMessage = "no back camera"; 177b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 178b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 179b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford errorMessage = e.getMessage(); 180b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 181b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // startBackgroundThread 182b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundThread = new HandlerThread("CameraBackground"); 183b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundThread.start(); 184b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); 185b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return (foundCamera) ? null : errorMessage; 186b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 187b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 188b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 189b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private boolean hasCapability(int[] capabilities, int capability) { 190b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford for (int c : capabilities) { 191b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (c == capability) return true; 192b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 193b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return false; 194b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 195b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 196b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final ImageReader.OnImageAvailableListener mOnImageAvailableListener 197b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford = new ImageReader.OnImageAvailableListener() { 198b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 199b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 200b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onImageAvailable(ImageReader reader) { 201b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), 202b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mSaveFileName, mContext,mCaptureMode)); 203b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 204b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 205b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }; 206b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 207b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 208b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Saves a JPEG {@link android.media.Image} into the specified {@link java.io.File}. 209b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 210b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private static class ImageSaver implements Runnable { 211b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final Image mImage; 212b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private final String mName; 213b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Context mContext; 214b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private int mMode; 215b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 216b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public ImageSaver(Image image, String fileName, Context context,int mode) { 217b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mImage = image; 218b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mName = fileName; 219b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mContext = context; 220b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mMode = mode; 221b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 222b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 223b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 224b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 225b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, "S>> SAVING..."); 226b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String url = MediaStoreSaver.insertImage(mContext.getContentResolver(), 227b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford new MediaStoreSaver.StreamWriter() { 228b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 229b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void write(OutputStream imageOut) throws IOException { 230b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 231b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford ByteBuffer buffer = mImage.getPlanes()[0].getBuffer(); 232b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford byte[] bytes = new byte[buffer.remaining()]; 233b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, "S>> size=" + mImage.getWidth() + 234b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford "," + mImage.getHeight()); 235b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, "S>> bytes " + bytes.length + 236b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford " (" + bytes.length / (1024 * 1024) + "MB"); 237b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, "S>> bytes out " + bytes.length / mImage.getWidth()); 238b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford buffer.get(bytes); 239b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford imageOut.write(bytes); 240b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } finally { 241b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mImage.close(); 242b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 243b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 244b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }, mName, "Saved from Simple Camera Demo"); 245b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford ViewfinderProcessor.reProcessImage(mContext, url, mMode); 246b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 247b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 248b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 249b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 250b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Create a new camera ops thread. 251b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * 252b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * @param errorDisplayer listener for displaying error messages 253b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * @param readyListener listener for notifying when camera is ready for requests 254b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 255b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CameraOps(CameraManager manager, ErrorDisplayer errorDisplayer, 256b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CameraReadyListener readyListener) { 257b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mReadyHandler = new Handler(Looper.getMainLooper()); 258b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 259b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraThread = new HandlerThread("CameraOpsThread"); 260b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraThread.start(); 261b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 262b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (manager == null || errorDisplayer == null || 263b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford readyListener == null || mReadyHandler == null) { 264b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford throw new IllegalArgumentException("Need valid displayer, listener, handler"); 265b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 266b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 267b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraManager = manager; 268b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer = errorDisplayer; 269b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mReadyListener = readyListener; 270b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 271b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 272b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 273b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 274b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Open the first backfacing camera listed by the camera manager. 275b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Displays a dialog if it cannot open a camera. 276b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 277b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void openCamera(final String cameraId) { 278b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraHandler = new Handler(mCameraThread.getLooper()); 279b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 280b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraHandler.post(new Runnable() { 281b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 282b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (mCameraDevice != null) { 283b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford throw new IllegalStateException("Camera already open"); 284b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 285b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 286b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 287b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraManager.openCamera(cameraId, mCameraDeviceListener, mCameraHandler); 288b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 289b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String errorMessage = mErrorDisplayer.getErrorString(e); 290b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog(errorMessage); 291b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 292b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 293b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }); 294b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 295b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 296b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void pause() { 297b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 298b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford closeCameraAndWait(); 299b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundThread.quitSafely(); 300b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 301b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundThread.join(); 302b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundThread = null; 303b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mBackgroundHandler = null; 304b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (InterruptedException e) { 305b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford e.printStackTrace(); 306b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 307b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 308b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 309b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public Size getBestSize() { 310b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // Find a good size for output - largest 16:9 aspect ratio that's less than 720p 311b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final int MAX_WIDTH = 640; 312b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final float TARGET_ASPECT = 16.f / 9.f; 313b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 314b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 315b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford StreamConfigurationMap configs = 316b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraInfo.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 317b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 318b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Size[] outputSizes = configs.getOutputSizes(SurfaceHolder.class); 319b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 320b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Size outputSize = null; 321b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford ArrayList<Size> smallEnough = new ArrayList<Size>(); 322b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford for (Size candidateSize : outputSizes) { 323b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (candidateSize.getWidth() <= MAX_WIDTH) { 324b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, "consider " + candidateSize); 325b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford smallEnough.add(candidateSize); 326b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 327b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 328b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (smallEnough.size() == 0) { 329b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return outputSizes[outputSizes.length - 1]; //pick the smallest 330b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 331b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Size maxSize = smallEnough.get(0); 332b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford double aspectDelta = Math.abs(maxSize.getWidth() / maxSize.getHeight() - TARGET_ASPECT); 333b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford for (Size candidateSize : smallEnough) { 334b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (maxSize.getWidth() < candidateSize.getWidth()) { 335b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford maxSize = candidateSize; 336b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford aspectDelta = Math.abs(maxSize.getWidth() / maxSize.getHeight() - TARGET_ASPECT); 337b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 338b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (maxSize.getWidth() == candidateSize.getWidth()) { 339b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (aspectDelta > Math.abs(candidateSize.getWidth() / candidateSize.getHeight() - TARGET_ASPECT)) { 340b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford maxSize = candidateSize; 341b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford aspectDelta = Math.abs(maxSize.getWidth() / maxSize.getHeight() - TARGET_ASPECT); 342b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 343b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 344b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 345b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 346b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return maxSize; 347b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 348b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 349b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 350b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Close the camera and wait for the close callback to be called in the camera thread. 351b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Times out after @{value CAMERA_CLOSE_TIMEOUT} ms. 352b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 353b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void closeCameraAndWait() { 354b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCloseWaiter.close(); 355b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraHandler.post(mCloseCameraRunnable); 356b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford boolean closed = mCloseWaiter.block(CAMERA_CLOSE_TIMEOUT); 357b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (!closed) { 358b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.e(TAG, "Timeout closing camera"); 359b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 360b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 361b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 362b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private Runnable mCloseCameraRunnable = new Runnable() { 363b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 364b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (mCameraDevice != null) { 365b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice.close(); 366b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 367b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice = null; 368b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraSession = null; 369b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mSurfaces = null; 370b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 371b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }; 372b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 373b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 374b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Set the output Surfaces, and finish configuration if otherwise ready. 375b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 376b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setSurface(Surface surface) { 377b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final List<Surface> surfaceList = new ArrayList<Surface>(); 378b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford surfaceList.add(surface); 379b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford surfaceList.add(mImageReader.getSurface()); 380b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 381b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraHandler.post(new Runnable() { 382b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 383b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mSurfaces = surfaceList; 384b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford startCameraSession(); 385b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 386b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }); 387b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 388b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 389b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 390b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Get a request builder for the current camera. 391b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 392b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public CaptureRequest.Builder createCaptureRequest(int template) throws CameraAccessException { 393b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CameraDevice device = mCameraDevice; 394b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (device == null) { 395b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford throw new IllegalStateException("Can't get requests when no camera is open"); 396b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 397b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return device.createCaptureRequest(template); 398b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 399b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 400b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 401b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Set a repeating request. 402b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 403b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setRepeatingRequest(final CaptureRequest request, 404b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final CameraCaptureSession.CaptureCallback listener, 405b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final Handler handler) { 406b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraHandler.post(new Runnable() { 407b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 408b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 409b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraSession.setRepeatingRequest(request, listener, handler); 410b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 411b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String errorMessage = mErrorDisplayer.getErrorString(e); 412b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog(errorMessage); 413b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 414b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 415b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }); 416b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 417b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 418b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 419b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Set a repeating request. 420b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 421b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setRepeatingBurst(final List<CaptureRequest> requests, 422b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final CameraCaptureSession.CaptureCallback listener, 423b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final Handler handler) { 424b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraHandler.post(new Runnable() { 425b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 426b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 427b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraSession.setRepeatingBurst(requests, listener, handler); 428b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 429b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 430b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String errorMessage = mErrorDisplayer.getErrorString(e); 431b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog(errorMessage); 432b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 433b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 434b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }); 435b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 436b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 437b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 438b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Configure the camera session. 439b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 440b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private void startCameraSession() { 441b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // Wait until both the camera device is open and the SurfaceView is ready 442b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (mCameraDevice == null || mSurfaces == null) return; 443b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 444b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 445b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 446b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice.createCaptureSession( 447b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mSurfaces, mCameraSessionListener, mCameraHandler); 448b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 449b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String errorMessage = mErrorDisplayer.getErrorString(e); 450b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog(errorMessage); 451b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice.close(); 452b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice = null; 453b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 454b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 455b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 456b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 457b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Main listener for camera session events 458b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Invoked on mCameraThread 459b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 460b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private CameraCaptureSession.StateCallback mCameraSessionListener = 461b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford new CameraCaptureSession.StateCallback() { 462b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 463b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 464b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onConfigured(CameraCaptureSession session) { 465b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraSession = session; 466b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mReadyHandler.post(new Runnable() { 467b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 468b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // This can happen when the screen is turned off and turned back on. 469b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (null == mCameraDevice) { 470b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return; 471b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 472b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 473b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mReadyListener.onCameraReady(); 474b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 475b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }); 476b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 477b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 478b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 479b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 480b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onConfigureFailed(CameraCaptureSession session) { 481b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog("Unable to configure the capture session"); 482b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice.close(); 483b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice = null; 484b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 485b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }; 486b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 487b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 488b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Main listener for camera device events. 489b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Invoked on mCameraThread 490b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 491b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private CameraDevice.StateCallback mCameraDeviceListener = new CameraDevice.StateCallback() { 492b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 493b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 494b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onOpened(CameraDevice camera) { 495b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice = camera; 496b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford startCameraSession(); 497b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 498b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 499b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 500b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onClosed(CameraDevice camera) { 501b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCloseWaiter.open(); 502b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 503b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 504b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 505b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onDisconnected(CameraDevice camera) { 506b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog("The camera device has been disconnected."); 507b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford camera.close(); 508b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice = null; 509b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 510b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 511b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 512b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onError(CameraDevice camera, int error) { 513b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog("The camera encountered an error:" + error); 514b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford camera.close(); 515b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraDevice = null; 516b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 517b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 518b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }; 519b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 520b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void captureStillPicture(int currentJpegRotation, String name, Context context, int mode) { 521b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mSaveFileName = name; 522b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mContext = context; 523b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCaptureMode = mode; 524b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 525b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // TODO call lock focus if we are in "AF-S(One-Shot AF) mode" 526b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // TODO call precapture if we are using flash 527b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // This is the CaptureRequest.Builder that we use to take a picture. 528b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final CaptureRequest.Builder captureBuilder = 529b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 530b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, "S>> Target " + mImageReader.getWidth() + "," + mImageReader.getHeight()); 531b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 532b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford captureBuilder.addTarget(mImageReader.getSurface()); 533b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 534b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, currentJpegRotation); 535b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 536b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CameraCaptureSession.CaptureCallback captureCallback 537b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford = new CameraCaptureSession.CaptureCallback() { 538b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 539b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford @Override 540b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, 541b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford TotalCaptureResult result) { 542b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, "S>> onCaptureCompleted"); 543b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford setParameters(); 544b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 545b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }; 546b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 547b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 548b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford setRequest(captureBuilder.build(), captureCallback, null); 549b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 550b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford e.printStackTrace(); 551b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 552b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 553b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 554b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 555b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Set a repeating request. 556b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 557b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private void setRequest(final CaptureRequest request, 558b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final CameraCaptureSession.CaptureCallback listener, 559b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford final Handler handler) { 560b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraHandler.post(new Runnable() { 561b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void run() { 562b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 563b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraSession.stopRepeating(); 564b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mCameraSession.capture(request, listener, handler); 565b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 566b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String errorMessage = mErrorDisplayer.getErrorString(e); 567b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mErrorDisplayer.showErrorDialog(errorMessage); 568b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 569b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 570b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }); 571b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 572b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 573b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setUpCamera(Surface processingNormalSurface) { 574b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mProcessingNormalSurface = processingNormalSurface; 575b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // Ready to send requests in, so set them up 576b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford try { 577b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CaptureRequest.Builder previewBuilder = 578b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 579b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford previewBuilder.addTarget(mProcessingNormalSurface); 580b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford previewBuilder.setTag(mAutoExposureTag); 581b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mPreviewRequest = previewBuilder.build(); 582b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder = createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 583b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.CONTROL_AE_MODE, 584b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford CaptureRequest.CONTROL_AE_MODE_OFF); 585b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.addTarget(mProcessingNormalSurface); 586b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford setParameters(); 587b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 588b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } catch (CameraAccessException e) { 589b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford String errorMessage = e.getMessage(); 590b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford // MessageDialogFragment.newInstance(errorMessage).show(getFragmentManager(), FRAGMENT_DIALOG); 591b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 592b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 593b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 594b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 595b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Start running an HDR burst on a configured camera session 596b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 597b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setParameters() { 598b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (mHdrBuilder == null) { 599b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford Log.v(TAG, " Camera not set up"); 600b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return; 601b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 602b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (mAutoExposure) { 603b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, ONE_SECOND / 30); 604b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, getExposure()); 605b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); 606b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } else { 607b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF); 608b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, ONE_SECOND / 30); 609b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, getExposure()); 610b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, getIso()); 611b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 612b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford if (mAutoFocus) { 613b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO); 614b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); 615b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } else { 616b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF); 617b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, getFocusDistance()); 618b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mHdrBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); 619b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 620b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 621b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford setRepeatingRequest(mHdrBuilder.build(), mCaptureCallback, mReadyHandler); 622b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 623b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 624b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford private CameraCaptureSession.CaptureCallback mCaptureCallback 625b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford = new CameraCaptureSession.CaptureCallback() { 626b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 627b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, 628b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford TotalCaptureResult result) { 629b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 630b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford }; 631b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 632b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 633b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Simple listener for main code to know the camera is ready for requests, or failed to 634b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * start. 635b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 636b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public interface CameraReadyListener { 637b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void onCameraReady(); 638b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 639b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 640b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford /** 641b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford * Simple listener for displaying error messages 642b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford */ 643b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public interface ErrorDisplayer { 644b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void showErrorDialog(String errorMessage); 645b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 646b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public String getErrorString(CameraAccessException e); 647b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 648b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 649b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public float getFocusDistance() { 650b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mFocusDist; 651b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 652b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 653b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setFocusDistance(float focusDistance) { 654b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mFocusDist = focusDistance; 655b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 656b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 657b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setIso(int iso) { 658b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mIso = iso; 659b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 660b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 661b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public boolean isAutoExposure() { 662b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mAutoExposure; 663b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 664b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 665b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setAutoExposure(boolean autoExposure) { 666b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mAutoExposure = autoExposure; 667b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 668b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 669b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public boolean isAutoFocus() { 670b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mAutoFocus; 671b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 672b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 673b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setAutoFocus(boolean autoFocus) { 674b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mAutoFocus = autoFocus; 675b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 676b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 677b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public int getIso() { 678b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mIso; 679b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 680b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 681b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public long getExposure() { 682b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mExposure; 683b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 684b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 685b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public void setExposure(long exposure) { 686b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford mExposure = exposure; 687b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 688b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 689b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public int getIsoMax() { 690b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mISOmax; 691b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 692b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 693b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public int getIsoMin() { 694b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mISOmin; 695b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 696b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 697b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public long getExpMax() { 698b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mExpMax; 699b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 700b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 701b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public long getExpMin() { 702b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mExpMin; 703b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 704b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford 705b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford public float getFocusMin() { 706b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford return mFocusMin; 707b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford } 708b7a6edcb8646d1ef4a090769c1ed53f273d89e6ehoford} 709