blob: 9e0fa317d6ef454f13b241ca2282e5bdc7e67667 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera.captureintent;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import com.android.camera.CameraActivity;
import com.android.camera.CameraModule;
import com.android.camera.app.AppController;
import com.android.camera.app.CameraAppUI;
import com.android.camera.async.MainThread;
import com.android.camera.async.RefCountBase;
import com.android.camera.burst.BurstFacadeFactory;
import com.android.camera.captureintent.event.EventClickOnCameraKey;
import com.android.camera.captureintent.event.EventOnSurfaceTextureAvailable;
import com.android.camera.captureintent.event.EventOnSurfaceTextureDestroyed;
import com.android.camera.captureintent.event.EventOnSurfaceTextureUpdated;
import com.android.camera.captureintent.event.EventOnTextureViewLayoutChanged;
import com.android.camera.captureintent.event.EventPause;
import com.android.camera.captureintent.event.EventResume;
import com.android.camera.captureintent.event.EventTapOnCancelShutterButton;
import com.android.camera.captureintent.event.EventTapOnPreview;
import com.android.camera.captureintent.event.EventTapOnShutterButton;
import com.android.camera.captureintent.event.EventZoomRatioChanged;
import com.android.camera.captureintent.resource.ResourceConstructed;
import com.android.camera.captureintent.resource.ResourceConstructedImpl;
import com.android.camera.captureintent.state.StateBackground;
import com.android.camera.captureintent.stateful.State;
import com.android.camera.captureintent.stateful.StateMachine;
import com.android.camera.captureintent.stateful.StateMachineImpl;
import com.android.camera.debug.Log;
import com.android.camera.hardware.HardwareSpec;
import com.android.camera.one.OneCameraException;
import com.android.camera.one.OneCameraModule;
import com.android.camera.settings.SettingsManager;
import com.android.camera.ui.PreviewStatusListener;
import com.android.camera.ui.TouchCoordinate;
import com.android.camera.util.Size;
import com.android.camera2.R;
import com.android.ex.camera2.portability.CameraAgent;
/**
* The camera module that handles image capture intent.
*/
public class CaptureIntentModule extends CameraModule {
private static final Log.Tag TAG = new Log.Tag("CapIntModule");
/** The module UI. */
private final CaptureIntentModuleUI mModuleUI;
/** The available resources after construction. */
private final RefCountBase<ResourceConstructed> mResourceConstructed;
/** The module state machine. */
private final StateMachine mStateMachine;
private TouchCoordinate mTouchPointInsideShutterButton;
public CaptureIntentModule(AppController appController, Intent intent,
String settingScopeNamespace) throws OneCameraException {
super(appController);
mModuleUI = new CaptureIntentModuleUI(
appController.getCameraAppUI(),
appController.getModuleLayoutRoot(),
mUIListener);
mStateMachine = new StateMachineImpl();
mResourceConstructed = ResourceConstructedImpl.create(
intent,
mModuleUI,
settingScopeNamespace,
MainThread.create(),
appController.getAndroidContext(),
appController.getCameraOpener(),
OneCameraModule.provideOneCameraManager(),
appController.getLocationManager(),
appController.getOrientationManager(),
appController.getSettingsManager(),
new BurstFacadeFactory.BurstFacadeStub(),
appController,
appController.getFatalErrorHandler());
final State initialState = StateBackground.create(mStateMachine, mResourceConstructed);
// Set the initial state.
mStateMachine.setInitialState(initialState);
}
@Override
public void onCameraAvailable(CameraAgent.CameraProxy cameraProxy) {
// Do nothing for capture intent.
}
@Override
public void onShutterButtonFocus(boolean pressed) {
// Do nothing for capture intent.
}
@Override
public void onShutterCoordinate(TouchCoordinate touchCoordinate) {
mTouchPointInsideShutterButton = touchCoordinate;
}
@Override
public void onShutterButtonClick() {
mStateMachine.processEvent(new EventTapOnShutterButton(mTouchPointInsideShutterButton));
}
@Override
public void onShutterButtonLongPressed() {
// Do nothing for capture intent.
}
@Override
public void init(
final CameraActivity activity, boolean isSecureCamera, boolean isCaptureIntent) {
mResourceConstructed.get().getAppController()
.setPreviewStatusListener(mPreviewStatusListener);
// Issue cancel countdown event when the button is pressed.
// TODO: Make this part of the official API the way shutter button events are.
mResourceConstructed.get().getAppController().getCameraAppUI()
.setCancelShutterButtonListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mStateMachine.processEvent(new EventTapOnCancelShutterButton());
}
});
}
@Override
public void resume() {
mModuleUI.onModuleResumed();
mStateMachine.processEvent(new EventResume());
}
@Override
public void pause() {
mModuleUI.setCountdownFinishedListener(null);
mModuleUI.onModulePaused();
mStateMachine.processEvent(new EventPause());
}
@Override
public void destroy() {
// Never called. Do nothing here.
}
@Override
public void onPreviewVisibilityChanged(int visibility) {
// Do nothing.
}
@Override
public void onLayoutOrientationChanged(boolean isLandscape) {
// Do nothing.
}
@Override
public void hardResetSettings(SettingsManager settingsManager) {
// Do nothing.
}
@Override
public HardwareSpec getHardwareSpec() {
/**
* Instead of passively providing CameraAppUI the hardware spec here,
* {@link com.android.camera.captureintent.state.StateOpeningCamera}
* will actively specify hardware spec.
*/
return null;
}
@Override
public CameraAppUI.BottomBarUISpec getBottomBarSpec() {
/**
* Instead of passively providing CameraAppUI the bottom bar spec here,
* {@link com.android.camera.captureintent.state.StateOpeningCamera}
* will actively specify bottom bar spec.
*/
return null;
}
@Override
public boolean isUsingBottomBar() {
return true;
}
@Override
public String getPeekAccessibilityString() {
return mResourceConstructed.get().getContext().getResources()
.getString(R.string.photo_accessibility_peek);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_CAMERA:
case KeyEvent.KEYCODE_DPAD_CENTER:
mStateMachine.processEvent(new EventClickOnCameraKey());
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
// Prevent default.
return true;
}
return false;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
mStateMachine.processEvent(new EventClickOnCameraKey());
return true;
}
return false;
}
/** The listener to listen events from the UI. */
private final CaptureIntentModuleUI.Listener mUIListener =
new CaptureIntentModuleUI.Listener() {
@Override
public void onZoomRatioChanged(final float zoomRatio) {
mStateMachine.processEvent(new EventZoomRatioChanged(zoomRatio));
}
};
/** The listener to listen events from the preview. */
private final PreviewStatusListener mPreviewStatusListener = new PreviewStatusListener() {
@Override
public void onPreviewLayoutChanged(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
final Size previewLayoutSize = new Size(right - left, bottom - top);
mStateMachine.processEvent(new EventOnTextureViewLayoutChanged(previewLayoutSize));
}
@Override
public boolean shouldAutoAdjustTransformMatrixOnLayout() {
return CaptureIntentConfig.WORKAROUND_PREVIEW_STRETCH_BUG_NEXUS4;
}
@Override
public void onPreviewFlipped() {
// Do nothing because when preview is flipped, TextureView will lay
// itself out again, which will then trigger a transform matrix
// update.
}
@Override
public GestureDetector.OnGestureListener getGestureListener() {
return new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent ev) {
final Point tapPoint = new Point((int) ev.getX(), (int) ev.getY());
mStateMachine.processEvent(new EventTapOnPreview(tapPoint));
return true;
}
};
}
@Override
public View.OnTouchListener getTouchListener() {
return null;
}
@Override
public void onSurfaceTextureAvailable(
final SurfaceTexture surfaceTexture, int width, int height) {
mStateMachine.processEvent(new EventOnSurfaceTextureAvailable(surfaceTexture));
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mStateMachine.processEvent(new EventOnSurfaceTextureDestroyed());
return true;
}
@Override
public void onSurfaceTextureSizeChanged(
SurfaceTexture surfaceTexture, int width, int height) {
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
mStateMachine.processEvent(new EventOnSurfaceTextureUpdated());
}
};
}