1a0842b40441db5332a5290f941021636b1182761Sol Boucher/*
2a0842b40441db5332a5290f941021636b1182761Sol Boucher * Copyright (C) 2014 The Android Open Source Project
3a0842b40441db5332a5290f941021636b1182761Sol Boucher *
4a0842b40441db5332a5290f941021636b1182761Sol Boucher * Licensed under the Apache License, Version 2.0 (the "License");
5a0842b40441db5332a5290f941021636b1182761Sol Boucher * you may not use this file except in compliance with the License.
6a0842b40441db5332a5290f941021636b1182761Sol Boucher * You may obtain a copy of the License at
7a0842b40441db5332a5290f941021636b1182761Sol Boucher *
8a0842b40441db5332a5290f941021636b1182761Sol Boucher *      http://www.apache.org/licenses/LICENSE-2.0
9a0842b40441db5332a5290f941021636b1182761Sol Boucher *
10a0842b40441db5332a5290f941021636b1182761Sol Boucher * Unless required by applicable law or agreed to in writing, software
11a0842b40441db5332a5290f941021636b1182761Sol Boucher * distributed under the License is distributed on an "AS IS" BASIS,
12a0842b40441db5332a5290f941021636b1182761Sol Boucher * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a0842b40441db5332a5290f941021636b1182761Sol Boucher * See the License for the specific language governing permissions and
14a0842b40441db5332a5290f941021636b1182761Sol Boucher * limitations under the License.
15a0842b40441db5332a5290f941021636b1182761Sol Boucher */
16a0842b40441db5332a5290f941021636b1182761Sol Boucher
17a0842b40441db5332a5290f941021636b1182761Sol Boucherpackage com.android.ex.camera2.portability;
18a0842b40441db5332a5290f941021636b1182761Sol Boucher
19de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport static android.hardware.camera2.CaptureRequest.*;
20de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
212569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucherimport android.graphics.Matrix;
22de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.graphics.Rect;
232569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucherimport android.graphics.RectF;
24de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.hardware.camera2.CameraAccessException;
25de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.hardware.camera2.CameraDevice;
26de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.hardware.camera2.params.MeteringRectangle;
27d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucherimport android.location.Location;
28de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.util.Range;
29de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
30de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.portability.CameraCapabilities.FlashMode;
31de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.portability.CameraCapabilities.FocusMode;
32de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.portability.CameraCapabilities.SceneMode;
33de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.portability.CameraCapabilities.WhiteBalance;
34de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.portability.debug.Log;
35de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.utils.Camera2RequestSettingsSet;
36de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
37de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport java.util.List;
38de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport java.util.Objects;
39a0842b40441db5332a5290f941021636b1182761Sol Boucher
40a0842b40441db5332a5290f941021636b1182761Sol Boucher/**
41a0842b40441db5332a5290f941021636b1182761Sol Boucher * The subclass of {@link CameraSettings} for Android Camera 2 API.
42a0842b40441db5332a5290f941021636b1182761Sol Boucher */
43a0842b40441db5332a5290f941021636b1182761Sol Boucherpublic class AndroidCamera2Settings extends CameraSettings {
44de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private static final Log.Tag TAG = new Log.Tag("AndCam2Set");
45de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
46de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private final Builder mTemplateSettings;
47de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private final Camera2RequestSettingsSet mRequestSettings;
482569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher    /** Sensor's active array bounds. */
499d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher    private final Rect mActiveArray;
502569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher    /** Crop rectangle for digital zoom (measured WRT the active array). */
519d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher    private final Rect mCropRectangle;
522569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher    /** Bounds of visible preview portion (measured WRT the active array). */
532569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher    private Rect mVisiblePreviewRectangle;
54de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
55de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    /**
56de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * Create a settings representation that answers queries of unspecified
57de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * options in the same way as the provided template would.
58de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     *
59de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * <p>The default settings provided by the given template are only ever used
60de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * for reporting back to the client app (i.e. when it queries an option
61de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * it didn't explicitly set first). {@link Camera2RequestSettingsSet}s
62de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * generated by an instance of this class will have any settings not
63de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * modified using one of that instance's mutators forced to default, so that
64de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * their effective values when submitting a capture request will be those of
65de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * the template that is provided to the camera framework at that time.</p>
66de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     *
679d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher     * @param camera Device from which to draw default settings
689d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher     *               (non-{@code null}).
69de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * @param template Specific template to use for the defaults.
709d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher     * @param activeArray Boundary coordinates of the sensor's active array
719d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher     *                    (non-{@code null}).
72de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * @param preview Dimensions of preview streams.
73de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * @param photo Dimensions of captured images.
74de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     *
759d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher     * @throws IllegalArgumentException If {@code camera} or {@code activeArray}
769d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher     *                                  is {@code null}.
77de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     * @throws CameraAccessException Upon internal framework/driver failure.
78de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher     */
79de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    public AndroidCamera2Settings(CameraDevice camera, int template, Rect activeArray,
80de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                  Size preview, Size photo) throws CameraAccessException {
819d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        if (camera == null) {
829d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            throw new NullPointerException("camera must not be null");
839d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        }
849d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        if (activeArray == null) {
859d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            throw new NullPointerException("activeArray must not be null");
869d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        }
879d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher
88de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mTemplateSettings = camera.createCaptureRequest(template);
89de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings = new Camera2RequestSettingsSet();
909d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mActiveArray = activeArray;
919d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mCropRectangle = new Rect(0, 0, activeArray.width(), activeArray.height());
92de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
932569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        mSizesLocked = false;
942569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
95de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Range<Integer> previewFpsRange = mTemplateSettings.get(CONTROL_AE_TARGET_FPS_RANGE);
96de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (previewFpsRange != null) {
97de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            setPreviewFpsRange(previewFpsRange.getLower(), previewFpsRange.getUpper());
98de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
99a0842b40441db5332a5290f941021636b1182761Sol Boucher        setPreviewSize(preview);
100de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mCurrentPreviewFormat
101a0842b40441db5332a5290f941021636b1182761Sol Boucher        setPhotoSize(photo);
102de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mJpegCompressQuality = queryTemplateDefaultOrMakeOneUp(JPEG_QUALITY, (byte) 0);
103de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mCurrentPhotoFormat
1049d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        // NB: We're assuming that templates won't be zoomed in by default.
1059d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mCurrentZoomRatio = CameraCapabilities.ZOOM_RATIO_UNZOOMED;
106de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mCurrentZoomIndex
107de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mExposureCompensationIndex =
108de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                queryTemplateDefaultOrMakeOneUp(CONTROL_AE_EXPOSURE_COMPENSATION, 0);
109bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher
110de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mCurrentFlashMode = flashModeFromRequest();
111bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        Integer currentFocusMode = mTemplateSettings.get(CONTROL_AF_MODE);
112bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        if (currentFocusMode != null) {
113bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher            mCurrentFocusMode = AndroidCamera2Capabilities.focusModeFromInt(currentFocusMode);
114bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        }
115bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        Integer currentSceneMode = mTemplateSettings.get(CONTROL_SCENE_MODE);
116bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        if (currentSceneMode != null) {
117bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher            mCurrentSceneMode = AndroidCamera2Capabilities.sceneModeFromInt(currentSceneMode);
118bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        }
119bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        Integer whiteBalance = mTemplateSettings.get(CONTROL_AWB_MODE);
120bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        if (whiteBalance != null) {
121bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher            mWhiteBalance = AndroidCamera2Capabilities.whiteBalanceFromInt(whiteBalance);
122bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher        }
123bc9c0e2cb071b085ecc5646751fb59f5145d51b1Sol Boucher
124de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mVideoStabilizationEnabled = queryTemplateDefaultOrMakeOneUp(
125de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        CONTROL_VIDEO_STABILIZATION_MODE, CONTROL_VIDEO_STABILIZATION_MODE_OFF) ==
126de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                CONTROL_VIDEO_STABILIZATION_MODE_ON;
127de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mAutoExposureLocked = queryTemplateDefaultOrMakeOneUp(CONTROL_AE_LOCK, false);
128de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mAutoWhiteBalanceLocked = queryTemplateDefaultOrMakeOneUp(CONTROL_AWB_LOCK, false);
129de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mRecordingHintEnabled
130de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mGpsData
131de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        android.util.Size exifThumbnailSize = mTemplateSettings.get(JPEG_THUMBNAIL_SIZE);
132de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (exifThumbnailSize != null) {
133de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            mExifThumbnailSize =
134de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    new Size(exifThumbnailSize.getWidth(), exifThumbnailSize.getHeight());
135de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
136de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
137de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
138de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    public AndroidCamera2Settings(AndroidCamera2Settings other) {
139de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        super(other);
140de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mTemplateSettings = other.mTemplateSettings;
141de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings = new Camera2RequestSettingsSet(other.mRequestSettings);
1429d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mActiveArray = other.mActiveArray;
1439d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mCropRectangle = new Rect(other.mCropRectangle);
144de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
145de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
146de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    @Override
147de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    public CameraSettings copy() {
148de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        return new AndroidCamera2Settings(this);
149de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
150de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
151de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private <T> T queryTemplateDefaultOrMakeOneUp(Key<T> key, T defaultDefault) {
152de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        T val = mTemplateSettings.get(key);
153de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (val != null) {
154de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return val;
155de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else {
156de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            // Spoof the default so matchesTemplateDefault excludes this key from generated sets.
157de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            // This approach beats a simple sentinel because it provides basic boolean support.
158de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            mTemplateSettings.set(key, defaultDefault);
159de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return defaultDefault;
160de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
161de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
162de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
163de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private FlashMode flashModeFromRequest() {
164de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Integer autoExposure = mTemplateSettings.get(CONTROL_AE_MODE);
165de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (autoExposure != null) {
166de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            switch (autoExposure) {
167de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CONTROL_AE_MODE_ON:
168de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    return FlashMode.OFF;
169de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CONTROL_AE_MODE_ON_AUTO_FLASH:
170de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    return FlashMode.AUTO;
171de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CONTROL_AE_MODE_ON_ALWAYS_FLASH: {
172de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    if (mTemplateSettings.get(FLASH_MODE) == FLASH_MODE_TORCH) {
173de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        return FlashMode.TORCH;
174de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    } else {
175de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        return FlashMode.ON;
176de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    }
177de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
178de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE:
179de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    return FlashMode.RED_EYE;
180de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
181de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
182de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        return null;
183de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
184de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
1859d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher    @Override
1869d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher    public void setZoomRatio(float ratio) {
1879d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        super.setZoomRatio(ratio);
1882569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
1892569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // Compute the crop rectangle to be passed to the framework
1909d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mCropRectangle.set(0, 0,
1919d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                toIntConstrained(
1929d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        mActiveArray.width() / mCurrentZoomRatio, 0, mActiveArray.width()),
1939d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                toIntConstrained(
1949d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        mActiveArray.height() / mCurrentZoomRatio, 0, mActiveArray.height()));
1959d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mCropRectangle.offsetTo((mActiveArray.width() - mCropRectangle.width()) / 2,
1969d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                (mActiveArray.height() - mCropRectangle.height()) / 2);
1972569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
1982569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // Compute the effective crop rectangle to be used for computing focus/metering coordinates
1992569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        mVisiblePreviewRectangle =
2002569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                effectiveCropRectFromRequested(mCropRectangle, mCurrentPreviewSize);
2019d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher    }
2029d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher
203de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private boolean matchesTemplateDefault(Key<?> setting) {
204de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (setting == CONTROL_AE_REGIONS) {
205de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return mMeteringAreas.size() == 0;
206de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == CONTROL_AF_REGIONS) {
207de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return mFocusAreas.size() == 0;
208de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == CONTROL_AE_TARGET_FPS_RANGE) {
209dc05ed7a8443af7c1a7b1bb39519d09d79284e42Igor Murashkin            Range<Integer> defaultFpsRange = mTemplateSettings.get(CONTROL_AE_TARGET_FPS_RANGE);
210de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return (mPreviewFpsRangeMin == 0 && mPreviewFpsRangeMax == 0) ||
211de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    (defaultFpsRange != null && mPreviewFpsRangeMin == defaultFpsRange.getLower() &&
212de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mPreviewFpsRangeMax == defaultFpsRange.getUpper());
213de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == JPEG_QUALITY) {
214de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return Objects.equals(mJpegCompressQuality,
215de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mTemplateSettings.get(JPEG_QUALITY));
216de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == CONTROL_AE_EXPOSURE_COMPENSATION) {
217de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return Objects.equals(mExposureCompensationIndex,
218de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mTemplateSettings.get(CONTROL_AE_EXPOSURE_COMPENSATION));
219de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == CONTROL_VIDEO_STABILIZATION_MODE) {
220de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            Integer videoStabilization = mTemplateSettings.get(CONTROL_VIDEO_STABILIZATION_MODE);
221de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return (videoStabilization != null &&
222de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    (mVideoStabilizationEnabled && videoStabilization ==
223de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            CONTROL_VIDEO_STABILIZATION_MODE_ON) ||
224de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    (!mVideoStabilizationEnabled && videoStabilization ==
225de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            CONTROL_VIDEO_STABILIZATION_MODE_OFF));
226de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == CONTROL_AE_LOCK) {
227de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return Objects.equals(mAutoExposureLocked, mTemplateSettings.get(CONTROL_AE_LOCK));
228de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == CONTROL_AWB_LOCK) {
229de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return Objects.equals(mAutoWhiteBalanceLocked, mTemplateSettings.get(CONTROL_AWB_LOCK));
230de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        } else if (setting == JPEG_THUMBNAIL_SIZE) {
231698997b9ef47f215350f03c0289f291846cd3604Puneet Lall            if (mExifThumbnailSize == null) {
232698997b9ef47f215350f03c0289f291846cd3604Puneet Lall                // It doesn't matter if this is true or false since setting this
233698997b9ef47f215350f03c0289f291846cd3604Puneet Lall                // to null in the request settings will use the default anyway.
234698997b9ef47f215350f03c0289f291846cd3604Puneet Lall                return false;
235698997b9ef47f215350f03c0289f291846cd3604Puneet Lall            }
236de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            android.util.Size defaultThumbnailSize = mTemplateSettings.get(JPEG_THUMBNAIL_SIZE);
237de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            return (mExifThumbnailSize.width() == 0 && mExifThumbnailSize.height() == 0) ||
238de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    (defaultThumbnailSize != null &&
239de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mExifThumbnailSize.width() == defaultThumbnailSize.getWidth() &&
240de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mExifThumbnailSize.height() == defaultThumbnailSize.getHeight());
241de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
242de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Log.w(TAG, "Settings implementation checked default of unhandled option key");
243de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // Since this class isn't equipped to handle it, claim it matches the default to prevent
244de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // updateRequestSettingOrForceToDefault from going with the user-provided preference
245de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        return true;
246de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
247de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
248de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private <T> void updateRequestSettingOrForceToDefault(Key<T> setting, T possibleChoice) {
249de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings.set(setting, matchesTemplateDefault(setting) ? null : possibleChoice);
250de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
251de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
252de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    public Camera2RequestSettingsSet getRequestSettings() {
253de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(CONTROL_AE_REGIONS,
254de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                legacyAreasToMeteringRectangles(mMeteringAreas));
255de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(CONTROL_AF_REGIONS,
256de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                legacyAreasToMeteringRectangles(mFocusAreas));
257de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(CONTROL_AE_TARGET_FPS_RANGE,
258de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                new Range(mPreviewFpsRangeMin, mPreviewFpsRangeMax));
259de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mCurrentPreviewFormat
260de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(JPEG_QUALITY, mJpegCompressQuality);
261de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mCurrentPhotoFormat
2629d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        mRequestSettings.set(SCALER_CROP_REGION, mCropRectangle);
263de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mCurrentZoomIndex
264de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(CONTROL_AE_EXPOSURE_COMPENSATION,
265de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                mExposureCompensationIndex);
266de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestFlashMode();
267de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestFocusMode();
268de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSceneMode();
269de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestWhiteBalance();
270de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(CONTROL_VIDEO_STABILIZATION_MODE,
271de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                mVideoStabilizationEnabled ?
272de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        CONTROL_VIDEO_STABILIZATION_MODE_ON : CONTROL_VIDEO_STABILIZATION_MODE_OFF);
273de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // OIS shouldn't be on if software video stabilization is.
274de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings.set(LENS_OPTICAL_STABILIZATION_MODE,
275de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                mVideoStabilizationEnabled ? LENS_OPTICAL_STABILIZATION_MODE_OFF :
276de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        null);
277de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(CONTROL_AE_LOCK, mAutoExposureLocked);
278de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        updateRequestSettingOrForceToDefault(CONTROL_AWB_LOCK, mAutoWhiteBalanceLocked);
279de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // TODO: mRecordingHintEnabled
280d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher        updateRequestGpsData();
281698997b9ef47f215350f03c0289f291846cd3604Puneet Lall        if (mExifThumbnailSize != null) {
282698997b9ef47f215350f03c0289f291846cd3604Puneet Lall            updateRequestSettingOrForceToDefault(JPEG_THUMBNAIL_SIZE,
283698997b9ef47f215350f03c0289f291846cd3604Puneet Lall                    new android.util.Size(
284698997b9ef47f215350f03c0289f291846cd3604Puneet Lall                            mExifThumbnailSize.width(), mExifThumbnailSize.height()));
285698997b9ef47f215350f03c0289f291846cd3604Puneet Lall        } else {
286698997b9ef47f215350f03c0289f291846cd3604Puneet Lall            updateRequestSettingOrForceToDefault(JPEG_THUMBNAIL_SIZE, null);
287698997b9ef47f215350f03c0289f291846cd3604Puneet Lall        }
288de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
289de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        return mRequestSettings;
290de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
291de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
292de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private MeteringRectangle[] legacyAreasToMeteringRectangles(
293de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            List<android.hardware.Camera.Area> reference) {
294de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        MeteringRectangle[] transformed = null;
295de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (reference.size() > 0) {
296de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            transformed = new MeteringRectangle[reference.size()];
297de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            for (int index = 0; index < reference.size(); ++index) {
298de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                android.hardware.Camera.Area source = reference.get(index);
299de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                Rect rectangle = source.rect;
300de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
301de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                // Old API coordinates were [-1000,1000]; new ones are [0,ACTIVE_ARRAY_SIZE).
3029d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                // We're also going from preview image--relative to sensor active array--relative.
303de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                double oldLeft = (rectangle.left + 1000) / 2000.0;
304de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                double oldTop = (rectangle.top + 1000) / 2000.0;
305de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                double oldRight = (rectangle.right + 1000) / 2000.0;
306de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                double oldBottom = (rectangle.bottom + 1000) / 2000.0;
3079d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                int left = mCropRectangle.left + toIntConstrained(
3089d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        mCropRectangle.width() * oldLeft, 0, mCropRectangle.width() - 1);
3099d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                int top = mCropRectangle.top + toIntConstrained(
3109d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        mCropRectangle.height() * oldTop, 0, mCropRectangle.height() - 1);
3119d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                int right = mCropRectangle.left + toIntConstrained(
3129d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        mCropRectangle.width() * oldRight, 0, mCropRectangle.width() - 1);
3139d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                int bottom = mCropRectangle.top + toIntConstrained(
3149d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        mCropRectangle.height() * oldBottom, 0, mCropRectangle.height() - 1);
315de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                transformed[index] = new MeteringRectangle(left, top, right - left, bottom - top,
316de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        source.weight);
317de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
318de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
319de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        return transformed;
320de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
321de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
322de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private int toIntConstrained(double original, int min, int max) {
323de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        original = Math.max(original, min);
324de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        original = Math.min(original, max);
325de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        return (int) original;
326de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
327de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
328de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private void updateRequestFlashMode() {
329de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Integer aeMode = null;
330de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Integer flashMode = null;
331de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (mCurrentFlashMode != null) {
332de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            switch (mCurrentFlashMode) {
333de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case AUTO: {
334de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    aeMode = CONTROL_AE_MODE_ON_AUTO_FLASH;
335de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
336de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
337de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case OFF: {
338de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    aeMode = CONTROL_AE_MODE_ON;
339de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    flashMode = FLASH_MODE_OFF;
340de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
341de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
342de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case ON: {
343de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    aeMode = CONTROL_AE_MODE_ON_ALWAYS_FLASH;
344de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    flashMode = FLASH_MODE_SINGLE;
345de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
346de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
347de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case TORCH: {
348de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    flashMode = FLASH_MODE_TORCH;
349de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
350de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
351de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case RED_EYE: {
352de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    aeMode = CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE;
353de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
354de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
355de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                default: {
356de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    Log.w(TAG, "Unable to convert to API 2 flash mode: " + mCurrentFlashMode);
357de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
358de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
359de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
360de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
361de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings.set(CONTROL_AE_MODE, aeMode);
362de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings.set(FLASH_MODE, flashMode);
363de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
364de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
365de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private void updateRequestFocusMode() {
366de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Integer mode = null;
367de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (mCurrentFocusMode != null) {
368de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            switch (mCurrentFocusMode) {
369de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case AUTO: {
370de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AF_MODE_AUTO;
371de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
372de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
373de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CONTINUOUS_PICTURE: {
374de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AF_MODE_CONTINUOUS_PICTURE;
375de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
376de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
377de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CONTINUOUS_VIDEO: {
378de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AF_MODE_CONTINUOUS_VIDEO;
379de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
380de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
381de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case EXTENDED_DOF: {
382de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AF_MODE_EDOF;
383de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
384de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
385de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case FIXED: {
386de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AF_MODE_OFF;
387de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
388de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
389de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                // TODO: We cannot support INFINITY
390de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case MACRO: {
391de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AF_MODE_MACRO;
392de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
393de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
394de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                default: {
395de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    Log.w(TAG, "Unable to convert to API 2 focus mode: " + mCurrentFocusMode);
396de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
397de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
398de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
399de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
400de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings.set(CONTROL_AF_MODE, mode);
401de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
402de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
403de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private void updateRequestSceneMode() {
404de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Integer mode = null;
405de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (mCurrentSceneMode != null) {
406de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            switch (mCurrentSceneMode) {
407de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case AUTO: {
408de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_DISABLED;
409de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
410de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
411de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case ACTION: {
412de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_ACTION;
413de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
414de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
415de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case BARCODE: {
416de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_BARCODE;
417de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
418de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
419de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case BEACH: {
420de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_BEACH;
421de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
422de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
423de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CANDLELIGHT: {
424de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_CANDLELIGHT;
425de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
426de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
427de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case FIREWORKS: {
428de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_FIREWORKS;
429de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
430de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
43154c8f898815a233ba6478630940432ddafdb4314Ruben Brunk                case HDR: {
432c5effbd8ffed05f6c5142c1c8d491c398194bf5bEino-Ville Talvala                    mode = CONTROL_SCENE_MODE_HDR;
43354c8f898815a233ba6478630940432ddafdb4314Ruben Brunk                    break;
43454c8f898815a233ba6478630940432ddafdb4314Ruben Brunk                }
435de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case LANDSCAPE: {
436de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_LANDSCAPE;
437de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
438de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
439de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case NIGHT: {
440de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_NIGHT;
441de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
442de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
443de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                // TODO: We cannot support NIGHT_PORTRAIT
444de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case PARTY: {
445de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_PARTY;
446de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
447de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
448de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case PORTRAIT: {
449de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_PORTRAIT;
450de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
451de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
452de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case SNOW: {
453de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_SNOW;
454de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
455de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
456de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case SPORTS: {
457de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_SPORTS;
458de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
459de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
460de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case STEADYPHOTO: {
461de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_STEADYPHOTO;
462de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
463de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
464de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case SUNSET: {
465de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_SUNSET;
466de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
467de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
468de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case THEATRE: {
469de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_SCENE_MODE_THEATRE;
470de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
471de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
472de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                default: {
473de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    Log.w(TAG, "Unable to convert to API 2 scene mode: " + mCurrentSceneMode);
474de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
475de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
476de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
477de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
478de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings.set(CONTROL_SCENE_MODE, mode);
479de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    }
480a0842b40441db5332a5290f941021636b1182761Sol Boucher
481de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private void updateRequestWhiteBalance() {
482de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        Integer mode = null;
483de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        if (mWhiteBalance != null) {
484de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            switch (mWhiteBalance) {
485de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case AUTO: {
486de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_AUTO;
487de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
488de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
489de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case CLOUDY_DAYLIGHT: {
490de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_CLOUDY_DAYLIGHT;
491de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
492de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
493de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case DAYLIGHT: {
494de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_DAYLIGHT;
495de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
496de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
497de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case FLUORESCENT: {
498de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_FLUORESCENT;
499de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
500de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
501de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case INCANDESCENT: {
502de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_INCANDESCENT;
503de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
504de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
505de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case SHADE: {
506de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_SHADE;
507de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
508de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
509de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case TWILIGHT: {
510de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_TWILIGHT;
511de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
512de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
513de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                case WARM_FLUORESCENT: {
514de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mode = CONTROL_AWB_MODE_WARM_FLUORESCENT;
515de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
516de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
517de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                default: {
518de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    Log.w(TAG, "Unable to convert to API 2 white balance: " + mWhiteBalance);
519de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    break;
520de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
521de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
522de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
523de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        mRequestSettings.set(CONTROL_AWB_MODE, mode);
524a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
525d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher
526d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher    private void updateRequestGpsData() {
527d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher        if (mGpsData == null || mGpsData.processingMethod == null) {
528d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            // It's a hack since we always use GPS time stamp but does
529d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            // not use other fields sometimes. Setting processing
530d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            // method to null means the other fields should not be used.
531d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            mRequestSettings.set(JPEG_GPS_LOCATION, null);
532d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher        } else {
533d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            Location location = new Location(mGpsData.processingMethod);
534d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            location.setTime(mGpsData.timeStamp);
535d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            location.setAltitude(mGpsData.altitude);
536d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            location.setLatitude(mGpsData.latitude);
537d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            location.setLongitude(mGpsData.longitude);
538d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher            mRequestSettings.set(JPEG_GPS_LOCATION, location);
539d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher        }
540d0185cc2f5786571565f01b26e1143ce0099bdc8Sol Boucher    }
5412569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
5422569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher    /**
5432569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * Calculate the effective crop rectangle for this preview viewport;
5442569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * assumes the preview is centered to the sensor and scaled to fit across one of the dimensions
5452569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * without skewing.
5462569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     *
5472569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * <p>Assumes the zoom level of the provided desired crop rectangle.</p>
5482569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     *
5492569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * @param requestedCrop Desired crop rectangle, in active array space.
5502569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * @param previewSize Size of the preview buffer render target, in pixels (not in sensor space).
5512569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * @return A rectangle that serves as the preview stream's effective crop region (unzoomed), in
5522569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     *          sensor space.
5532569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     *
5542569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     * @throws NullPointerException
5552569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     *          If any of the args were {@code null}.
5562569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher     */
5572569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher    private static Rect effectiveCropRectFromRequested(Rect requestedCrop, Size previewSize) {
5582569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        float aspectRatioArray = requestedCrop.width() * 1.0f / requestedCrop.height();
5592569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        float aspectRatioPreview = previewSize.width() * 1.0f / previewSize.height();
5602569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
5612569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        float cropHeight, cropWidth;
5622569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        if (aspectRatioPreview < aspectRatioArray) {
5632569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            // The new width must be smaller than the height, so scale the width by AR
5642569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            cropHeight = requestedCrop.height();
5652569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            cropWidth = cropHeight * aspectRatioPreview;
5662569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        } else {
5672569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            // The new height must be smaller (or equal) than the width, so scale the height by AR
5682569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            cropWidth = requestedCrop.width();
5692569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            cropHeight = cropWidth / aspectRatioPreview;
5702569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        }
5712569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
5722569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        Matrix translateMatrix = new Matrix();
5732569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        RectF cropRect = new RectF(/*left*/0, /*top*/0, cropWidth, cropHeight);
5742569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
5752569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // Now center the crop rectangle so its center is in the center of the active array
5762569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        translateMatrix.setTranslate(requestedCrop.exactCenterX(), requestedCrop.exactCenterY());
5772569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        translateMatrix.postTranslate(-cropRect.centerX(), -cropRect.centerY());
5782569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
5792569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        translateMatrix.mapRect(/*inout*/cropRect);
5802569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
5812569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // Round the rect corners towards the nearest integer values
5822569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        Rect result = new Rect();
5832569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        cropRect.roundOut(result);
5842569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        return result;
5852569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher    }
586a0842b40441db5332a5290f941021636b1182761Sol Boucher}
587