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.initialization;
18
19import android.content.Context;
20import android.view.Surface;
21
22import com.android.camera.async.FilteredCallback;
23import com.android.camera.async.Listenable;
24import com.android.camera.async.SafeCloseable;
25import com.android.camera.async.Updatable;
26import com.android.camera.one.OneCamera;
27import com.android.camera.one.PreviewSizeSelector;
28import com.android.camera.one.v2.AutoFocusHelper;
29import com.android.camera.one.v2.autofocus.ManualAutoFocus;
30import com.android.camera.one.v2.photo.PictureTaker;
31import com.android.camera.session.CaptureSession;
32import com.android.camera.ui.motion.LinearScale;
33import com.android.camera.util.Callback;
34import com.android.camera.util.Size;
35import com.google.common.util.concurrent.FutureCallback;
36import com.google.common.util.concurrent.Futures;
37import com.google.common.util.concurrent.ListenableFuture;
38
39import java.util.concurrent.Executor;
40
41import javax.annotation.Nonnull;
42
43/**
44 * A generic, composable {@link OneCamera}.
45 * <p>
46 * Note: This implementation assumes that these four methods are invoked in
47 * sequences matching the following regex:
48 * <p>
49 * startPreview (takePicture | triggerFocusAndMeterAtPoint)* close
50 * <p>
51 * All other methods may be called at any time.
52 */
53class GenericOneCameraImpl implements OneCamera {
54
55    private final SafeCloseable mCloseListener;
56    private final PictureTaker mPictureTaker;
57    private final ManualAutoFocus mManualAutoFocus;
58    private final LinearScale mLensRange;
59    private final Executor mMainExecutor;
60    private final Listenable<Integer> mAFStateListenable;
61    private final Listenable<FocusState> mFocusStateListenable;
62    private final Listenable<Boolean> mReadyStateListenable;
63    private final float mMaxZoom;
64    private final Updatable<Float> mZoom;
65    private final Facing mDirection;
66    private final PreviewSizeSelector mPreviewSizeSelector;
67    private final PreviewStarter mPreviewStarter;
68
69    public GenericOneCameraImpl(SafeCloseable closeListener, PictureTaker pictureTaker,
70            ManualAutoFocus manualAutoFocus, LinearScale lensRange, Executor mainExecutor,
71            Listenable<Integer> afStateProvider, Listenable<FocusState> focusStateProvider,
72            Listenable<Boolean> readyStateListenable, float maxZoom, Updatable<Float> zoom,
73            Facing direction, PreviewSizeSelector previewSizeSelector,
74            PreviewStarter previewStarter) {
75        mCloseListener = closeListener;
76        mMainExecutor = mainExecutor;
77        mMaxZoom = maxZoom;
78        mDirection = direction;
79        mPreviewSizeSelector = previewSizeSelector;
80        mPictureTaker = pictureTaker;
81        mManualAutoFocus = manualAutoFocus;
82        mLensRange = lensRange;
83        mAFStateListenable = afStateProvider;
84        mFocusStateListenable = focusStateProvider;
85        mReadyStateListenable = readyStateListenable;
86        mZoom = zoom;
87        mPreviewStarter = previewStarter;
88    }
89
90    @Override
91    public void triggerFocusAndMeterAtPoint(float nx, float ny) {
92        mManualAutoFocus.triggerFocusAndMeterAtPoint(nx, ny);
93    }
94
95    @Override
96    public void takePicture(PhotoCaptureParameters params, CaptureSession session) {
97        mPictureTaker.takePicture(params, session);
98    }
99
100    @Override
101    public void setFocusStateListener(final FocusStateListener listener) {
102        mAFStateListenable.setCallback(new Callback<Integer>() {
103            @Override
104            public void onCallback(@Nonnull Integer afState) {
105                // TODO delete frameNumber from FocusStateListener callback. It
106                // is optional and never actually used.
107                long frameNumber = -1;
108                if(listener !=null) {
109                    listener.onFocusStatusUpdate(AutoFocusHelper.stateFromCamera2State(afState),
110                            frameNumber);
111                }
112            }
113        });
114    }
115
116    @Override
117    public void setFocusDistanceListener(final FocusDistanceListener listener) {
118        if (listener == null) {
119            mFocusStateListenable.clear();
120            return;
121        }
122        mFocusStateListenable.setCallback(new Callback<FocusState>() {
123            @Override
124            public void onCallback(@Nonnull FocusState focusState) {
125                if (focusState.isActive) {
126                    listener.onFocusDistance(focusState.lensDistance, mLensRange);
127                }
128            }
129        });
130    }
131
132    @Override
133    public void setReadyStateChangedListener(final ReadyStateChangedListener listener) {
134        if (listener == null) {
135            mReadyStateListenable.clear();
136            return;
137        }
138
139        Callback<Boolean> readyStateCallback = new Callback<Boolean>() {
140            @Override
141            public void onCallback(@Nonnull Boolean result) {
142                listener.onReadyStateChanged(result);
143            }
144        };
145
146        mReadyStateListenable.setCallback(new FilteredCallback<>(readyStateCallback));
147    }
148
149    @Override
150    public void startPreview(Surface surface, final CaptureReadyCallback listener) {
151        ListenableFuture<Void> result = mPreviewStarter.startPreview(surface);
152        Futures.addCallback(result, new FutureCallback<Void>() {
153            @Override
154            public void onSuccess(@Nonnull Void aVoid) {
155                listener.onReadyForCapture();
156            }
157
158            @Override
159            public void onFailure(@Nonnull Throwable throwable) {
160                listener.onSetupFailed();
161            }
162        });
163    }
164
165    @Override
166    public void close() {
167        mCloseListener.close();
168    }
169
170    @Override
171    public Facing getDirection() {
172        return mDirection;
173    }
174
175    @Override
176    public float getMaxZoom() {
177        return mMaxZoom;
178    }
179
180    @Override
181    public void setZoom(float zoom) {
182        mZoom.update(zoom);
183    }
184
185    @Override
186    public Size pickPreviewSize(Size pictureSize, Context context) {
187        return mPreviewSizeSelector.pickPreviewSize(pictureSize);
188    }
189}
190