Home | History | Annotate | Download | only in captureintent
      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 
     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
    107     public void onCameraAvailable(CameraAgent.CameraProxy cameraProxy) {
    108         // Do nothing for capture intent.
    109     }
    110 
    111     @Override
    112     public void onShutterButtonFocus(boolean pressed) {
    113         // Do nothing for capture intent.
    114     }
    115 
    116     @Override
    117     public void onShutterCoordinate(TouchCoordinate touchCoordinate) {
    118         mTouchPointInsideShutterButton = touchCoordinate;
    119     }
    120 
    121     @Override
    122     public void onShutterButtonClick() {
    123         mStateMachine.processEvent(new EventTapOnShutterButton(mTouchPointInsideShutterButton));
    124     }
    125 
    126     @Override
    127     public void onShutterButtonLongPressed() {
    128         // Do nothing for capture intent.
    129     }
    130 
    131     @Override
    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
    150     public void resume() {
    151         mModuleUI.onModuleResumed();
    152         mStateMachine.processEvent(new EventResume());
    153     }
    154 
    155     @Override
    156     public void pause() {
    157         mModuleUI.setCountdownFinishedListener(null);
    158         mModuleUI.onModulePaused();
    159         mStateMachine.processEvent(new EventPause());
    160     }
    161 
    162     @Override
    163     public void destroy() {
    164         // Never called. Do nothing here.
    165     }
    166 
    167     @Override
    168     public void onPreviewVisibilityChanged(int visibility) {
    169         // Do nothing.
    170     }
    171 
    172     @Override
    173     public void onLayoutOrientationChanged(boolean isLandscape) {
    174         // Do nothing.
    175     }
    176 
    177     @Override
    178     public void hardResetSettings(SettingsManager settingsManager) {
    179         // Do nothing.
    180     }
    181 
    182     @Override
    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
    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
    203     public boolean isUsingBottomBar() {
    204         return true;
    205     }
    206 
    207     @Override
    208     public String getPeekAccessibilityString() {
    209         return mResourceConstructed.get().getContext().getResources()
    210                 .getString(R.string.photo_accessibility_peek);
    211     }
    212 
    213     @Override
    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
    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