• 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;
18 
19 import android.content.Intent;
20 import android.graphics.Point;
21 import android.graphics.SurfaceTexture;
22 import android.view.GestureDetector;
23 import android.view.KeyEvent;
24 import android.view.MotionEvent;
25 import android.view.View;
26 
27 import com.android.camera.CameraActivity;
28 import com.android.camera.CameraModule;
29 import com.android.camera.app.AppController;
30 import com.android.camera.app.CameraAppUI;
31 import com.android.camera.async.MainThread;
32 import com.android.camera.async.RefCountBase;
33 import com.android.camera.burst.BurstFacadeFactory;
34 import com.android.camera.captureintent.event.EventClickOnCameraKey;
35 import com.android.camera.captureintent.event.EventOnSurfaceTextureAvailable;
36 import com.android.camera.captureintent.event.EventOnSurfaceTextureDestroyed;
37 import com.android.camera.captureintent.event.EventOnSurfaceTextureUpdated;
38 import com.android.camera.captureintent.event.EventOnTextureViewLayoutChanged;
39 import com.android.camera.captureintent.event.EventPause;
40 import com.android.camera.captureintent.event.EventResume;
41 import com.android.camera.captureintent.event.EventTapOnCancelShutterButton;
42 import com.android.camera.captureintent.event.EventTapOnPreview;
43 import com.android.camera.captureintent.event.EventTapOnShutterButton;
44 import com.android.camera.captureintent.event.EventZoomRatioChanged;
45 import com.android.camera.captureintent.resource.ResourceConstructed;
46 import com.android.camera.captureintent.resource.ResourceConstructedImpl;
47 import com.android.camera.captureintent.state.StateBackground;
48 import com.android.camera.captureintent.stateful.State;
49 import com.android.camera.captureintent.stateful.StateMachine;
50 import com.android.camera.captureintent.stateful.StateMachineImpl;
51 import com.android.camera.debug.Log;
52 import com.android.camera.hardware.HardwareSpec;
53 import com.android.camera.one.OneCameraException;
54 import com.android.camera.one.OneCameraModule;
55 import com.android.camera.settings.SettingsManager;
56 import com.android.camera.ui.PreviewStatusListener;
57 import com.android.camera.ui.TouchCoordinate;
58 import com.android.camera.util.Size;
59 import com.android.camera2.R;
60 import com.android.ex.camera2.portability.CameraAgent;
61 
62 /**
63  * The camera module that handles image capture intent.
64  */
65 public class CaptureIntentModule extends CameraModule {
66     private static final Log.Tag TAG = new Log.Tag("CapIntModule");
67 
68     /** The module UI. */
69     private final CaptureIntentModuleUI mModuleUI;
70 
71     /** The available resources after construction. */
72     private final RefCountBase<ResourceConstructed> mResourceConstructed;
73 
74     /** The module state machine. */
75     private final StateMachine mStateMachine;
76 
77     private TouchCoordinate mTouchPointInsideShutterButton;
78 
CaptureIntentModule(AppController appController, Intent intent, String settingScopeNamespace)79     public CaptureIntentModule(AppController appController, Intent intent,
80             String settingScopeNamespace) throws OneCameraException {
81         super(appController);
82         mModuleUI = new CaptureIntentModuleUI(
83                 appController.getCameraAppUI(),
84                 appController.getModuleLayoutRoot(),
85                 mUIListener);
86         mStateMachine = new StateMachineImpl();
87         mResourceConstructed = ResourceConstructedImpl.create(
88                 intent,
89                 mModuleUI,
90                 settingScopeNamespace,
91                 MainThread.create(),
92                 appController.getAndroidContext(),
93                 appController.getCameraOpener(),
94                 OneCameraModule.provideOneCameraManager(),
95                 appController.getLocationManager(),
96                 appController.getOrientationManager(),
97                 appController.getSettingsManager(),
98                 new BurstFacadeFactory.BurstFacadeStub(),
99                 appController,
100                 appController.getFatalErrorHandler());
101         final State initialState = StateBackground.create(mStateMachine, mResourceConstructed);
102         // Set the initial state.
103         mStateMachine.setInitialState(initialState);
104     }
105 
106     @Override
onCameraAvailable(CameraAgent.CameraProxy cameraProxy)107     public void onCameraAvailable(CameraAgent.CameraProxy cameraProxy) {
108         // Do nothing for capture intent.
109     }
110 
111     @Override
onShutterButtonFocus(boolean pressed)112     public void onShutterButtonFocus(boolean pressed) {
113         // Do nothing for capture intent.
114     }
115 
116     @Override
onShutterCoordinate(TouchCoordinate touchCoordinate)117     public void onShutterCoordinate(TouchCoordinate touchCoordinate) {
118         mTouchPointInsideShutterButton = touchCoordinate;
119     }
120 
121     @Override
onShutterButtonClick()122     public void onShutterButtonClick() {
123         mStateMachine.processEvent(new EventTapOnShutterButton(mTouchPointInsideShutterButton));
124     }
125 
126     @Override
onShutterButtonLongPressed()127     public void onShutterButtonLongPressed() {
128         // Do nothing for capture intent.
129     }
130 
131     @Override
init( final CameraActivity activity, boolean isSecureCamera, boolean isCaptureIntent)132     public void init(
133             final CameraActivity activity, boolean isSecureCamera, boolean isCaptureIntent) {
134         mResourceConstructed.get().getAppController()
135                 .setPreviewStatusListener(mPreviewStatusListener);
136 
137         // Issue cancel countdown event when the button is pressed.
138         // TODO: Make this part of the official API the way shutter button events are.
139         mResourceConstructed.get().getAppController().getCameraAppUI()
140                 .setCancelShutterButtonListener(new View.OnClickListener() {
141                     @Override
142                     public void onClick(View v) {
143                         mStateMachine.processEvent(new EventTapOnCancelShutterButton());
144                     }
145                 });
146 
147     }
148 
149     @Override
resume()150     public void resume() {
151         mModuleUI.onModuleResumed();
152         mStateMachine.processEvent(new EventResume());
153     }
154 
155     @Override
pause()156     public void pause() {
157         mModuleUI.setCountdownFinishedListener(null);
158         mModuleUI.onModulePaused();
159         mStateMachine.processEvent(new EventPause());
160     }
161 
162     @Override
destroy()163     public void destroy() {
164         // Never called. Do nothing here.
165     }
166 
167     @Override
onPreviewVisibilityChanged(int visibility)168     public void onPreviewVisibilityChanged(int visibility) {
169         // Do nothing.
170     }
171 
172     @Override
onLayoutOrientationChanged(boolean isLandscape)173     public void onLayoutOrientationChanged(boolean isLandscape) {
174         // Do nothing.
175     }
176 
177     @Override
hardResetSettings(SettingsManager settingsManager)178     public void hardResetSettings(SettingsManager settingsManager) {
179         // Do nothing.
180     }
181 
182     @Override
getHardwareSpec()183     public HardwareSpec getHardwareSpec() {
184         /**
185          * Instead of passively providing CameraAppUI the hardware spec here,
186          * {@link com.android.camera.captureintent.state.StateOpeningCamera}
187          * will actively specify hardware spec.
188          */
189         return null;
190     }
191 
192     @Override
getBottomBarSpec()193     public CameraAppUI.BottomBarUISpec getBottomBarSpec() {
194         /**
195          * Instead of passively providing CameraAppUI the bottom bar spec here,
196          * {@link com.android.camera.captureintent.state.StateOpeningCamera}
197          * will actively specify bottom bar spec.
198          */
199         return null;
200     }
201 
202     @Override
isUsingBottomBar()203     public boolean isUsingBottomBar() {
204         return true;
205     }
206 
207     @Override
getPeekAccessibilityString()208     public String getPeekAccessibilityString() {
209         return mResourceConstructed.get().getContext().getResources()
210                 .getString(R.string.photo_accessibility_peek);
211     }
212 
213     @Override
onKeyDown(int keyCode, KeyEvent event)214     public boolean onKeyDown(int keyCode, KeyEvent event) {
215         switch (keyCode) {
216             case KeyEvent.KEYCODE_CAMERA:
217             case KeyEvent.KEYCODE_DPAD_CENTER:
218                 mStateMachine.processEvent(new EventClickOnCameraKey());
219                 return true;
220             case KeyEvent.KEYCODE_VOLUME_UP:
221             case KeyEvent.KEYCODE_VOLUME_DOWN:
222                 // Prevent default.
223                 return true;
224         }
225         return false;
226     }
227 
228     @Override
onKeyUp(int keyCode, KeyEvent event)229     public boolean onKeyUp(int keyCode, KeyEvent event) {
230         switch (keyCode) {
231             case KeyEvent.KEYCODE_VOLUME_UP:
232             case KeyEvent.KEYCODE_VOLUME_DOWN:
233                 mStateMachine.processEvent(new EventClickOnCameraKey());
234                 return true;
235         }
236         return false;
237     }
238 
239     /** The listener to listen events from the UI. */
240     private final CaptureIntentModuleUI.Listener mUIListener =
241             new CaptureIntentModuleUI.Listener() {
242                 @Override
243                 public void onZoomRatioChanged(final float zoomRatio) {
244                     mStateMachine.processEvent(new EventZoomRatioChanged(zoomRatio));
245                 }
246             };
247 
248     /** The listener to listen events from the preview. */
249     private final PreviewStatusListener mPreviewStatusListener = new PreviewStatusListener() {
250         @Override
251         public void onPreviewLayoutChanged(View v, int left, int top, int right,
252                 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
253             final Size previewLayoutSize = new Size(right - left, bottom - top);
254             mStateMachine.processEvent(new EventOnTextureViewLayoutChanged(previewLayoutSize));
255         }
256 
257         @Override
258         public boolean shouldAutoAdjustTransformMatrixOnLayout() {
259             return CaptureIntentConfig.WORKAROUND_PREVIEW_STRETCH_BUG_NEXUS4;
260         }
261 
262         @Override
263         public void onPreviewFlipped() {
264             // Do nothing because when preview is flipped, TextureView will lay
265             // itself out again, which will then trigger a transform matrix
266             // update.
267         }
268 
269         @Override
270         public GestureDetector.OnGestureListener getGestureListener() {
271             return new GestureDetector.SimpleOnGestureListener() {
272                 @Override
273                 public boolean onSingleTapUp(MotionEvent ev) {
274                     final Point tapPoint = new Point((int) ev.getX(), (int) ev.getY());
275                     mStateMachine.processEvent(new EventTapOnPreview(tapPoint));
276                     return true;
277                 }
278             };
279         }
280 
281         @Override
282         public View.OnTouchListener getTouchListener() {
283             return null;
284         }
285 
286         @Override
287         public void onSurfaceTextureAvailable(
288                 final SurfaceTexture surfaceTexture, int width, int height) {
289             mStateMachine.processEvent(new EventOnSurfaceTextureAvailable(surfaceTexture));
290         }
291 
292         @Override
293         public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
294             mStateMachine.processEvent(new EventOnSurfaceTextureDestroyed());
295             return true;
296         }
297 
298         @Override
299         public void onSurfaceTextureSizeChanged(
300                 SurfaceTexture surfaceTexture, int width, int height) {
301         }
302 
303         @Override
304         public void onSurfaceTextureUpdated(SurfaceTexture surface) {
305             mStateMachine.processEvent(new EventOnSurfaceTextureUpdated());
306         }
307     };
308 }
309