1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.one.v2.common;
18
19import android.annotation.TargetApi;
20import android.graphics.Rect;
21import android.hardware.camera2.CaptureRequest;
22import android.hardware.camera2.params.MeteringRectangle;
23import android.os.Build.VERSION_CODES;
24
25import com.android.camera.async.Lifetime;
26import com.android.camera.async.Observable;
27import com.android.camera.async.SafeCloseable;
28import com.android.camera.one.OneCamera;
29import com.android.camera.one.OneCameraCharacteristics;
30import com.android.camera.one.OneCameraCharacteristics.FaceDetectMode;
31import com.android.camera.one.Settings3A;
32import com.android.camera.one.v2.autofocus.ManualAutoFocus;
33import com.android.camera.one.v2.autofocus.ManualAutoFocusFactory;
34import com.android.camera.one.v2.commands.CameraCommand;
35import com.android.camera.one.v2.commands.CameraCommandExecutor;
36import com.android.camera.one.v2.commands.ResettingRunnableCameraCommand;
37import com.android.camera.one.v2.commands.PreviewCommandFactory;
38import com.android.camera.one.v2.core.FrameServer;
39import com.android.camera.one.v2.core.RequestBuilder;
40import com.android.camera.one.v2.core.RequestTemplate;
41import com.android.camera.one.v2.face.FaceDetect;
42import com.google.common.base.Supplier;
43import com.google.common.base.Suppliers;
44import com.google.common.util.concurrent.MoreExecutors;
45
46import java.util.concurrent.Executors;
47
48/**
49 * Wires together functionality common to all cameras:
50 * <ul>
51 * <li>Tap-to-focus</li>
52 * <li>Auto exposure, based on the current flash-setting</li>
53 * <li>Metering regions</li>
54 * <li>Zoom</li>
55 * <li>TODO Logging of OS/driver-level errors</li>
56 * </ul>
57 * <p>
58 * Note that this does not include functionality for taking pictures, since this
59 * varies depending on hardware capability.
60 * </p>
61 */
62@TargetApi(VERSION_CODES.LOLLIPOP)
63public class BasicCameraFactory {
64    private final ManualAutoFocus mManualAutoFocus;
65    private final RequestBuilder.Factory mMeteredZoomedRequestBuilder;
66    private final Runnable mPreviewUpdater;
67
68    /**
69     * @param lifetime The lifetime of all created objects and their associated
70     *            resources.
71     * @param cameraCharacteristics
72     * @param rootTemplate Provides preconfigured request builders to be used for
73     *            all requests to mFrameServer.
74     * @param cameraCommandExecutor The
75     * @param templateType The template (e.g. CameraDevice.TEMPLATE_PREVIEW) to
76     *            use for repeating requests.
77     */
78    public BasicCameraFactory(Lifetime lifetime,
79            OneCameraCharacteristics cameraCharacteristics,
80            FrameServer frameServer,
81            RequestBuilder.Factory rootTemplate,
82            CameraCommandExecutor cameraCommandExecutor,
83            PreviewCommandFactory previewCommandFactory,
84            Observable<OneCamera.PhotoCaptureParameters.Flash> flash,
85            Observable<Integer> exposure,
86            Observable<Float> zoom,
87            Observable<Boolean> hdrSceneSetting,
88            int templateType) {
89        RequestTemplate requestTemplate = new RequestTemplate(rootTemplate);
90        requestTemplate.setParam(
91              CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
92        requestTemplate.setParam(
93              CaptureRequest.CONTROL_AE_MODE, new FlashBasedAEMode(flash, hdrSceneSetting));
94        requestTemplate.setParam(
95              CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, exposure);
96
97        Supplier<FaceDetectMode> faceDetectMode = Suppliers.ofInstance(
98              FaceDetect.getHighestFaceDetectMode(cameraCharacteristics));
99
100        requestTemplate.setParam(CaptureRequest.CONTROL_MODE,
101              new ControlModeSelector(hdrSceneSetting,
102                    faceDetectMode,
103                    cameraCharacteristics.getSupportedHardwareLevel()));
104        requestTemplate.setParam(
105              CaptureRequest.CONTROL_SCENE_MODE, new ControlSceneModeSelector(
106                    hdrSceneSetting,
107                    faceDetectMode,
108                    cameraCharacteristics.getSupportedHardwareLevel()));
109        requestTemplate.setParam(CaptureRequest.STATISTICS_FACE_DETECT_MODE,
110              new StatisticsFaceDetectMode(faceDetectMode));
111
112        Supplier<Rect> cropRegion = new ZoomedCropRegion(
113                cameraCharacteristics.getSensorInfoActiveArraySize(), zoom);
114        requestTemplate.setParam(CaptureRequest.SCALER_CROP_REGION, cropRegion);
115
116        CameraCommand previewUpdaterCommand =
117              previewCommandFactory.get(requestTemplate, templateType);
118
119        // Use a resetting command to ensure that many rapid settings changes do
120        // not result in many rapid (>30fps) requests to restart the preview.
121        mPreviewUpdater = new ResettingRunnableCameraCommand(cameraCommandExecutor,
122              previewUpdaterCommand);
123
124        // Resend the repeating preview request when the zoom or flash state
125        // changes to apply the new setting.
126        // Also, de-register these callbacks when the camera is closed (to
127        // not leak memory).
128        SafeCloseable zoomCallback = zoom.addCallback(mPreviewUpdater, MoreExecutors
129                .sameThreadExecutor());
130        lifetime.add(zoomCallback);
131        SafeCloseable flashCallback = flash.addCallback(mPreviewUpdater, MoreExecutors
132                .sameThreadExecutor());
133        lifetime.add(flashCallback);
134        SafeCloseable exposureCallback = exposure.addCallback(mPreviewUpdater, MoreExecutors
135                .sameThreadExecutor());
136        lifetime.add(exposureCallback);
137        SafeCloseable hdrCallback = hdrSceneSetting.addCallback(mPreviewUpdater, MoreExecutors
138                .sameThreadExecutor());
139        lifetime.add(hdrCallback);
140
141        int sensorOrientation = cameraCharacteristics.getSensorOrientation();
142
143        ManualAutoFocusFactory manualAutoFocusFactory = ManualAutoFocusFactory.create(new
144                Lifetime(lifetime), frameServer, cameraCommandExecutor, cropRegion,
145                sensorOrientation, mPreviewUpdater, requestTemplate,
146                templateType, new Settings3A(), Executors.newScheduledThreadPool(1),
147                3 /* afHoldSeconds */);
148        mManualAutoFocus = manualAutoFocusFactory.provideManualAutoFocus();
149        Supplier<MeteringRectangle[]> aeRegions =
150                manualAutoFocusFactory.provideAEMeteringRegion();
151        Supplier<MeteringRectangle[]> afRegions =
152                manualAutoFocusFactory.provideAFMeteringRegion();
153
154        requestTemplate.setParam(CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
155        requestTemplate.setParam(CaptureRequest.CONTROL_AF_REGIONS, afRegions);
156
157        mMeteredZoomedRequestBuilder = requestTemplate;
158    }
159
160    public RequestBuilder.Factory provideMeteredZoomedRequestBuilder() {
161        return mMeteredZoomedRequestBuilder;
162    }
163
164    public ManualAutoFocus provideManualAutoFocus() {
165        return mManualAutoFocus;
166    }
167
168    public Runnable providePreviewUpdater() {
169        return mPreviewUpdater;
170    }
171}
172