summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/NewPhotoModule.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/camera/NewPhotoModule.java')
-rw-r--r--src/com/android/camera/NewPhotoModule.java2037
1 files changed, 0 insertions, 2037 deletions
diff --git a/src/com/android/camera/NewPhotoModule.java b/src/com/android/camera/NewPhotoModule.java
deleted file mode 100644
index 6e306e48f..000000000
--- a/src/com/android/camera/NewPhotoModule.java
+++ /dev/null
@@ -1,2037 +0,0 @@
-/*
- * Copyright (C) 2013 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;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences.Editor;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.SurfaceTexture;
-import android.hardware.Camera.CameraInfo;
-import android.hardware.Camera.Parameters;
-import android.hardware.Camera.PictureCallback;
-import android.hardware.Camera.Size;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.location.Location;
-import android.media.CameraProfile;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.MessageQueue;
-import android.os.SystemClock;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.OrientationEventListener;
-import android.view.SurfaceHolder;
-import android.view.View;
-import android.view.WindowManager;
-
-import com.android.camera.CameraManager.CameraProxy;
-import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
-import com.android.camera.ui.PopupManager;
-import com.android.camera.ui.RotateTextToast;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.exif.ExifInterface;
-import com.android.gallery3d.exif.ExifTag;
-import com.android.gallery3d.exif.Rational;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.filtershow.crop.CropExtras;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Formatter;
-import java.util.List;
-
-public class NewPhotoModule
- implements NewCameraModule,
- PhotoController,
- FocusOverlayManager.Listener,
- CameraPreference.OnPreferenceChangedListener,
- ShutterButton.OnShutterButtonListener,
- MediaSaveService.Listener,
- OnCountDownFinishedListener,
- SensorEventListener {
-
- private static final String TAG = "CAM_PhotoModule";
-
- // We number the request code from 1000 to avoid collision with Gallery.
- private static final int REQUEST_CROP = 1000;
-
- private static final int SETUP_PREVIEW = 1;
- private static final int FIRST_TIME_INIT = 2;
- private static final int CLEAR_SCREEN_DELAY = 3;
- private static final int SET_CAMERA_PARAMETERS_WHEN_IDLE = 4;
- private static final int CHECK_DISPLAY_ROTATION = 5;
- private static final int SHOW_TAP_TO_FOCUS_TOAST = 6;
- private static final int SWITCH_CAMERA = 7;
- private static final int SWITCH_CAMERA_START_ANIMATION = 8;
- private static final int CAMERA_OPEN_DONE = 9;
- private static final int START_PREVIEW_DONE = 10;
- private static final int OPEN_CAMERA_FAIL = 11;
- private static final int CAMERA_DISABLED = 12;
- private static final int CAPTURE_ANIMATION_DONE = 13;
-
- // The subset of parameters we need to update in setCameraParameters().
- private static final int UPDATE_PARAM_INITIALIZE = 1;
- private static final int UPDATE_PARAM_ZOOM = 2;
- private static final int UPDATE_PARAM_PREFERENCE = 4;
- private static final int UPDATE_PARAM_ALL = -1;
-
- // This is the timeout to keep the camera in onPause for the first time
- // after screen on if the activity is started from secure lock screen.
- private static final int KEEP_CAMERA_TIMEOUT = 1000; // ms
-
- // copied from Camera hierarchy
- private NewCameraActivity mActivity;
- private CameraProxy mCameraDevice;
- private int mCameraId;
- private Parameters mParameters;
- private boolean mPaused;
-
- private NewPhotoUI mUI;
-
- // The activity is going to switch to the specified camera id. This is
- // needed because texture copy is done in GL thread. -1 means camera is not
- // switching.
- protected int mPendingSwitchCameraId = -1;
- private boolean mOpenCameraFail;
- private boolean mCameraDisabled;
-
- // When setCameraParametersWhenIdle() is called, we accumulate the subsets
- // needed to be updated in mUpdateSet.
- private int mUpdateSet;
-
- private static final int SCREEN_DELAY = 2 * 60 * 1000;
-
- private int mZoomValue; // The current zoom value.
-
- private Parameters mInitialParams;
- private boolean mFocusAreaSupported;
- private boolean mMeteringAreaSupported;
- private boolean mAeLockSupported;
- private boolean mAwbLockSupported;
- private boolean mContinousFocusSupported;
-
- // The degrees of the device rotated clockwise from its natural orientation.
- private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
- private ComboPreferences mPreferences;
-
- private static final String sTempCropFilename = "crop-temp";
-
- private ContentProviderClient mMediaProviderClient;
- private boolean mFaceDetectionStarted = false;
-
- // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true.
- private String mCropValue;
- private Uri mSaveUri;
-
- // We use a queue to generated names of the images to be used later
- // when the image is ready to be saved.
- private NamedImages mNamedImages;
-
- private Runnable mDoSnapRunnable = new Runnable() {
- @Override
- public void run() {
- onShutterButtonClick();
- }
- };
-
- private Runnable mFlashRunnable = new Runnable() {
- @Override
- public void run() {
- animateFlash();
- }
- };
-
- private final StringBuilder mBuilder = new StringBuilder();
- private final Formatter mFormatter = new Formatter(mBuilder);
- private final Object[] mFormatterArgs = new Object[1];
-
- /**
- * An unpublished intent flag requesting to return as soon as capturing
- * is completed.
- *
- * TODO: consider publishing by moving into MediaStore.
- */
- private static final String EXTRA_QUICK_CAPTURE =
- "android.intent.extra.quickCapture";
-
- // The display rotation in degrees. This is only valid when mCameraState is
- // not PREVIEW_STOPPED.
- private int mDisplayRotation;
- // The value for android.hardware.Camera.setDisplayOrientation.
- private int mCameraDisplayOrientation;
- // The value for UI components like indicators.
- private int mDisplayOrientation;
- // The value for android.hardware.Camera.Parameters.setRotation.
- private int mJpegRotation;
- private boolean mFirstTimeInitialized;
- private boolean mIsImageCaptureIntent;
-
- private int mCameraState = PREVIEW_STOPPED;
- private boolean mSnapshotOnIdle = false;
-
- private ContentResolver mContentResolver;
-
- private LocationManager mLocationManager;
-
- private final PostViewPictureCallback mPostViewPictureCallback =
- new PostViewPictureCallback();
- private final RawPictureCallback mRawPictureCallback =
- new RawPictureCallback();
- private final AutoFocusCallback mAutoFocusCallback =
- new AutoFocusCallback();
- private final Object mAutoFocusMoveCallback =
- ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK
- ? new AutoFocusMoveCallback()
- : null;
-
- private final CameraErrorCallback mErrorCallback = new CameraErrorCallback();
-
- private long mFocusStartTime;
- private long mShutterCallbackTime;
- private long mPostViewPictureCallbackTime;
- private long mRawPictureCallbackTime;
- private long mJpegPictureCallbackTime;
- private long mOnResumeTime;
- private byte[] mJpegImageData;
-
- // These latency time are for the CameraLatency test.
- public long mAutoFocusTime;
- public long mShutterLag;
- public long mShutterToPictureDisplayedTime;
- public long mPictureDisplayedToJpegCallbackTime;
- public long mJpegCallbackFinishTime;
- public long mCaptureStartTime;
-
- // This handles everything about focus.
- private FocusOverlayManager mFocusManager;
-
- private String mSceneMode;
-
- private final Handler mHandler = new MainHandler();
- private PreferenceGroup mPreferenceGroup;
-
- private boolean mQuickCapture;
- private SensorManager mSensorManager;
- private float[] mGData = new float[3];
- private float[] mMData = new float[3];
- private float[] mR = new float[16];
- private int mHeading = -1;
-
- CameraStartUpThread mCameraStartUpThread;
- ConditionVariable mStartPreviewPrerequisiteReady = new ConditionVariable();
-
- private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener =
- new MediaSaveService.OnMediaSavedListener() {
- @Override
- public void onMediaSaved(Uri uri) {
- if (uri != null) {
- mActivity.notifyNewMedia(uri);
- }
- }
- };
-
- // The purpose is not to block the main thread in onCreate and onResume.
- private class CameraStartUpThread extends Thread {
- private volatile boolean mCancelled;
-
- public void cancel() {
- mCancelled = true;
- interrupt();
- }
-
- public boolean isCanceled() {
- return mCancelled;
- }
-
- @Override
- public void run() {
- try {
- // We need to check whether the activity is paused before long
- // operations to ensure that onPause() can be done ASAP.
- if (mCancelled) return;
- mCameraDevice = Util.openCamera(mActivity, mCameraId);
- mParameters = mCameraDevice.getParameters();
- // Wait until all the initialization needed by startPreview are
- // done.
- mStartPreviewPrerequisiteReady.block();
-
- initializeCapabilities();
- if (mFocusManager == null) initializeFocusManager();
- if (mCancelled) return;
- setCameraParameters(UPDATE_PARAM_ALL);
- mHandler.sendEmptyMessage(CAMERA_OPEN_DONE);
- if (mCancelled) return;
- startPreview();
- mHandler.sendEmptyMessage(START_PREVIEW_DONE);
- mOnResumeTime = SystemClock.uptimeMillis();
- mHandler.sendEmptyMessage(CHECK_DISPLAY_ROTATION);
- } catch (CameraHardwareException e) {
- mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL);
- } catch (CameraDisabledException e) {
- mHandler.sendEmptyMessage(CAMERA_DISABLED);
- }
- }
- }
-
- /**
- * This Handler is used to post message back onto the main thread of the
- * application
- */
- private class MainHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SETUP_PREVIEW: {
- setupPreview();
- break;
- }
-
- case CLEAR_SCREEN_DELAY: {
- mActivity.getWindow().clearFlags(
- WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- break;
- }
-
- case FIRST_TIME_INIT: {
- initializeFirstTime();
- break;
- }
-
- case SET_CAMERA_PARAMETERS_WHEN_IDLE: {
- setCameraParametersWhenIdle(0);
- break;
- }
-
- case CHECK_DISPLAY_ROTATION: {
- // Set the display orientation if display rotation has changed.
- // Sometimes this happens when the device is held upside
- // down and camera app is opened. Rotation animation will
- // take some time and the rotation value we have got may be
- // wrong. Framework does not have a callback for this now.
- if (Util.getDisplayRotation(mActivity) != mDisplayRotation) {
- setDisplayOrientation();
- }
- if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) {
- mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100);
- }
- break;
- }
-
- case SHOW_TAP_TO_FOCUS_TOAST: {
- showTapToFocusToast();
- break;
- }
-
- case SWITCH_CAMERA: {
- switchCamera();
- break;
- }
-
- case SWITCH_CAMERA_START_ANIMATION: {
- // TODO: Need to revisit
- // ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera();
- break;
- }
-
- case CAMERA_OPEN_DONE: {
- onCameraOpened();
- break;
- }
-
- case START_PREVIEW_DONE: {
- onPreviewStarted();
- break;
- }
-
- case OPEN_CAMERA_FAIL: {
- mCameraStartUpThread = null;
- mOpenCameraFail = true;
- Util.showErrorAndFinish(mActivity,
- R.string.cannot_connect_camera);
- break;
- }
-
- case CAMERA_DISABLED: {
- mCameraStartUpThread = null;
- mCameraDisabled = true;
- Util.showErrorAndFinish(mActivity,
- R.string.camera_disabled);
- break;
- }
- case CAPTURE_ANIMATION_DONE: {
- mUI.enablePreviewThumb(false);
- break;
- }
- }
- }
- }
-
- @Override
- public void init(NewCameraActivity activity, View parent) {
- mActivity = activity;
- mUI = new NewPhotoUI(activity, this, parent);
- mPreferences = new ComboPreferences(mActivity);
- CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal());
- mCameraId = getPreferredCameraId(mPreferences);
-
- mContentResolver = mActivity.getContentResolver();
-
- // To reduce startup time, open the camera and start the preview in
- // another thread.
- mCameraStartUpThread = new CameraStartUpThread();
- mCameraStartUpThread.start();
-
- // Surface texture is from camera screen nail and startPreview needs it.
- // This must be done before startPreview.
- mIsImageCaptureIntent = isImageCaptureIntent();
-
- mPreferences.setLocalId(mActivity, mCameraId);
- CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
- // we need to reset exposure for the preview
- resetExposureCompensation();
- // Starting the preview needs preferences, camera screen nail, and
- // focus area indicator.
- mStartPreviewPrerequisiteReady.open();
-
- initializeControlByIntent();
- mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
- mLocationManager = new LocationManager(mActivity, mUI);
- mSensorManager = (SensorManager)(mActivity.getSystemService(Context.SENSOR_SERVICE));
- }
-
- private void initializeControlByIntent() {
- mUI.initializeControlByIntent();
- if (mIsImageCaptureIntent) {
- setupCaptureParams();
- }
- }
-
- private void onPreviewStarted() {
- mCameraStartUpThread = null;
- setCameraState(IDLE);
- startFaceDetection();
- locationFirstRun();
- }
-
- // Prompt the user to pick to record location for the very first run of
- // camera only
- private void locationFirstRun() {
- if (RecordLocationPreference.isSet(mPreferences)) {
- return;
- }
- if (mActivity.isSecureCamera()) return;
- // Check if the back camera exists
- int backCameraId = CameraHolder.instance().getBackCameraId();
- if (backCameraId == -1) {
- // If there is no back camera, do not show the prompt.
- return;
- }
-
- new AlertDialog.Builder(mActivity)
- .setTitle(R.string.remember_location_title)
- .setMessage(R.string.remember_location_prompt)
- .setPositiveButton(R.string.remember_location_yes, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int arg1) {
- setLocationPreference(RecordLocationPreference.VALUE_ON);
- }
- })
- .setNegativeButton(R.string.remember_location_no, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int arg1) {
- dialog.cancel();
- }
- })
- .setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- setLocationPreference(RecordLocationPreference.VALUE_OFF);
- }
- })
- .show();
- }
-
- private void setLocationPreference(String value) {
- mPreferences.edit()
- .putString(CameraSettings.KEY_RECORD_LOCATION, value)
- .apply();
- // TODO: Fix this to use the actual onSharedPreferencesChanged listener
- // instead of invoking manually
- onSharedPreferenceChanged();
- }
-
- private void onCameraOpened() {
- View root = mUI.getRootView();
- // These depend on camera parameters.
-
- int width = root.getWidth();
- int height = root.getHeight();
- mFocusManager.setPreviewSize(width, height);
- openCameraCommon();
- }
-
- private void switchCamera() {
- if (mPaused) return;
-
- Log.v(TAG, "Start to switch camera. id=" + mPendingSwitchCameraId);
- mCameraId = mPendingSwitchCameraId;
- mPendingSwitchCameraId = -1;
- setCameraId(mCameraId);
-
- // from onPause
- closeCamera();
- mUI.collapseCameraControls();
- mUI.clearFaces();
- if (mFocusManager != null) mFocusManager.removeMessages();
-
- // Restart the camera and initialize the UI. From onCreate.
- mPreferences.setLocalId(mActivity, mCameraId);
- CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
- try {
- mCameraDevice = Util.openCamera(mActivity, mCameraId);
- mParameters = mCameraDevice.getParameters();
- } catch (CameraHardwareException e) {
- Util.showErrorAndFinish(mActivity, R.string.cannot_connect_camera);
- return;
- } catch (CameraDisabledException e) {
- Util.showErrorAndFinish(mActivity, R.string.camera_disabled);
- return;
- }
- initializeCapabilities();
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
- boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
- mFocusManager.setMirror(mirror);
- mFocusManager.setParameters(mInitialParams);
- setupPreview();
-
- // reset zoom value index
- mZoomValue = 0;
- openCameraCommon();
-
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- // Start switch camera animation. Post a message because
- // onFrameAvailable from the old camera may already exist.
- mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION);
- }
- }
-
- protected void setCameraId(int cameraId) {
- ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID);
- pref.setValue("" + cameraId);
- }
-
- // either open a new camera or switch cameras
- private void openCameraCommon() {
- loadCameraPreferences();
-
- mUI.onCameraOpened(mPreferenceGroup, mPreferences, mParameters, this);
- updateSceneMode();
- showTapToFocusToastIfNeeded();
-
-
- }
-
- public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) {
- if (mFocusManager != null) mFocusManager.setPreviewSize(width, height);
- }
-
- private void resetExposureCompensation() {
- String value = mPreferences.getString(CameraSettings.KEY_EXPOSURE,
- CameraSettings.EXPOSURE_DEFAULT_VALUE);
- if (!CameraSettings.EXPOSURE_DEFAULT_VALUE.equals(value)) {
- Editor editor = mPreferences.edit();
- editor.putString(CameraSettings.KEY_EXPOSURE, "0");
- editor.apply();
- }
- }
-
- private void keepMediaProviderInstance() {
- // We want to keep a reference to MediaProvider in camera's lifecycle.
- // TODO: Utilize mMediaProviderClient instance to replace
- // ContentResolver calls.
- if (mMediaProviderClient == null) {
- mMediaProviderClient = mContentResolver
- .acquireContentProviderClient(MediaStore.AUTHORITY);
- }
- }
-
- // Snapshots can only be taken after this is called. It should be called
- // once only. We could have done these things in onCreate() but we want to
- // make preview screen appear as soon as possible.
- private void initializeFirstTime() {
- if (mFirstTimeInitialized) return;
-
- // Initialize location service.
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
- mLocationManager.recordLocation(recordLocation);
-
- keepMediaProviderInstance();
-
- mUI.initializeFirstTime();
- MediaSaveService s = mActivity.getMediaSaveService();
- // We set the listener only when both service and shutterbutton
- // are initialized.
- if (s != null) {
- s.setListener(this);
- }
-
- mNamedImages = new NamedImages();
-
- mFirstTimeInitialized = true;
- addIdleHandler();
-
- mActivity.updateStorageSpaceAndHint();
- }
-
- // If the activity is paused and resumed, this method will be called in
- // onResume.
- private void initializeSecondTime() {
- // Start location update if needed.
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
- mLocationManager.recordLocation(recordLocation);
- MediaSaveService s = mActivity.getMediaSaveService();
- if (s != null) {
- s.setListener(this);
- }
- mNamedImages = new NamedImages();
- mUI.initializeSecondTime(mParameters);
- keepMediaProviderInstance();
- }
-
- @Override
- public void onSurfaceCreated(SurfaceHolder holder) {
- // Do not access the camera if camera start up thread is not finished.
- if (mCameraDevice == null || mCameraStartUpThread != null)
- return;
-
- mCameraDevice.setPreviewDisplayAsync(holder);
- // This happens when onConfigurationChanged arrives, surface has been
- // destroyed, and there is no onFullScreenChanged.
- if (mCameraState == PREVIEW_STOPPED) {
- setupPreview();
- }
- }
-
- private void showTapToFocusToastIfNeeded() {
- // Show the tap to focus toast if this is the first start.
- if (mFocusAreaSupported &&
- mPreferences.getBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, true)) {
- // Delay the toast for one second to wait for orientation.
- mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000);
- }
- }
-
- private void addIdleHandler() {
- MessageQueue queue = Looper.myQueue();
- queue.addIdleHandler(new MessageQueue.IdleHandler() {
- @Override
- public boolean queueIdle() {
- Storage.ensureOSXCompatible();
- return false;
- }
- });
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- @Override
- public void startFaceDetection() {
- if (!ApiHelper.HAS_FACE_DETECTION) return;
- if (mFaceDetectionStarted) return;
- if (mParameters.getMaxNumDetectedFaces() > 0) {
- mFaceDetectionStarted = true;
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
- mUI.onStartFaceDetection(mDisplayOrientation,
- (info.facing == CameraInfo.CAMERA_FACING_FRONT));
- mCameraDevice.setFaceDetectionListener(mUI);
- mCameraDevice.startFaceDetection();
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- @Override
- public void stopFaceDetection() {
- if (!ApiHelper.HAS_FACE_DETECTION) return;
- if (!mFaceDetectionStarted) return;
- if (mParameters.getMaxNumDetectedFaces() > 0) {
- mFaceDetectionStarted = false;
- mCameraDevice.setFaceDetectionListener(null);
- mCameraDevice.stopFaceDetection();
- mUI.clearFaces();
- }
- }
-
- private final class ShutterCallback
- implements android.hardware.Camera.ShutterCallback {
-
- private boolean mAnimateFlash;
-
- public ShutterCallback(boolean animateFlash) {
- mAnimateFlash = animateFlash;
- }
-
- @Override
- public void onShutter() {
- mShutterCallbackTime = System.currentTimeMillis();
- mShutterLag = mShutterCallbackTime - mCaptureStartTime;
- Log.v(TAG, "mShutterLag = " + mShutterLag + "ms");
- if (mAnimateFlash) {
- mActivity.runOnUiThread(mFlashRunnable);
- }
- }
- }
-
- private final class PostViewPictureCallback implements PictureCallback {
- @Override
- public void onPictureTaken(
- byte [] data, android.hardware.Camera camera) {
- mPostViewPictureCallbackTime = System.currentTimeMillis();
- Log.v(TAG, "mShutterToPostViewCallbackTime = "
- + (mPostViewPictureCallbackTime - mShutterCallbackTime)
- + "ms");
- }
- }
-
- private final class RawPictureCallback implements PictureCallback {
- @Override
- public void onPictureTaken(
- byte [] rawData, android.hardware.Camera camera) {
- mRawPictureCallbackTime = System.currentTimeMillis();
- Log.v(TAG, "mShutterToRawCallbackTime = "
- + (mRawPictureCallbackTime - mShutterCallbackTime) + "ms");
- }
- }
-
- private final class JpegPictureCallback implements PictureCallback {
- Location mLocation;
-
- public JpegPictureCallback(Location loc) {
- mLocation = loc;
- }
-
- @Override
- public void onPictureTaken(
- final byte [] jpegData, final android.hardware.Camera camera) {
- if (mPaused) {
- return;
- }
- //TODO: We should show the picture taken rather than frozen preview here
- if (mIsImageCaptureIntent) {
- stopPreview();
- }
- if (mSceneMode == Util.SCENE_MODE_HDR) {
- mUI.showSwitcher();
- mUI.setSwipingEnabled(true);
- }
-
- mJpegPictureCallbackTime = System.currentTimeMillis();
- // If postview callback has arrived, the captured image is displayed
- // in postview callback. If not, the captured image is displayed in
- // raw picture callback.
- if (mPostViewPictureCallbackTime != 0) {
- mShutterToPictureDisplayedTime =
- mPostViewPictureCallbackTime - mShutterCallbackTime;
- mPictureDisplayedToJpegCallbackTime =
- mJpegPictureCallbackTime - mPostViewPictureCallbackTime;
- } else {
- mShutterToPictureDisplayedTime =
- mRawPictureCallbackTime - mShutterCallbackTime;
- mPictureDisplayedToJpegCallbackTime =
- mJpegPictureCallbackTime - mRawPictureCallbackTime;
- }
- Log.v(TAG, "mPictureDisplayedToJpegCallbackTime = "
- + mPictureDisplayedToJpegCallbackTime + "ms");
-
- /*TODO:
- // Only animate when in full screen capture mode
- // i.e. If monkey/a user swipes to the gallery during picture taking,
- // don't show animation
- if (ApiHelper.HAS_SURFACE_TEXTURE && !mIsImageCaptureIntent
- && mActivity.mShowCameraAppView) {
- // Finish capture animation
- mHandler.removeMessages(CAPTURE_ANIMATION_DONE);
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateSlide();
- mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE,
- CaptureAnimManager.getAnimationDuration());
- } */
- mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden.
- if (!mIsImageCaptureIntent) {
- if (ApiHelper.CAN_START_PREVIEW_IN_JPEG_CALLBACK) {
- setupPreview();
- } else {
- // Camera HAL of some devices have a bug. Starting preview
- // immediately after taking a picture will fail. Wait some
- // time before starting the preview.
- mHandler.sendEmptyMessageDelayed(SETUP_PREVIEW, 300);
- }
- }
-
- if (!mIsImageCaptureIntent) {
- // Calculate the width and the height of the jpeg.
- Size s = mParameters.getPictureSize();
- ExifInterface exif = Exif.getExif(jpegData);
- int orientation = Exif.getOrientation(exif);
- int width, height;
- if ((mJpegRotation + orientation) % 180 == 0) {
- width = s.width;
- height = s.height;
- } else {
- width = s.height;
- height = s.width;
- }
- String title = mNamedImages.getTitle();
- long date = mNamedImages.getDate();
- if (title == null) {
- Log.e(TAG, "Unbalanced name/data pair");
- } else {
- if (date == -1) date = mCaptureStartTime;
- if (mHeading >= 0) {
- // heading direction has been updated by the sensor.
- ExifTag directionRefTag = exif.buildTag(
- ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
- ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION);
- ExifTag directionTag = exif.buildTag(
- ExifInterface.TAG_GPS_IMG_DIRECTION,
- new Rational(mHeading, 1));
- exif.setTag(directionRefTag);
- exif.setTag(directionTag);
- }
- mActivity.getMediaSaveService().addImage(
- jpegData, title, date, mLocation, width, height,
- orientation, exif, mOnMediaSavedListener, mContentResolver);
- }
- } else {
- mJpegImageData = jpegData;
- if (!mQuickCapture) {
- mUI.showPostCaptureAlert();
- } else {
- onCaptureDone();
- }
- }
-
- // Check this in advance of each shot so we don't add to shutter
- // latency. It's true that someone else could write to the SD card in
- // the mean time and fill it, but that could have happened between the
- // shutter press and saving the JPEG too.
- mActivity.updateStorageSpaceAndHint();
-
- long now = System.currentTimeMillis();
- mJpegCallbackFinishTime = now - mJpegPictureCallbackTime;
- Log.v(TAG, "mJpegCallbackFinishTime = "
- + mJpegCallbackFinishTime + "ms");
- mJpegPictureCallbackTime = 0;
- }
- }
-
- private final class AutoFocusCallback
- implements android.hardware.Camera.AutoFocusCallback {
- @Override
- public void onAutoFocus(
- boolean focused, android.hardware.Camera camera) {
- if (mPaused) return;
-
- mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime;
- Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms");
- setCameraState(IDLE);
- mFocusManager.onAutoFocus(focused, mUI.isShutterPressed());
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
- private final class AutoFocusMoveCallback
- implements android.hardware.Camera.AutoFocusMoveCallback {
- @Override
- public void onAutoFocusMoving(
- boolean moving, android.hardware.Camera camera) {
- mFocusManager.onAutoFocusMoving(moving);
- }
- }
-
- private static class NamedImages {
- private ArrayList<NamedEntity> mQueue;
- private boolean mStop;
- private NamedEntity mNamedEntity;
-
- public NamedImages() {
- mQueue = new ArrayList<NamedEntity>();
- }
-
- public void nameNewImage(ContentResolver resolver, long date) {
- NamedEntity r = new NamedEntity();
- r.title = Util.createJpegName(date);
- r.date = date;
- mQueue.add(r);
- }
-
- public String getTitle() {
- if (mQueue.isEmpty()) {
- mNamedEntity = null;
- return null;
- }
- mNamedEntity = mQueue.get(0);
- mQueue.remove(0);
-
- return mNamedEntity.title;
- }
-
- // Must be called after getTitle().
- public long getDate() {
- if (mNamedEntity == null) return -1;
- return mNamedEntity.date;
- }
-
- private static class NamedEntity {
- String title;
- long date;
- }
- }
-
- private void setCameraState(int state) {
- mCameraState = state;
- switch (state) {
- case PhotoController.PREVIEW_STOPPED:
- case PhotoController.SNAPSHOT_IN_PROGRESS:
- case PhotoController.SWITCHING_CAMERA:
- mUI.enableGestures(false);
- break;
- case PhotoController.IDLE:
- mUI.enableGestures(true);
- break;
- }
- }
-
- private void animateFlash() {
- /* //TODO:
- // Only animate when in full screen capture mode
- // i.e. If monkey/a user swipes to the gallery during picture taking,
- // don't show animation
- if (ApiHelper.HAS_SURFACE_TEXTURE && !mIsImageCaptureIntent
- && mActivity.mShowCameraAppView) {
- // Start capture animation.
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateFlash(mDisplayRotation);
- mUI.enablePreviewThumb(true);
- mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE,
- CaptureAnimManager.getAnimationDuration());
- } */
- }
-
- @Override
- public boolean capture() {
- // If we are already in the middle of taking a snapshot or the image save request
- // is full then ignore.
- if (mCameraDevice == null || mCameraState == SNAPSHOT_IN_PROGRESS
- || mCameraState == SWITCHING_CAMERA
- || mActivity.getMediaSaveService().isQueueFull()) {
- return false;
- }
- mCaptureStartTime = System.currentTimeMillis();
- mPostViewPictureCallbackTime = 0;
- mJpegImageData = null;
-
- final boolean animateBefore = (mSceneMode == Util.SCENE_MODE_HDR);
-
- if (animateBefore) {
- animateFlash();
- }
-
- // Set rotation and gps data.
- int orientation;
- // We need to be consistent with the framework orientation (i.e. the
- // orientation of the UI.) when the auto-rotate screen setting is on.
- if (mActivity.isAutoRotateScreen()) {
- orientation = (360 - mDisplayRotation) % 360;
- } else {
- orientation = mOrientation;
- }
- mJpegRotation = Util.getJpegRotation(mCameraId, orientation);
- mParameters.setRotation(mJpegRotation);
- Location loc = mLocationManager.getCurrentLocation();
- Util.setGpsParameters(mParameters, loc);
- mCameraDevice.setParameters(mParameters);
-
- mCameraDevice.takePicture2(new ShutterCallback(!animateBefore),
- mRawPictureCallback, mPostViewPictureCallback,
- new JpegPictureCallback(loc), mCameraState,
- mFocusManager.getFocusState());
-
- mNamedImages.nameNewImage(mContentResolver, mCaptureStartTime);
-
- mFaceDetectionStarted = false;
- setCameraState(SNAPSHOT_IN_PROGRESS);
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
- UsageStatistics.ACTION_CAPTURE_DONE, "Photo");
- return true;
- }
-
- @Override
- public void setFocusParameters() {
- setCameraParameters(UPDATE_PARAM_PREFERENCE);
- }
-
- private int getPreferredCameraId(ComboPreferences preferences) {
- int intentCameraId = Util.getCameraFacingIntentExtras(mActivity);
- if (intentCameraId != -1) {
- // Testing purpose. Launch a specific camera through the intent
- // extras.
- return intentCameraId;
- } else {
- return CameraSettings.readPreferredCameraId(preferences);
- }
- }
-
- private void updateSceneMode() {
- // If scene mode is set, we cannot set flash mode, white balance, and
- // focus mode, instead, we read it from driver
- if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
- overrideCameraSettings(mParameters.getFlashMode(),
- mParameters.getWhiteBalance(), mParameters.getFocusMode());
- } else {
- overrideCameraSettings(null, null, null);
- }
- }
-
- private void overrideCameraSettings(final String flashMode,
- final String whiteBalance, final String focusMode) {
- mUI.overrideSettings(
- CameraSettings.KEY_FLASH_MODE, flashMode,
- CameraSettings.KEY_WHITE_BALANCE, whiteBalance,
- CameraSettings.KEY_FOCUS_MODE, focusMode);
- }
-
- private void loadCameraPreferences() {
- CameraSettings settings = new CameraSettings(mActivity, mInitialParams,
- mCameraId, CameraHolder.instance().getCameraInfo());
- mPreferenceGroup = settings.getPreferenceGroup(R.xml.camera_preferences);
- }
-
- @Override
- public void onOrientationChanged(int orientation) {
- // We keep the last known orientation. So if the user first orient
- // the camera then point the camera to floor or sky, we still have
- // the correct orientation.
- if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return;
- mOrientation = Util.roundOrientation(orientation, mOrientation);
-
- // Show the toast after getting the first orientation changed.
- if (mHandler.hasMessages(SHOW_TAP_TO_FOCUS_TOAST)) {
- mHandler.removeMessages(SHOW_TAP_TO_FOCUS_TOAST);
- showTapToFocusToast();
- }
- }
-
- @Override
- public void onStop() {
- if (mMediaProviderClient != null) {
- mMediaProviderClient.release();
- mMediaProviderClient = null;
- }
- }
-
- @Override
- public void onCaptureCancelled() {
- mActivity.setResultEx(Activity.RESULT_CANCELED, new Intent());
- mActivity.finish();
- }
-
- @Override
- public void onCaptureRetake() {
- if (mPaused)
- return;
- mUI.hidePostCaptureAlert();
- setupPreview();
- }
-
- @Override
- public void onCaptureDone() {
- if (mPaused) {
- return;
- }
-
- byte[] data = mJpegImageData;
-
- if (mCropValue == null) {
- // First handle the no crop case -- just return the value. If the
- // caller specifies a "save uri" then write the data to its
- // stream. Otherwise, pass back a scaled down version of the bitmap
- // directly in the extras.
- if (mSaveUri != null) {
- OutputStream outputStream = null;
- try {
- outputStream = mContentResolver.openOutputStream(mSaveUri);
- outputStream.write(data);
- outputStream.close();
-
- mActivity.setResultEx(Activity.RESULT_OK);
- mActivity.finish();
- } catch (IOException ex) {
- // ignore exception
- } finally {
- Util.closeSilently(outputStream);
- }
- } else {
- ExifInterface exif = Exif.getExif(data);
- int orientation = Exif.getOrientation(exif);
- Bitmap bitmap = Util.makeBitmap(data, 50 * 1024);
- bitmap = Util.rotate(bitmap, orientation);
- mActivity.setResultEx(Activity.RESULT_OK,
- new Intent("inline-data").putExtra("data", bitmap));
- mActivity.finish();
- }
- } else {
- // Save the image to a temp file and invoke the cropper
- Uri tempUri = null;
- FileOutputStream tempStream = null;
- try {
- File path = mActivity.getFileStreamPath(sTempCropFilename);
- path.delete();
- tempStream = mActivity.openFileOutput(sTempCropFilename, 0);
- tempStream.write(data);
- tempStream.close();
- tempUri = Uri.fromFile(path);
- } catch (FileNotFoundException ex) {
- mActivity.setResultEx(Activity.RESULT_CANCELED);
- mActivity.finish();
- return;
- } catch (IOException ex) {
- mActivity.setResultEx(Activity.RESULT_CANCELED);
- mActivity.finish();
- return;
- } finally {
- Util.closeSilently(tempStream);
- }
-
- Bundle newExtras = new Bundle();
- if (mCropValue.equals("circle")) {
- newExtras.putString("circleCrop", "true");
- }
- if (mSaveUri != null) {
- newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri);
- } else {
- newExtras.putBoolean(CropExtras.KEY_RETURN_DATA, true);
- }
- if (mActivity.isSecureCamera()) {
- newExtras.putBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, true);
- }
-
- Intent cropIntent = new Intent(CropActivity.CROP_ACTION);
-
- cropIntent.setData(tempUri);
- cropIntent.putExtras(newExtras);
-
- mActivity.startActivityForResult(cropIntent, REQUEST_CROP);
- }
- }
-
- @Override
- public void onShutterButtonFocus(boolean pressed) {
- if (mPaused || mUI.collapseCameraControls()
- || (mCameraState == SNAPSHOT_IN_PROGRESS)
- || (mCameraState == PREVIEW_STOPPED)) return;
-
- // Do not do focus if there is not enough storage.
- if (pressed && !canTakePicture()) return;
-
- if (pressed) {
- mFocusManager.onShutterDown();
- } else {
- // for countdown mode, we need to postpone the shutter release
- // i.e. lock the focus during countdown.
- if (!mUI.isCountingDown()) {
- mFocusManager.onShutterUp();
- }
- }
- }
-
- @Override
- public void onShutterButtonClick() {
- if (mPaused || mUI.collapseCameraControls()
- || (mCameraState == SWITCHING_CAMERA)
- || (mCameraState == PREVIEW_STOPPED)) return;
-
- // Do not take the picture if there is not enough storage.
- if (mActivity.getStorageSpace() <= Storage.LOW_STORAGE_THRESHOLD) {
- Log.i(TAG, "Not enough space or storage not ready. remaining="
- + mActivity.getStorageSpace());
- return;
- }
- Log.v(TAG, "onShutterButtonClick: mCameraState=" + mCameraState);
-
- if (mSceneMode == Util.SCENE_MODE_HDR) {
- mUI.hideSwitcher();
- mUI.setSwipingEnabled(false);
- }
- // If the user wants to do a snapshot while the previous one is still
- // in progress, remember the fact and do it after we finish the previous
- // one and re-start the preview. Snapshot in progress also includes the
- // state that autofocus is focusing and a picture will be taken when
- // focus callback arrives.
- if ((mFocusManager.isFocusingSnapOnFinish() || mCameraState == SNAPSHOT_IN_PROGRESS)
- && !mIsImageCaptureIntent) {
- mSnapshotOnIdle = true;
- return;
- }
-
- String timer = mPreferences.getString(
- CameraSettings.KEY_TIMER,
- mActivity.getString(R.string.pref_camera_timer_default));
- boolean playSound = mPreferences.getString(CameraSettings.KEY_TIMER_SOUND_EFFECTS,
- mActivity.getString(R.string.pref_camera_timer_sound_default))
- .equals(mActivity.getString(R.string.setting_on_value));
-
- int seconds = Integer.parseInt(timer);
- // When shutter button is pressed, check whether the previous countdown is
- // finished. If not, cancel the previous countdown and start a new one.
- if (mUI.isCountingDown()) {
- mUI.cancelCountDown();
- }
- if (seconds > 0) {
- mUI.startCountDown(seconds, playSound);
- } else {
- mSnapshotOnIdle = false;
- mFocusManager.doSnap();
- }
- }
-
- @Override
- public void installIntentFilter() {
- }
-
- @Override
- public boolean updateStorageHintOnResume() {
- return mFirstTimeInitialized;
- }
-
- @Override
- public void updateCameraAppView() {
- }
-
- @Override
- public void onResumeBeforeSuper() {
- mPaused = false;
- }
-
- @Override
- public void onResumeAfterSuper() {
- if (mOpenCameraFail || mCameraDisabled) return;
-
- mJpegPictureCallbackTime = 0;
- mZoomValue = 0;
- // Start the preview if it is not started.
- if (mCameraState == PREVIEW_STOPPED && mCameraStartUpThread == null) {
- resetExposureCompensation();
- mCameraStartUpThread = new CameraStartUpThread();
- mCameraStartUpThread.start();
- }
-
- // If first time initialization is not finished, put it in the
- // message queue.
- if (!mFirstTimeInitialized) {
- mHandler.sendEmptyMessage(FIRST_TIME_INIT);
- } else {
- initializeSecondTime();
- }
- keepScreenOnAwhile();
-
- // Dismiss open menu if exists.
- PopupManager.getInstance(mActivity).notifyShowPopup(null);
- UsageStatistics.onContentViewChanged(
- UsageStatistics.COMPONENT_CAMERA, "PhotoModule");
-
- Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- if (gsensor != null) {
- mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_NORMAL);
- }
-
- Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
- if (msensor != null) {
- mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_NORMAL);
- }
- }
-
- void waitCameraStartUpThread() {
- try {
- if (mCameraStartUpThread != null) {
- mCameraStartUpThread.cancel();
- mCameraStartUpThread.join();
- mCameraStartUpThread = null;
- setCameraState(IDLE);
- }
- } catch (InterruptedException e) {
- // ignore
- }
- }
-
- @Override
- public void onPauseBeforeSuper() {
- mPaused = true;
- Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- if (gsensor != null) {
- mSensorManager.unregisterListener(this, gsensor);
- }
-
- Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
- if (msensor != null) {
- mSensorManager.unregisterListener(this, msensor);
- }
- }
-
- @Override
- public void onPauseAfterSuper() {
- // Wait the camera start up thread to finish.
- waitCameraStartUpThread();
-
- // When camera is started from secure lock screen for the first time
- // after screen on, the activity gets onCreate->onResume->onPause->onResume.
- // To reduce the latency, keep the camera for a short time so it does
- // not need to be opened again.
- if (mCameraDevice != null && mActivity.isSecureCamera()
- && ActivityBase.isFirstStartAfterScreenOn()) {
- ActivityBase.resetFirstStartAfterScreenOn();
- CameraHolder.instance().keep(KEEP_CAMERA_TIMEOUT);
- }
- // Reset the focus first. Camera CTS does not guarantee that
- // cancelAutoFocus is allowed after preview stops.
- if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
- mCameraDevice.cancelAutoFocus();
- }
- stopPreview();
-
- mNamedImages = null;
-
- if (mLocationManager != null) mLocationManager.recordLocation(false);
-
- // If we are in an image capture intent and has taken
- // a picture, we just clear it in onPause.
- mJpegImageData = null;
-
- // Remove the messages in the event queue.
- mHandler.removeMessages(SETUP_PREVIEW);
- mHandler.removeMessages(FIRST_TIME_INIT);
- mHandler.removeMessages(CHECK_DISPLAY_ROTATION);
- mHandler.removeMessages(SWITCH_CAMERA);
- mHandler.removeMessages(SWITCH_CAMERA_START_ANIMATION);
- mHandler.removeMessages(CAMERA_OPEN_DONE);
- mHandler.removeMessages(START_PREVIEW_DONE);
- mHandler.removeMessages(OPEN_CAMERA_FAIL);
- mHandler.removeMessages(CAMERA_DISABLED);
-
- closeCamera();
-
- resetScreenOn();
- mUI.onPause();
-
- mPendingSwitchCameraId = -1;
- if (mFocusManager != null) mFocusManager.removeMessages();
- MediaSaveService s = mActivity.getMediaSaveService();
- if (s != null) {
- s.setListener(null);
- }
- }
-
- /**
- * The focus manager is the first UI related element to get initialized,
- * and it requires the RenderOverlay, so initialize it here
- */
- private void initializeFocusManager() {
- // Create FocusManager object. startPreview needs it.
- // if mFocusManager not null, reuse it
- // otherwise create a new instance
- if (mFocusManager != null) {
- mFocusManager.removeMessages();
- } else {
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
- boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
- String[] defaultFocusModes = mActivity.getResources().getStringArray(
- R.array.pref_camera_focusmode_default_array);
- mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes,
- mInitialParams, this, mirror,
- mActivity.getMainLooper(), mUI);
- }
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- Log.v(TAG, "onConfigurationChanged");
- setDisplayOrientation();
- }
-
- @Override
- public void updateCameraOrientation() {
- if (mDisplayRotation != Util.getDisplayRotation(mActivity)) {
- setDisplayOrientation();
- }
- }
-
- @Override
- public void onActivityResult(
- int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CROP: {
- Intent intent = new Intent();
- if (data != null) {
- Bundle extras = data.getExtras();
- if (extras != null) {
- intent.putExtras(extras);
- }
- }
- mActivity.setResultEx(resultCode, intent);
- mActivity.finish();
-
- File path = mActivity.getFileStreamPath(sTempCropFilename);
- path.delete();
-
- break;
- }
- }
- }
-
- private boolean canTakePicture() {
- return isCameraIdle() && (mActivity.getStorageSpace() > Storage.LOW_STORAGE_THRESHOLD);
- }
-
- @Override
- public void autoFocus() {
- mFocusStartTime = System.currentTimeMillis();
- mCameraDevice.autoFocus(mAutoFocusCallback);
- setCameraState(FOCUSING);
- }
-
- @Override
- public void cancelAutoFocus() {
- mCameraDevice.cancelAutoFocus();
- setCameraState(IDLE);
- setCameraParameters(UPDATE_PARAM_PREFERENCE);
- }
-
- // Preview area is touched. Handle touch focus.
- @Override
- public void onSingleTapUp(View view, int x, int y) {
- if (mPaused || mCameraDevice == null || !mFirstTimeInitialized
- || mCameraState == SNAPSHOT_IN_PROGRESS
- || mCameraState == SWITCHING_CAMERA
- || mCameraState == PREVIEW_STOPPED) {
- return;
- }
-
- // Do not trigger touch focus if popup window is opened.
- if (mUI.removeTopLevelPopup()) return;
-
- // Check if metering area or focus area is supported.
- if (!mFocusAreaSupported && !mMeteringAreaSupported) return;
- mFocusManager.onSingleTapUp(x, y);
- }
-
- @Override
- public boolean onBackPressed() {
- return mUI.onBackPressed();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_FOCUS:
- if (/*TODO: mActivity.isInCameraApp() &&*/ mFirstTimeInitialized) {
- if (event.getRepeatCount() == 0) {
- onShutterButtonFocus(true);
- }
- return true;
- }
- return false;
- case KeyEvent.KEYCODE_CAMERA:
- if (mFirstTimeInitialized && event.getRepeatCount() == 0) {
- onShutterButtonClick();
- }
- return true;
- case KeyEvent.KEYCODE_DPAD_CENTER:
- // If we get a dpad center event without any focused view, move
- // the focus to the shutter button and press it.
- if (mFirstTimeInitialized && event.getRepeatCount() == 0) {
- // Start auto-focus immediately to reduce shutter lag. After
- // the shutter button gets the focus, onShutterButtonFocus()
- // will be called again but it is fine.
- if (mUI.removeTopLevelPopup()) return true;
- onShutterButtonFocus(true);
- mUI.pressShutterButton();
- }
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (/*mActivity.isInCameraApp() && */ mFirstTimeInitialized) {
- onShutterButtonClick();
- return true;
- }
- return false;
- case KeyEvent.KEYCODE_FOCUS:
- if (mFirstTimeInitialized) {
- onShutterButtonFocus(false);
- }
- return true;
- }
- return false;
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- private void closeCamera() {
- if (mCameraDevice != null) {
- mCameraDevice.setZoomChangeListener(null);
- if(ApiHelper.HAS_FACE_DETECTION) {
- mCameraDevice.setFaceDetectionListener(null);
- }
- mCameraDevice.setErrorCallback(null);
- CameraHolder.instance().release();
- mFaceDetectionStarted = false;
- mCameraDevice = null;
- setCameraState(PREVIEW_STOPPED);
- mFocusManager.onCameraReleased();
- }
- }
-
- private void setDisplayOrientation() {
- mDisplayRotation = Util.getDisplayRotation(mActivity);
- mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId);
- mCameraDisplayOrientation = mDisplayOrientation;
- mUI.setDisplayOrientation(mDisplayOrientation);
- if (mFocusManager != null) {
- mFocusManager.setDisplayOrientation(mDisplayOrientation);
- }
- // Change the camera display orientation
- if (mCameraDevice != null) {
- mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
- }
- }
-
- // Only called by UI thread.
- private void setupPreview() {
- mFocusManager.resetTouchFocus();
- startPreview();
- setCameraState(IDLE);
- startFaceDetection();
- }
-
- // This can be called by UI Thread or CameraStartUpThread. So this should
- // not modify the views.
- private void startPreview() {
- mCameraDevice.setErrorCallback(mErrorCallback);
-
- // ICS camera frameworks has a bug. Face detection state is not cleared
- // after taking a picture. Stop the preview to work around it. The bug
- // was fixed in JB.
- if (mCameraState != PREVIEW_STOPPED) stopPreview();
-
- setDisplayOrientation();
-
- if (!mSnapshotOnIdle) {
- // If the focus mode is continuous autofocus, call cancelAutoFocus to
- // resume it because it may have been paused by autoFocus call.
- if (Util.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) {
- mCameraDevice.cancelAutoFocus();
- }
- mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
- }
- setCameraParameters(UPDATE_PARAM_ALL);
- // Let UI set its expected aspect ratio
- mUI.setPreviewSize(mParameters.getPreviewSize());
- Object st = mUI.getSurfaceTexture();
- if (st != null) {
- mCameraDevice.setPreviewTextureAsync((SurfaceTexture) st);
- }
-
- Log.v(TAG, "startPreview");
- mCameraDevice.startPreviewAsync();
- mFocusManager.onPreviewStarted();
-
- if (mSnapshotOnIdle) {
- mHandler.post(mDoSnapRunnable);
- }
- }
-
- @Override
- public void stopPreview() {
- if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
- Log.v(TAG, "stopPreview");
- mCameraDevice.stopPreview();
- mFaceDetectionStarted = false;
- }
- setCameraState(PREVIEW_STOPPED);
- if (mFocusManager != null) mFocusManager.onPreviewStopped();
- }
-
- @SuppressWarnings("deprecation")
- private void updateCameraParametersInitialize() {
- // Reset preview frame rate to the maximum because it may be lowered by
- // video camera application.
- int[] fpsRange = Util.getMaxPreviewFpsRange(mParameters);
- if (fpsRange.length > 0) {
- mParameters.setPreviewFpsRange(
- fpsRange[Parameters.PREVIEW_FPS_MIN_INDEX],
- fpsRange[Parameters.PREVIEW_FPS_MAX_INDEX]);
- }
-
- mParameters.set(Util.RECORDING_HINT, Util.FALSE);
-
- // Disable video stabilization. Convenience methods not available in API
- // level <= 14
- String vstabSupported = mParameters.get("video-stabilization-supported");
- if ("true".equals(vstabSupported)) {
- mParameters.set("video-stabilization", "false");
- }
- }
-
- private void updateCameraParametersZoom() {
- // Set zoom.
- if (mParameters.isZoomSupported()) {
- mParameters.setZoom(mZoomValue);
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
- private void setAutoExposureLockIfSupported() {
- if (mAeLockSupported) {
- mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock());
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
- private void setAutoWhiteBalanceLockIfSupported() {
- if (mAwbLockSupported) {
- mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock());
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- private void setFocusAreasIfSupported() {
- if (mFocusAreaSupported) {
- mParameters.setFocusAreas(mFocusManager.getFocusAreas());
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- private void setMeteringAreasIfSupported() {
- if (mMeteringAreaSupported) {
- // Use the same area for focus and metering.
- mParameters.setMeteringAreas(mFocusManager.getMeteringAreas());
- }
- }
-
- private void updateCameraParametersPreference() {
- setAutoExposureLockIfSupported();
- setAutoWhiteBalanceLockIfSupported();
- setFocusAreasIfSupported();
- setMeteringAreasIfSupported();
-
- // Set picture size.
- String pictureSize = mPreferences.getString(
- CameraSettings.KEY_PICTURE_SIZE, null);
- if (pictureSize == null) {
- CameraSettings.initialCameraPictureSize(mActivity, mParameters);
- } else {
- List<Size> supported = mParameters.getSupportedPictureSizes();
- CameraSettings.setCameraPictureSize(
- pictureSize, supported, mParameters);
- }
- Size size = mParameters.getPictureSize();
-
- // Set a preview size that is closest to the viewfinder height and has
- // the right aspect ratio.
- List<Size> sizes = mParameters.getSupportedPreviewSizes();
- Size optimalSize = Util.getOptimalPreviewSize(mActivity, sizes,
- (double) size.width / size.height);
- Size original = mParameters.getPreviewSize();
- if (!original.equals(optimalSize)) {
- mParameters.setPreviewSize(optimalSize.width, optimalSize.height);
-
- // Zoom related settings will be changed for different preview
- // sizes, so set and read the parameters to get latest values
- if (mHandler.getLooper() == Looper.myLooper()) {
- // On UI thread only, not when camera starts up
- setupPreview();
- } else {
- mCameraDevice.setParameters(mParameters);
- }
- mParameters = mCameraDevice.getParameters();
- }
- Log.v(TAG, "Preview size is " + optimalSize.width + "x" + optimalSize.height);
-
- // Since changing scene mode may change supported values, set scene mode
- // first. HDR is a scene mode. To promote it in UI, it is stored in a
- // separate preference.
- String hdr = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR,
- mActivity.getString(R.string.pref_camera_hdr_default));
- if (mActivity.getString(R.string.setting_on_value).equals(hdr)) {
- mSceneMode = Util.SCENE_MODE_HDR;
- } else {
- mSceneMode = mPreferences.getString(
- CameraSettings.KEY_SCENE_MODE,
- mActivity.getString(R.string.pref_camera_scenemode_default));
- }
- if (Util.isSupported(mSceneMode, mParameters.getSupportedSceneModes())) {
- if (!mParameters.getSceneMode().equals(mSceneMode)) {
- mParameters.setSceneMode(mSceneMode);
-
- // Setting scene mode will change the settings of flash mode,
- // white balance, and focus mode. Here we read back the
- // parameters, so we can know those settings.
- mCameraDevice.setParameters(mParameters);
- mParameters = mCameraDevice.getParameters();
- }
- } else {
- mSceneMode = mParameters.getSceneMode();
- if (mSceneMode == null) {
- mSceneMode = Parameters.SCENE_MODE_AUTO;
- }
- }
-
- // Set JPEG quality.
- int jpegQuality = CameraProfile.getJpegEncodingQualityParameter(mCameraId,
- CameraProfile.QUALITY_HIGH);
- mParameters.setJpegQuality(jpegQuality);
-
- // For the following settings, we need to check if the settings are
- // still supported by latest driver, if not, ignore the settings.
-
- // Set exposure compensation
- int value = CameraSettings.readExposure(mPreferences);
- int max = mParameters.getMaxExposureCompensation();
- int min = mParameters.getMinExposureCompensation();
- if (value >= min && value <= max) {
- mParameters.setExposureCompensation(value);
- } else {
- Log.w(TAG, "invalid exposure range: " + value);
- }
-
- if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
- // Set flash mode.
- String flashMode = mPreferences.getString(
- CameraSettings.KEY_FLASH_MODE,
- mActivity.getString(R.string.pref_camera_flashmode_default));
- List<String> supportedFlash = mParameters.getSupportedFlashModes();
- if (Util.isSupported(flashMode, supportedFlash)) {
- mParameters.setFlashMode(flashMode);
- } else {
- flashMode = mParameters.getFlashMode();
- if (flashMode == null) {
- flashMode = mActivity.getString(
- R.string.pref_camera_flashmode_no_flash);
- }
- }
-
- // Set white balance parameter.
- String whiteBalance = mPreferences.getString(
- CameraSettings.KEY_WHITE_BALANCE,
- mActivity.getString(R.string.pref_camera_whitebalance_default));
- if (Util.isSupported(whiteBalance,
- mParameters.getSupportedWhiteBalance())) {
- mParameters.setWhiteBalance(whiteBalance);
- } else {
- whiteBalance = mParameters.getWhiteBalance();
- if (whiteBalance == null) {
- whiteBalance = Parameters.WHITE_BALANCE_AUTO;
- }
- }
-
- // Set focus mode.
- mFocusManager.overrideFocusMode(null);
- mParameters.setFocusMode(mFocusManager.getFocusMode());
- } else {
- mFocusManager.overrideFocusMode(mParameters.getFocusMode());
- }
-
- if (mContinousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) {
- updateAutoFocusMoveCallback();
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
- private void updateAutoFocusMoveCallback() {
- if (mParameters.getFocusMode().equals(Util.FOCUS_MODE_CONTINUOUS_PICTURE)) {
- mCameraDevice.setAutoFocusMoveCallback(
- (AutoFocusMoveCallback) mAutoFocusMoveCallback);
- } else {
- mCameraDevice.setAutoFocusMoveCallback(null);
- }
- }
-
- // We separate the parameters into several subsets, so we can update only
- // the subsets actually need updating. The PREFERENCE set needs extra
- // locking because the preference can be changed from GLThread as well.
- private void setCameraParameters(int updateSet) {
- if ((updateSet & UPDATE_PARAM_INITIALIZE) != 0) {
- updateCameraParametersInitialize();
- }
-
- if ((updateSet & UPDATE_PARAM_ZOOM) != 0) {
- updateCameraParametersZoom();
- }
-
- if ((updateSet & UPDATE_PARAM_PREFERENCE) != 0) {
- updateCameraParametersPreference();
- }
-
- mCameraDevice.setParameters(mParameters);
- }
-
- // If the Camera is idle, update the parameters immediately, otherwise
- // accumulate them in mUpdateSet and update later.
- private void setCameraParametersWhenIdle(int additionalUpdateSet) {
- mUpdateSet |= additionalUpdateSet;
- if (mCameraDevice == null) {
- // We will update all the parameters when we open the device, so
- // we don't need to do anything now.
- mUpdateSet = 0;
- return;
- } else if (isCameraIdle()) {
- setCameraParameters(mUpdateSet);
- updateSceneMode();
- mUpdateSet = 0;
- } else {
- if (!mHandler.hasMessages(SET_CAMERA_PARAMETERS_WHEN_IDLE)) {
- mHandler.sendEmptyMessageDelayed(
- SET_CAMERA_PARAMETERS_WHEN_IDLE, 1000);
- }
- }
- }
-
- public boolean isCameraIdle() {
- return (mCameraState == IDLE) ||
- (mCameraState == PREVIEW_STOPPED) ||
- ((mFocusManager != null) && mFocusManager.isFocusCompleted()
- && (mCameraState != SWITCHING_CAMERA));
- }
-
- public boolean isImageCaptureIntent() {
- String action = mActivity.getIntent().getAction();
- return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)
- || ActivityBase.ACTION_IMAGE_CAPTURE_SECURE.equals(action));
- }
-
- private void setupCaptureParams() {
- Bundle myExtras = mActivity.getIntent().getExtras();
- if (myExtras != null) {
- mSaveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
- mCropValue = myExtras.getString("crop");
- }
- }
-
- @Override
- public void onSharedPreferenceChanged() {
- // ignore the events after "onPause()"
- if (mPaused) return;
-
- boolean recordLocation = RecordLocationPreference.get(
- mPreferences, mContentResolver);
- mLocationManager.recordLocation(recordLocation);
-
- setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE);
- mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, mPreferences);
- }
-
- @Override
- public void onCameraPickerClicked(int cameraId) {
- if (mPaused || mPendingSwitchCameraId != -1) return;
-
- mPendingSwitchCameraId = cameraId;
-
- Log.v(TAG, "Start to switch camera. cameraId=" + cameraId);
- // We need to keep a preview frame for the animation before
- // releasing the camera. This will trigger onPreviewTextureCopied.
- //TODO: Need to animate the camera switch
- switchCamera();
- }
-
- // Preview texture has been copied. Now camera can be released and the
- // animation can be started.
- @Override
- public void onPreviewTextureCopied() {
- mHandler.sendEmptyMessage(SWITCH_CAMERA);
- }
-
- @Override
- public void onCaptureTextureCopied() {
- }
-
- @Override
- public void onUserInteraction() {
- if (!mActivity.isFinishing()) keepScreenOnAwhile();
- }
-
- private void resetScreenOn() {
- mHandler.removeMessages(CLEAR_SCREEN_DELAY);
- mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
-
- private void keepScreenOnAwhile() {
- mHandler.removeMessages(CLEAR_SCREEN_DELAY);
- mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
- }
-
- @Override
- public void onOverriddenPreferencesClicked() {
- if (mPaused) return;
- mUI.showPreferencesToast();
- }
-
- private void showTapToFocusToast() {
- // TODO: Use a toast?
- new RotateTextToast(mActivity, R.string.tap_to_focus, 0).show();
- // Clear the preference.
- Editor editor = mPreferences.edit();
- editor.putBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, false);
- editor.apply();
- }
-
- private void initializeCapabilities() {
- mInitialParams = mCameraDevice.getParameters();
- mFocusAreaSupported = Util.isFocusAreaSupported(mInitialParams);
- mMeteringAreaSupported = Util.isMeteringAreaSupported(mInitialParams);
- mAeLockSupported = Util.isAutoExposureLockSupported(mInitialParams);
- mAwbLockSupported = Util.isAutoWhiteBalanceLockSupported(mInitialParams);
- mContinousFocusSupported = mInitialParams.getSupportedFocusModes().contains(
- Util.FOCUS_MODE_CONTINUOUS_PICTURE);
- }
-
- @Override
- public void onCountDownFinished() {
- mSnapshotOnIdle = false;
- mFocusManager.doSnap();
- mFocusManager.onShutterUp();
- }
-
- @Override
- public boolean needsSwitcher() {
- return !mIsImageCaptureIntent;
- }
-
- @Override
- public boolean needsPieMenu() {
- return true;
- }
-
- @Override
- public void onShowSwitcherPopup() {
- mUI.onShowSwitcherPopup();
- }
-
- @Override
- public int onZoomChanged(int index) {
- // Not useful to change zoom value when the activity is paused.
- if (mPaused) return index;
- mZoomValue = index;
- if (mParameters == null || mCameraDevice == null) return index;
- // Set zoom parameters asynchronously
- mParameters.setZoom(mZoomValue);
- mCameraDevice.setParameters(mParameters);
- Parameters p = mCameraDevice.getParameters();
- if (p != null) return p.getZoom();
- return index;
- }
-
- @Override
- public int getCameraState() {
- return mCameraState;
- }
-
- @Override
- public void onQueueStatus(boolean full) {
- mUI.enableShutter(!full);
- }
-
- @Override
- public void onMediaSaveServiceConnected(MediaSaveService s) {
- // We set the listener only when both service and shutterbutton
- // are initialized.
- if (mFirstTimeInitialized) {
- s.setListener(this);
- }
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- int type = event.sensor.getType();
- float[] data;
- if (type == Sensor.TYPE_ACCELEROMETER) {
- data = mGData;
- } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
- data = mMData;
- } else {
- // we should not be here.
- return;
- }
- for (int i = 0; i < 3 ; i++) {
- data[i] = event.values[i];
- }
- float[] orientation = new float[3];
- SensorManager.getRotationMatrix(mR, null, mGData, mMData);
- SensorManager.getOrientation(mR, orientation);
- mHeading = (int) (orientation[0] * 180f / Math.PI) % 360;
- if (mHeading < 0) {
- mHeading += 360;
- }
- }
-
- @Override
- public void onSwitchMode(boolean toCamera) {
- mUI.onSwitchMode(toCamera);
- }
-
-/* Below is no longer needed, except to get rid of compile error
- * TODO: Remove these
- */
-
- // TODO: Delete this function after old camera code is removed
- @Override
- public void onRestorePreferencesClicked() {}
-
-}