OSDN Git Service

Refactor UsageStatistic so it can be disabled more easily.
[android-x86/packages-apps-Camera2.git] / src / com / android / camera / VideoModule.java
index 94b0048..5003c96 100644 (file)
@@ -26,6 +26,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Bitmap;
+import android.graphics.Point;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.Parameters;
@@ -45,7 +46,6 @@ import android.os.SystemClock;
 import android.provider.MediaStore;
 import android.provider.MediaStore.MediaColumns;
 import android.provider.MediaStore.Video;
-import android.util.Log;
 import android.view.KeyEvent;
 import android.view.OrientationEventListener;
 import android.view.View;
@@ -60,13 +60,13 @@ import com.android.camera.app.LocationManager;
 import com.android.camera.app.MediaSaver;
 import com.android.camera.app.MemoryManager;
 import com.android.camera.app.MemoryManager.MemoryListener;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.hardware.HardwareSpec;
 import com.android.camera.hardware.HardwareSpecImpl;
 import com.android.camera.module.ModuleController;
 import com.android.camera.settings.SettingsManager;
 import com.android.camera.settings.SettingsUtil;
-import com.android.camera.util.AccessibilityUtils;
 import com.android.camera.util.ApiHelper;
 import com.android.camera.util.CameraUtil;
 import com.android.camera.util.UsageStatistics;
@@ -87,7 +87,7 @@ public class VideoModule extends CameraModule
     MediaRecorder.OnErrorListener,
     MediaRecorder.OnInfoListener, FocusOverlayManager.Listener {
 
-    private static final String TAG = "VideoModule";
+    private static final Log.Tag TAG = new Log.Tag("VideoModule");
 
     // Messages defined for the UI thread handler.
     private static final int MSG_CHECK_DISPLAY_ROTATION = 4;
@@ -109,6 +109,11 @@ public class VideoModule extends CameraModule
     // module fields
     private CameraActivity mActivity;
     private boolean mPaused;
+
+    // if, during and intent capture, the activity is paused (e.g. when app switching or reviewing a
+    // shot video), we don't want the bottom bar intent ui to reset to the capture button
+    private boolean mDontResetIntentUiOnResume;
+
     private int mCameraId;
     private Parameters mParameters;
 
@@ -149,9 +154,9 @@ public class VideoModule extends CameraModule
     private int mMaxVideoDurationInMs;
 
     // Time Lapse parameters.
-    private boolean mCaptureTimeLapse = false;
+    private final boolean mCaptureTimeLapse = false;
     // Default 0. If it is larger than 0, the camcorder is in time lapse mode.
-    private int mTimeBetweenTimeLapseFrameCaptureMs = 0;
+    private final int mTimeBetweenTimeLapseFrameCaptureMs = 0;
 
     boolean mPreviewing = false; // True if preview is started.
     // The display rotation in degrees. This is only valid when mPreviewing is
@@ -360,13 +365,17 @@ public class VideoModule extends CameraModule
 
     private void initializeControlByIntent() {
         if (isVideoCaptureIntent()) {
-            mActivity.getCameraAppUI().transitionToIntentCaptureLayout();
+            if (!mDontResetIntentUiOnResume) {
+                mActivity.getCameraAppUI().transitionToIntentCaptureLayout();
+            }
+            // reset the flag
+            mDontResetIntentUiOnResume = false;
         }
     }
 
     @Override
     public void onSingleTapUp(View view, int x, int y) {
-        if (mPaused || mCameraDevice == null) {
+        if (mMediaRecorderRecording || mPaused || mCameraDevice == null) {
             return;
         }
         // Check if metering area or focus area is supported.
@@ -397,8 +406,8 @@ public class VideoModule extends CameraModule
                     null, null, null, new JpegPictureCallback(loc));
             showVideoSnapshotUI(true);
             mSnapshotInProgress = true;
-            UsageStatistics.captureEvent(eventprotos.NavigationChange.Mode.VIDEO_STILL,
-                    null, null);
+            UsageStatistics.instance().captureEvent(
+                    eventprotos.NavigationChange.Mode.VIDEO_STILL, null, null, null);
         }
     }
 
@@ -417,6 +426,14 @@ public class VideoModule extends CameraModule
     }
 
     /**
+     * @return Whether the currently active camera is front-facing.
+     */
+    private boolean isCameraFrontFacing() {
+        CameraInfo info = mAppController.getCameraProvider().getCameraInfo()[mCameraId];
+        return info.facing == CameraInfo.CAMERA_FACING_FRONT;
+    }
+
+    /**
      * The focus manager gets initialized after camera is available.
      */
     private void initializeFocusManager() {
@@ -426,8 +443,7 @@ public class VideoModule extends CameraModule
         if (mFocusManager != null) {
             mFocusManager.removeMessages();
         } else {
-            CameraInfo info = mAppController.getCameraProvider().getCameraInfo()[mCameraId];
-            mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
+            mMirror = isCameraFrontFacing();
             String[] defaultFocusModes = mActivity.getResources().getStringArray(
                     R.array.pref_camera_focusmode_default_array);
             mFocusManager = new FocusOverlayManager(mActivity.getSettingsManager(),
@@ -495,12 +511,16 @@ public class VideoModule extends CameraModule
     private final View.OnClickListener mReviewCallback = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            mActivity.getCameraAppUI().transitionToIntentCaptureLayout();
             onReviewPlayClicked(v);
         }
     };
 
     @Override
+    public void hardResetSettings(SettingsManager settingsManager) {
+        // VideoModule does not need to hard reset any settings.
+    }
+
+    @Override
     public HardwareSpec getHardwareSpec() {
         return (mParameters != null ? new HardwareSpecImpl(mParameters) : null);
     }
@@ -514,7 +534,7 @@ public class VideoModule extends CameraModule
         bottomBarSpec.enableTorchFlash = true;
         bottomBarSpec.flashCallback = mFlashCallback;
         bottomBarSpec.hideHdr = true;
-        bottomBarSpec.hideGridLines = true;
+        bottomBarSpec.enableGridLines = true;
 
         if (isVideoCaptureIntent()) {
             bottomBarSpec.showCancel = true;
@@ -652,10 +672,15 @@ public class VideoModule extends CameraModule
         // The preference stores values from ListPreference and is thus string type for all values.
         // We need to convert it to int manually.
         SettingsManager settingsManager = mActivity.getSettingsManager();
-        if (!settingsManager.isSet(SettingsManager.SETTING_VIDEO_QUALITY)) {
-            settingsManager.setDefault(SettingsManager.SETTING_VIDEO_QUALITY);
+        if (!settingsManager.isSet(SettingsManager.SETTING_VIDEO_QUALITY_BACK)) {
+            settingsManager.setDefault(SettingsManager.SETTING_VIDEO_QUALITY_BACK);
+        }
+        if (!settingsManager.isSet(SettingsManager.SETTING_VIDEO_QUALITY_FRONT)) {
+            settingsManager.setDefault(SettingsManager.SETTING_VIDEO_QUALITY_FRONT);
         }
-        String videoQuality = settingsManager.get(SettingsManager.SETTING_VIDEO_QUALITY);
+        String videoQuality = settingsManager
+                .get(isCameraFrontFacing() ? SettingsManager.SETTING_VIDEO_QUALITY_FRONT
+                        : SettingsManager.SETTING_VIDEO_QUALITY_BACK);
         int quality = SettingsUtil.getVideoQuality(videoQuality, mCameraId);
         Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
 
@@ -681,7 +706,8 @@ public class VideoModule extends CameraModule
             mMaxVideoDurationInMs = CameraSettings.getMaxVideoDuration(mActivity);
         }
 
-        // Read time lapse recording interval.
+        // TODO: Uncomment this block to re-enable time-lapse.
+        /* // Read time lapse recording interval.
         String frameIntervalStr = settingsManager.get(
             SettingsManager.SETTING_VIDEO_TIME_LAPSE_FRAME_INTERVAL);
         mTimeBetweenTimeLapseFrameCaptureMs = Integer.parseInt(frameIntervalStr);
@@ -689,48 +715,70 @@ public class VideoModule extends CameraModule
         // TODO: This should be checked instead directly +1000.
         if (mCaptureTimeLapse) {
             quality += 1000;
-        }
+        } */
 
         // If quality is not supported, request QUALITY_HIGH which is always supported.
         if (CamcorderProfile.hasProfile(mCameraId, quality) == false) {
             quality = CamcorderProfile.QUALITY_HIGH;
         }
         mProfile = CamcorderProfile.get(mCameraId, quality);
-        getDesiredPreviewSize();
         mPreferenceRead = true;
-    }
-
-    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
-    private void getDesiredPreviewSize() {
         if (mCameraDevice == null) {
             return;
         }
         mParameters = mCameraDevice.getParameters();
-        if (mParameters.getSupportedVideoSizes() == null) {
-            mDesiredPreviewWidth = mProfile.videoFrameWidth;
-            mDesiredPreviewHeight = mProfile.videoFrameHeight;
-        } else { // Driver supports separates outputs for preview and video.
-            List<Size> sizes = mParameters.getSupportedPreviewSizes();
-            Size preferred = mParameters.getPreferredPreviewSizeForVideo();
-            int product = preferred.width * preferred.height;
-            Iterator<Size> it = sizes.iterator();
-            // Remove the preview sizes that are not preferred.
-            while (it.hasNext()) {
-                Size size = it.next();
-                if (size.width * size.height > product) {
-                    it.remove();
-                }
-            }
-            Size optimalSize = CameraUtil.getOptimalPreviewSize(mActivity, sizes,
-                    (double) mProfile.videoFrameWidth / mProfile.videoFrameHeight);
-            mDesiredPreviewWidth = optimalSize.width;
-            mDesiredPreviewHeight = optimalSize.height;
-        }
+        Point desiredPreviewSize = getDesiredPreviewSize(mAppController.getAndroidContext(),
+                mParameters, mProfile, mUI.getPreviewScreenSize());
+        mDesiredPreviewWidth = desiredPreviewSize.x;
+        mDesiredPreviewHeight = desiredPreviewSize.y;
         mUI.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight);
         Log.v(TAG, "mDesiredPreviewWidth=" + mDesiredPreviewWidth +
                 ". mDesiredPreviewHeight=" + mDesiredPreviewHeight);
     }
 
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+    /**
+     * Calculates the preview size and stores it in mDesiredPreviewWidth and
+     * mDesiredPreviewHeight. This function checks {@link
+     * android.hardware.Camera.Parameters#getPreferredPreviewSizeForVideo()}
+     * but also considers the current preview area size on screen and make sure
+     * the final preview size will not be smaller than 1/2 of the current
+     * on screen preview area in terms of their short sides.
+     *
+     * @return The preferred preview size or {@code null} if the camera is not
+     *         opened yet.
+     */
+    private static Point getDesiredPreviewSize(Context context, Parameters parameters,
+            CamcorderProfile profile, Point previewScreenSize) {
+        if (parameters.getSupportedVideoSizes() == null) {
+            // Driver doesn't support separate outputs for preview and video.
+            return new Point(profile.videoFrameWidth, profile.videoFrameHeight);
+        }
+
+        final int previewScreenShortSide = (previewScreenSize.x < previewScreenSize.y ?
+                previewScreenSize.x : previewScreenSize.y);
+        List<Size> sizes = parameters.getSupportedPreviewSizes();
+        Size preferred = parameters.getPreferredPreviewSizeForVideo();
+        final int preferredPreviewSizeShortSide = (preferred.width < preferred.height ?
+                preferred.width : preferred.height);
+        if (preferredPreviewSizeShortSide * 2 < previewScreenShortSide) {
+            preferred.width = profile.videoFrameWidth;
+            preferred.height = profile.videoFrameHeight;
+        }
+        int product = preferred.width * preferred.height;
+        Iterator<Size> it = sizes.iterator();
+        // Remove the preview sizes that are not preferred.
+        while (it.hasNext()) {
+            Size size = it.next();
+            if (size.width * size.height > product) {
+                it.remove();
+            }
+        }
+        Size optimalSize = CameraUtil.getOptimalPreviewSize(context, sizes,
+                (double) profile.videoFrameWidth / profile.videoFrameHeight);
+        return new Point(optimalSize.width, optimalSize.height);
+    }
+
     private void resizeForPreviewAspectRatio() {
         mUI.setAspectRatio((float) mProfile.videoFrameWidth / mProfile.videoFrameHeight);
     }
@@ -801,7 +849,7 @@ public class VideoModule extends CameraModule
             return;
         }
 
-        mCameraDevice.setErrorCallback(mErrorCallback);
+        mCameraDevice.setErrorCallback(mHandler, mErrorCallback);
         if (mPreviewing == true) {
             stopPreview();
         }
@@ -863,7 +911,7 @@ public class VideoModule extends CameraModule
             return;
         }
         mCameraDevice.setZoomChangeListener(null);
-        mCameraDevice.setErrorCallback(null);
+        mCameraDevice.setErrorCallback(null, null);
         mActivity.getCameraProvider().releaseCamera(mCameraDevice.getCameraId());
         mCameraDevice = null;
         mPreviewing = false;
@@ -899,18 +947,14 @@ public class VideoModule extends CameraModule
                     mUI.clickShutter();
                     return true;
                 }
-                break;
             case KeyEvent.KEYCODE_DPAD_CENTER:
                 if (event.getRepeatCount() == 0) {
                     mUI.clickShutter();
                     return true;
                 }
-                break;
             case KeyEvent.KEYCODE_MENU:
-                if (mMediaRecorderRecording) {
-                    return true;
-                }
-                break;
+                // Consume menu button presses during capture.
+                return mMediaRecorderRecording;
         }
         return false;
     }
@@ -921,6 +965,9 @@ public class VideoModule extends CameraModule
             case KeyEvent.KEYCODE_CAMERA:
                 mUI.pressShutter(false);
                 return true;
+            case KeyEvent.KEYCODE_MENU:
+                // Consume menu button presses during capture.
+                return mMediaRecorderRecording;
         }
         return false;
     }
@@ -1034,7 +1081,7 @@ public class VideoModule extends CameraModule
         int rotation = 0;
         if (mOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
             CameraInfo info = mActivity.getCameraProvider().getCameraInfo()[mCameraId];
-            if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
+            if (isCameraFrontFacing()) {
                 rotation = (info.orientation - mOrientation + 360) % 360;
             } else {  // back-facing camera
                 rotation = (info.orientation + mOrientation) % 360;
@@ -1092,6 +1139,8 @@ public class VideoModule extends CameraModule
         mCurrentVideoValues.put(MediaColumns.DATE_MODIFIED, dateTaken / 1000);
         mCurrentVideoValues.put(Video.Media.MIME_TYPE, mime);
         mCurrentVideoValues.put(Video.Media.DATA, path);
+        mCurrentVideoValues.put(Video.Media.WIDTH, mProfile.videoFrameWidth);
+        mCurrentVideoValues.put(Video.Media.HEIGHT, mProfile.videoFrameHeight);
         mCurrentVideoValues.put(Video.Media.RESOLUTION,
                 Integer.toString(mProfile.videoFrameWidth) + "x" +
                 Integer.toString(mProfile.videoFrameHeight));
@@ -1177,11 +1226,7 @@ public class VideoModule extends CameraModule
         mUI.cancelAnimations();
         mUI.setSwipingEnabled(false);
         mUI.showFocusUI(false);
-
-        // A special case of mode options closing: during capture it should
-        // not be possible to change mode state.
-        mAppController.getCameraAppUI().hideModeOptions();
-        mAppController.getCameraAppUI().animateBottomBarToCircle(R.drawable.ic_stop);
+        mUI.showVideoRecordingHints(false);
 
         mActivity.updateStorageSpaceAndHint();
         if (mActivity.getStorageSpaceBytes() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
@@ -1212,11 +1257,6 @@ public class VideoModule extends CameraModule
         }
         mAppController.getCameraAppUI().setSwipeEnabled(false);
 
-        // Make sure the video recording has started before announcing
-        // this in accessibility.
-        AccessibilityUtils.makeAnnouncement(mUI.getShutterButton(),
-                mActivity.getString(R.string.video_recording_started));
-
         // The parameters might have been altered by MediaRecorder already.
         // We need to force mCameraDevice to refresh before getting it.
         mCameraDevice.refreshParameters();
@@ -1229,6 +1269,11 @@ public class VideoModule extends CameraModule
         mMediaRecorderRecording = true;
         mActivity.lockOrientation();
         mRecordingStartTime = SystemClock.uptimeMillis();
+
+        // A special case of mode options closing: during capture it should
+        // not be possible to change mode state.
+        mAppController.getCameraAppUI().hideModeOptions();
+        mAppController.getCameraAppUI().animateBottomBarToVideoStop(R.drawable.ic_stop);
         mUI.showRecordingUI(true);
 
         setFocusParameters();
@@ -1255,9 +1300,7 @@ public class VideoModule extends CameraModule
         if (bitmap != null) {
             // MetadataRetriever already rotates the thumbnail. We should rotate
             // it to match the UI orientation (and mirror if it is front-facing camera).
-            CameraInfo[] info = mActivity.getCameraProvider().getCameraInfo();
-            boolean mirror = (info[mCameraId].facing == CameraInfo.CAMERA_FACING_FRONT);
-            bitmap = CameraUtil.rotateAndMirror(bitmap, 0, mirror);
+            bitmap = CameraUtil.rotateAndMirror(bitmap, 0, isCameraFrontFacing());
         }
         return bitmap;
     }
@@ -1276,9 +1319,7 @@ public class VideoModule extends CameraModule
         Log.v(TAG, "stopVideoRecording");
         mUI.setSwipingEnabled(true);
         mUI.showFocusUI(true);
-
-        mAppController.getCameraAppUI().showModeOptions();
-        mAppController.getCameraAppUI().animateBottomBarToFullSize(mShutterIconId);
+        mUI.showVideoRecordingHints(true);
 
         boolean fail = false;
         if (mMediaRecorderRecording) {
@@ -1293,11 +1334,12 @@ public class VideoModule extends CameraModule
                 Log.v(TAG, "stopVideoRecording: Setting current video filename: "
                         + mCurrentVideoFilename);
                 float duration = (SystemClock.uptimeMillis() - mRecordingStartTime) / 1000;
-                UsageStatistics.captureEvent(eventprotos.NavigationChange.Mode.VIDEO_CAPTURE,
-                        mCurrentVideoFilename, mParameters, duration);
-                AccessibilityUtils.makeAnnouncement(mUI.getShutterButton(),
-                        mActivity.getAndroidContext().getString(R.string
-                                .video_recording_stopped));
+                String statisticFilename = (mCurrentVideoFilename == null
+                        ? "INTENT"
+                        : mCurrentVideoFilename);
+                UsageStatistics.instance().captureEvent(
+                        eventprotos.NavigationChange.Mode.VIDEO_CAPTURE, statisticFilename,
+                        mParameters, duration);
             } catch (RuntimeException e) {
                 Log.e(TAG, "stop fail",  e);
                 if (mVideoFilename != null) {
@@ -1331,6 +1373,9 @@ public class VideoModule extends CameraModule
         }
         // release media recorder
         releaseMediaRecorder();
+
+        mAppController.getCameraAppUI().showModeOptions();
+        mAppController.getCameraAppUI().animateBottomBarToFullSize(mShutterIconId);
         if (!mPaused) {
             setFocusParameters();
             mCameraDevice.lock();
@@ -1455,7 +1500,6 @@ public class VideoModule extends CameraModule
         SettingsManager settingsManager = mActivity.getSettingsManager();
 
         mParameters.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight);
-        mParameters.set("video-size", mProfile.videoFrameWidth+"x"+mProfile.videoFrameHeight);
         int[] fpsRange = CameraUtil.getMaxPreviewFpsRange(mParameters);
         if (fpsRange.length > 0) {
             mParameters.setPreviewFpsRange(
@@ -1467,18 +1511,6 @@ public class VideoModule extends CameraModule
 
         enableTorchMode(settingsManager.isCameraBackFacing());
 
-        // Set white balance parameter.
-        String whiteBalance = settingsManager.get(SettingsManager.SETTING_WHITE_BALANCE);
-        if (isSupported(whiteBalance,
-                mParameters.getSupportedWhiteBalance())) {
-            mParameters.setWhiteBalance(whiteBalance);
-        } else {
-            whiteBalance = mParameters.getWhiteBalance();
-            if (whiteBalance == null) {
-                whiteBalance = Parameters.WHITE_BALANCE_AUTO;
-            }
-        }
-
         // Set zoom.
         if (mParameters.isZoomSupported()) {
             mParameters.setZoom(mZoomValue);
@@ -1549,6 +1581,10 @@ public class VideoModule extends CameraModule
 
     @Override
     public void resume() {
+        if (isVideoCaptureIntent()) {
+            mDontResetIntentUiOnResume = mPaused;
+        }
+
         mPaused = false;
         installIntentFilter();
         mUI.enableShutter(false);
@@ -1570,15 +1606,12 @@ public class VideoModule extends CameraModule
             mAppController.addPreviewAreaSizeChangedListener(mFocusManager);
         }
 
-        // Initialize location service.
-        mActivity.syncLocationManagerSetting();
-
         if (mPreviewing) {
             mOnResumeTime = SystemClock.uptimeMillis();
             mHandler.sendEmptyMessageDelayed(MSG_CHECK_DISPLAY_ROTATION, 100);
         }
 
-        UsageStatistics.changeScreen(eventprotos.NavigationChange.Mode.VIDEO_CAPTURE,
+        UsageStatistics.instance().changeScreen(eventprotos.NavigationChange.Mode.VIDEO_CAPTURE,
                 eventprotos.CameraEvent.InteractionCause.BUTTON);
         getServices().getMemoryManager().addListener(this);
     }
@@ -1610,10 +1643,6 @@ public class VideoModule extends CameraModule
             mReceiver = null;
         }
 
-        if (mLocationManager != null) {
-            mLocationManager.recordLocation(false);
-        }
-
         mHandler.removeMessages(MSG_CHECK_DISPLAY_ROTATION);
         mHandler.removeMessages(MSG_SWITCH_CAMERA);
         mHandler.removeMessages(MSG_SWITCH_CAMERA_START_ANIMATION);
@@ -1655,8 +1684,7 @@ public class VideoModule extends CameraModule
         closeCamera();
         requestCamera(mCameraId);
 
-        CameraInfo info = mActivity.getCameraProvider().getCameraInfo()[mCameraId];
-        mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
+        mMirror = isCameraFrontFacing();
         if (mFocusManager != null) {
             mFocusManager.setMirror(mMirror);
         }