• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.captureintent.state;
18 
19 import android.view.View;
20 
21 import com.android.camera.ButtonManager;
22 import com.android.camera.app.CameraAppUI;
23 import com.android.camera.async.RefCountBase;
24 import com.android.camera.captureintent.event.EventOnOpenCameraFailed;
25 import com.android.camera.captureintent.event.EventOnOpenCameraSucceeded;
26 import com.android.camera.captureintent.event.EventPause;
27 import com.android.camera.captureintent.event.EventTapOnCancelIntentButton;
28 import com.android.camera.captureintent.event.EventTapOnConfirmPhotoButton;
29 import com.android.camera.captureintent.event.EventTapOnRetakePhotoButton;
30 import com.android.camera.captureintent.event.EventTapOnSwitchCameraButton;
31 import com.android.camera.captureintent.resource.ResourceConstructed;
32 import com.android.camera.captureintent.resource.ResourceSurfaceTexture;
33 import com.android.camera.captureintent.stateful.EventHandler;
34 import com.android.camera.captureintent.stateful.State;
35 import com.android.camera.captureintent.stateful.StateImpl;
36 import com.android.camera.debug.Log;
37 import com.android.camera.device.CameraId;
38 import com.android.camera.hardware.HardwareSpec;
39 import com.android.camera.one.OneCamera;
40 import com.android.camera.one.OneCameraAccessException;
41 import com.android.camera.one.OneCameraCaptureSetting;
42 import com.android.camera.one.OneCameraCharacteristics;
43 import com.android.camera.one.v2.photo.ImageRotationCalculator;
44 import com.android.camera.one.v2.photo.ImageRotationCalculatorImpl;
45 import com.android.camera.settings.Keys;
46 import com.android.camera.settings.SettingsManager;
47 import com.android.camera.util.Size;
48 import com.google.common.annotations.VisibleForTesting;
49 import com.google.common.base.Optional;
50 
51 import javax.annotation.Nonnull;
52 
53 /**
54  * Represents a state that the module is waiting for a camera to be opened.
55  */
56 public final class StateOpeningCamera extends StateImpl {
57     private static final Log.Tag TAG = new Log.Tag("StateOpeningCamera");
58 
59     private final RefCountBase<ResourceConstructed> mResourceConstructed;
60     private final RefCountBase<ResourceSurfaceTexture> mResourceSurfaceTexture;
61     private final OneCamera.Facing mCameraFacing;
62     private final CameraId mCameraId;
63     private final OneCameraCharacteristics mCameraCharacteristics;
64     private final String mCameraSettingsScope;
65 
66     /** The desired picture size. */
67     private Size mPictureSize;
68 
69     /** Whether is paused in the middle of opening camera. */
70     private boolean mIsPaused;
71 
72     private OneCameraCaptureSetting mOneCameraCaptureSetting;
73 
74     private OneCamera.OpenCallback mCameraOpenCallback = new OneCamera.OpenCallback() {
75         @Override
76         public void onFailure() {
77             getStateMachine().processEvent(new EventOnOpenCameraFailed());
78         }
79 
80         @Override
81         public void onCameraInUse() {
82             getStateMachine().processEvent(new EventOnOpenCameraFailed());
83         }
84 
85         @Override
86         public void onCameraClosed() {
87             // Not used anymore.
88         }
89 
90         @Override
91         public void onCameraInterrupted() {
92             // Not used.
93         }
94 
95         @Override
96         public void onCameraOpened(@Nonnull final OneCamera camera) {
97             getStateMachine().processEvent(new EventOnOpenCameraSucceeded(camera));
98         }
99     };
100 
from( State previousState, RefCountBase<ResourceConstructed> resourceConstructed, RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture, OneCamera.Facing cameraFacing, CameraId cameraId, OneCameraCharacteristics cameraCharacteristics)101     public static StateOpeningCamera from(
102             State previousState,
103             RefCountBase<ResourceConstructed> resourceConstructed,
104             RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture,
105             OneCamera.Facing cameraFacing,
106             CameraId cameraId,
107             OneCameraCharacteristics cameraCharacteristics) {
108         return new StateOpeningCamera(previousState, resourceConstructed,
109                 resourceSurfaceTexture, cameraFacing, cameraId, cameraCharacteristics);
110     }
111 
StateOpeningCamera(State previousState, RefCountBase<ResourceConstructed> resourceConstructed, RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture, OneCamera.Facing cameraFacing, CameraId cameraId, OneCameraCharacteristics cameraCharacteristics)112     private StateOpeningCamera(State previousState,
113             RefCountBase<ResourceConstructed> resourceConstructed,
114             RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture,
115             OneCamera.Facing cameraFacing,
116             CameraId cameraId,
117             OneCameraCharacteristics cameraCharacteristics) {
118         super(previousState);
119         mResourceConstructed = resourceConstructed;
120         mResourceConstructed.addRef();     // Will be balanced in onLeave().
121         mResourceSurfaceTexture = resourceSurfaceTexture;
122         mResourceSurfaceTexture.addRef();  // Will be balanced in onLeave().
123         mCameraFacing = cameraFacing;
124         mCameraId = cameraId;
125         mCameraCharacteristics = cameraCharacteristics;
126         mIsPaused = false;
127         mCameraSettingsScope = SettingsManager.getCameraSettingScope(mCameraId.getValue());
128         registerEventHandlers();
129     }
130 
registerEventHandlers()131     private void registerEventHandlers() {
132         /** Handles EventPause. */
133         EventHandler<EventPause> pauseHandler = new EventHandler<EventPause>() {
134             @Override
135             public Optional<State> processEvent(EventPause event) {
136                 mIsPaused = true;
137                 return NO_CHANGE;
138             }
139         };
140         setEventHandler(EventPause.class, pauseHandler);
141 
142         /** Handles EventOnOpenCameraSucceeded. */
143         EventHandler<EventOnOpenCameraSucceeded> onOpenCameraSucceededHandler =
144                 new EventHandler<EventOnOpenCameraSucceeded>() {
145                     @Override
146                     public Optional<State> processEvent(EventOnOpenCameraSucceeded event) {
147                         final OneCamera camera = event.getCamera();
148                         if (mIsPaused) {
149                             // Just close the camera and finish.
150                             camera.close();
151                             return Optional.of((State) StateBackgroundWithSurfaceTexture.from(
152                                     StateOpeningCamera.this,
153                                     mResourceConstructed,
154                                     mResourceSurfaceTexture));
155                         }
156 
157                         mResourceConstructed.get().getMainThread().execute(new Runnable() {
158                             @Override
159                             public void run() {
160                                 mResourceConstructed.get().getModuleUI().applyModuleSpecs(
161                                         getHardwareSpec(), getBottomBarSpec());
162                             }
163                         });
164 
165                         return Optional.of((State) StateStartingPreview.from(
166                                 StateOpeningCamera.this,
167                                 mResourceConstructed,
168                                 mResourceSurfaceTexture,
169                                 camera,
170                                 mCameraId,
171                                 mCameraFacing,
172                                 mCameraCharacteristics,
173                                 mPictureSize,
174                                 mOneCameraCaptureSetting));
175                     }
176                 };
177         setEventHandler(EventOnOpenCameraSucceeded.class, onOpenCameraSucceededHandler);
178 
179         /** Handles EventOnOpenCameraFailed. */
180         EventHandler<EventOnOpenCameraFailed> onOpenCameraFailedHandler =
181                 new EventHandler<EventOnOpenCameraFailed>() {
182                     @Override
183                     public Optional<State> processEvent(EventOnOpenCameraFailed event) {
184                         Log.e(TAG, "processOnCameraOpenFailure");
185                         return Optional.of((State) StateFatal.from(
186                                 StateOpeningCamera.this, mResourceConstructed));
187                     }
188                 };
189         setEventHandler(EventOnOpenCameraFailed.class, onOpenCameraFailedHandler);
190     }
191 
192     @Override
onEnter()193     public Optional<State> onEnter() {
194         if (mCameraCharacteristics == null) {
195             Log.e(TAG, "mCameraCharacteristics is null");
196             return Optional.of((State) StateFatal.from(this, mResourceConstructed));
197         }
198         try {
199             mPictureSize = mResourceConstructed.get().getResolutionSetting().getPictureSize(
200                     mCameraId, mCameraFacing);
201             mOneCameraCaptureSetting = OneCameraCaptureSetting.create(
202                     mPictureSize,
203                     mResourceConstructed.get().getAppController().getSettingsManager(),
204                     getHardwareSpec(),
205                     mCameraSettingsScope,
206                     false);
207         } catch (OneCameraAccessException ex) {
208             Log.e(TAG, "Failed while open camera", ex);
209             return Optional.of((State) StateFatal.from(this, mResourceConstructed));
210         }
211 
212         final ImageRotationCalculator imageRotationCalculator = ImageRotationCalculatorImpl.from(
213                 mResourceConstructed.get().getOrientationManager(), mCameraCharacteristics);
214 
215         mResourceConstructed.get().getOneCameraOpener().open(
216                 mCameraId,
217                 mOneCameraCaptureSetting,
218                 mResourceConstructed.get().getCameraHandler(),
219                 mResourceConstructed.get().getMainThread(),
220                 imageRotationCalculator,
221                 mResourceConstructed.get().getBurstFacade(),
222                 mResourceConstructed.get().getSoundPlayer(),
223                 mCameraOpenCallback,
224                 mResourceConstructed.get().getFatalErrorHandler());
225         return Optional.absent();
226     }
227 
228     @Override
onLeave()229     public void onLeave() {
230         mResourceConstructed.close();
231         mResourceSurfaceTexture.close();
232     }
233 
234     @VisibleForTesting
isPaused()235     public boolean isPaused() {
236         return mIsPaused;
237     }
238 
getHardwareSpec()239     private HardwareSpec getHardwareSpec() {
240         return new HardwareSpec() {
241             @Override
242             public boolean isFrontCameraSupported() {
243                 return mResourceConstructed.get()
244                       .getOneCameraManager().hasCameraFacing(OneCamera.Facing.FRONT);
245             }
246 
247             @Override
248             public boolean isHdrSupported() {
249                 return false;
250             }
251 
252             @Override
253             public boolean isHdrPlusSupported() {
254                 return false;
255             }
256 
257             @Override
258             public boolean isFlashSupported() {
259                 return mCameraCharacteristics.isFlashSupported();
260             }
261         };
262     }
263 
264     private CameraAppUI.BottomBarUISpec getBottomBarSpec() {
265         CameraAppUI.BottomBarUISpec bottomBarSpec = new CameraAppUI.BottomBarUISpec();
266         /** Camera switch button UI spec. */
267         bottomBarSpec.enableCamera = true;
268         bottomBarSpec.cameraCallback = new ButtonManager.ButtonCallback() {
269             @Override
270             public void onStateChanged(int cameraId) {
271                 getStateMachine().processEvent(new EventTapOnSwitchCameraButton());
272             }
273         };
274         /** Grid lines button UI spec. */
275         bottomBarSpec.enableGridLines = true;
276         /** HDR button UI spec. */
277         bottomBarSpec.enableHdr = false;
278         bottomBarSpec.hideHdr = true;
279         bottomBarSpec.hdrCallback = null;
280         /** Timer button UI spec. */
281         bottomBarSpec.enableSelfTimer = true;
282         bottomBarSpec.showSelfTimer = true;
283         /** Flash button UI spec. */
284         bottomBarSpec.enableFlash = mCameraCharacteristics.isFlashSupported();
285 
286         /** Setup exposure compensation */
287         bottomBarSpec.isExposureCompensationSupported = mCameraCharacteristics
288                 .isExposureCompensationSupported();
289         bottomBarSpec.enableExposureCompensation = bottomBarSpec.isExposureCompensationSupported;
290         bottomBarSpec.minExposureCompensation =
291                 mCameraCharacteristics.getMinExposureCompensation();
292         bottomBarSpec.maxExposureCompensation =
293                 mCameraCharacteristics.getMaxExposureCompensation();
294         bottomBarSpec.exposureCompensationStep =
295                 mCameraCharacteristics.getExposureCompensationStep();
296         bottomBarSpec.exposureCompensationSetCallback =
297                 new CameraAppUI.BottomBarUISpec.ExposureCompensationSetCallback() {
298                     @Override
299                     public void setExposure(int value) {
300                         mResourceConstructed.get().getSettingsManager().set(
301                                 mCameraSettingsScope, Keys.KEY_EXPOSURE, value);
302                     }
303                 };
304 
305         /** Intent image review UI spec. */
306         bottomBarSpec.showCancel = true;
307         bottomBarSpec.cancelCallback = new View.OnClickListener() {
308             @Override
309             public void onClick(View v) {
310                 getStateMachine().processEvent(new EventTapOnCancelIntentButton());
311             }
312         };
313         bottomBarSpec.showDone = true;
314         bottomBarSpec.doneCallback = new View.OnClickListener() {
315             @Override
316             public void onClick(View v) {
317                 getStateMachine().processEvent(new EventTapOnConfirmPhotoButton());
318             }
319         };
320         bottomBarSpec.showRetake = true;
321         bottomBarSpec.retakeCallback = new View.OnClickListener() {
322             @Override
323             public void onClick(View v) {
324                 getStateMachine().processEvent(new EventTapOnRetakePhotoButton());
325             }
326         };
327         return bottomBarSpec;
328     }
329 }
330