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