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