Camera2: Added pause button in Camcorder

- Added pause button in camcorder app.so that user pause
  recording and resume later which results in a single
  recorded clip.
CRs-Fixed: 587051

Change-Id: I2a7d8af7fcea74fe8af62c44119c3c1fa0c13e85
diff --git a/src/com/android/camera/PauseButton.java b/src/com/android/camera/PauseButton.java
new file mode 100644
index 0000000..a785050
--- /dev/null
+++ b/src/com/android/camera/PauseButton.java
@@ -0,0 +1,82 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package com.android.camera;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.view.MotionEvent;
+import android.view.View;
+import android.util.Log;
+
+/**
+ * A button designed to be used for the on-screen recording
+ * pausing-continue button.
+ */
+public class PauseButton extends ImageView {
+
+    public interface OnPauseButtonListener {
+        void onButtonPause();
+        void onButtonContinue();
+    }
+
+    public PauseButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setClickable(true);
+        setSelected(false);
+    }
+
+    public void setPaused(boolean paused) {
+        setSelected(paused);
+    }
+
+    @Override
+    public boolean performClick() {
+        boolean result = super.performClick();
+        if (isSelected()) {
+            setSelected(false);
+            if (mListener != null && getVisibility() == View.VISIBLE) {
+                mListener.onButtonContinue();
+            }
+        } else {
+            setSelected(true);
+            if (mListener != null && getVisibility() == View.VISIBLE) {
+                mListener.onButtonPause();
+            }
+        }
+        return result;
+    }
+
+    public void setOnPauseButtonListener(OnPauseButtonListener listener) {
+        mListener = listener;
+    }
+
+    private OnPauseButtonListener mListener;
+}
diff --git a/src/com/android/camera/VideoController.java b/src/com/android/camera/VideoController.java
index e846548..cf694a3 100644
--- a/src/com/android/camera/VideoController.java
+++ b/src/com/android/camera/VideoController.java
@@ -19,8 +19,9 @@
 import android.view.View;
 
 import com.android.camera.ShutterButton.OnShutterButtonListener;
+import com.android.camera.PauseButton.OnPauseButtonListener;
 
-public interface VideoController extends OnShutterButtonListener {
+public interface VideoController extends OnShutterButtonListener, OnPauseButtonListener {
 
     public void onReviewDoneClicked(View view);
     public void onReviewCancelClicked(View viwe);
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index a79bc25..f2562b1 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -129,7 +129,9 @@
 
     private boolean mSwitchingCamera;
     private boolean mMediaRecorderRecording = false;
+    private boolean mMediaRecorderPausing = false;
     private long mRecordingStartTime;
+    private long mRecordingTotalTime;
     private boolean mRecordingTimeCountsDown = false;
     private long mOnResumeTime;
     // The video file that the hardware camera is about to record into
@@ -460,6 +462,7 @@
     // Preview area is touched. Take a picture.
     @Override
     public void onSingleTapUp(View view, int x, int y) {
+        if (mMediaRecorderPausing) return;
         takeASnapshot();
     }
 
@@ -1329,7 +1332,7 @@
 
     private void saveVideo() {
         if (mVideoFileDescriptor == null) {
-            long duration = SystemClock.uptimeMillis() - mRecordingStartTime;
+            long duration = SystemClock.uptimeMillis() - mRecordingStartTime + mRecordingTotalTime;
             if (duration > 0) {
                 if (mCaptureTimeLapse) {
                     duration = getTimeLapseVideoLength(duration);
@@ -1491,7 +1494,10 @@
         mUI.enableCameraControls(false);
 
         mMediaRecorderRecording = true;
+        mMediaRecorderPausing = false;
+        mUI.resetPauseButton();
         mOrientationManager.lockOrientation();
+        mRecordingTotalTime = 0L;
         mRecordingStartTime = SystemClock.uptimeMillis();
         mUI.showRecordingUI(true);
 
@@ -1539,6 +1545,21 @@
         mUI.showTimeLapseUI(false);
     }
 
+    private void pauseVideoRecording() {
+        Log.v(TAG, "pauseVideoRecording");
+        mMediaRecorderPausing = true;
+        mRecordingTotalTime += SystemClock.uptimeMillis() - mRecordingStartTime;
+        mMediaRecorder.pause();
+    }
+
+    private void resumeVideoRecording() {
+        Log.v(TAG, "resumeVideoRecording");
+        mMediaRecorderPausing = false;
+        mRecordingStartTime = SystemClock.uptimeMillis();
+        updateRecordingTime();
+        mMediaRecorder.start();
+    }
+
     private boolean stopVideoRecording() {
         Log.v(TAG, "stopVideoRecording");
         mStopRecPending = true;
@@ -1616,7 +1637,7 @@
         UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
                 fail ? UsageStatistics.ACTION_CAPTURE_FAIL :
                     UsageStatistics.ACTION_CAPTURE_DONE, "Video",
-                    SystemClock.uptimeMillis() - mRecordingStartTime);
+                    SystemClock.uptimeMillis() - mRecordingStartTime + mRecordingTotalTime);
         mStopRecPending = false;
         return fail;
     }
@@ -1693,8 +1714,12 @@
         if (!mMediaRecorderRecording) {
             return;
         }
+        if (mMediaRecorderPausing) {
+            return;
+        }
+
         long now = SystemClock.uptimeMillis();
-        long delta = now - mRecordingStartTime;
+        long delta = now - mRecordingStartTime + mRecordingTotalTime;
 
         // Starting a minute before reaching the max duration
         // limit, we'll countdown the remaining time instead.
@@ -2227,4 +2252,15 @@
     public void onPreviewUIDestroyed() {
         stopPreview();
     }
+
+     @Override
+    public void onButtonPause() {
+        pauseVideoRecording();
+    }
+
+    @Override
+    public void onButtonContinue() {
+        resumeVideoRecording();
+    }
+
 }
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index bb270b7..8ea7091 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -49,6 +49,7 @@
 import com.android.camera.ui.PieRenderer;
 import com.android.camera.ui.RenderOverlay;
 import com.android.camera.ui.RotateLayout;
+import com.android.camera.PauseButton.OnPauseButtonListener;
 import com.android.camera.ui.ZoomRenderer;
 import com.android.camera.util.CameraUtil;
 import com.android.camera2.R;
@@ -58,7 +59,8 @@
 public class VideoUI implements PieRenderer.PieListener,
         PreviewGestures.SingleTapListener,
         CameraRootView.MyDisplayListener,
-        SurfaceTextureListener, SurfaceHolder.Callback {
+        SurfaceTextureListener, SurfaceHolder.Callback,
+        PauseButton.OnPauseButtonListener {
     private static final String TAG = "CAM_VideoUI";
     private static final int UPDATE_TRANSFORM_MATRIX = 1;
     // module fields
@@ -72,6 +74,7 @@
     private View mReviewDoneButton;
     private View mReviewPlayButton;
     private ShutterButton mShutterButton;
+    private PauseButton mPauseButton;
     private ModuleSwitcher mSwitcher;
     private TextView mRecordingTimeView;
     private LinearLayout mLabelsLinearLayout;
@@ -192,6 +195,7 @@
         initializeMiscControls();
         initializeControlByIntent();
         initializeOverlay();
+        initializePauseButton();
         mAnimationManager = new AnimationManager();
         mOrientationResize = false;
         mPrevOrientationResize = false;
@@ -514,6 +518,11 @@
         mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels);
     }
 
+    private void initializePauseButton() {
+        mPauseButton = (PauseButton) mRootView.findViewById(R.id.video_pause);
+        mPauseButton.setOnPauseButtonListener(this);
+    }
+
     public void updateOnScreenIndicators(Parameters param, ComboPreferences prefs) {
       mOnScreenIndicators.updateFlashOnScreenIndicator(param.getFlashMode());
       boolean location = RecordLocationPreference.get(
@@ -631,12 +640,14 @@
             hideSwitcher();
             mRecordingTimeView.setText("");
             mRecordingTimeView.setVisibility(View.VISIBLE);
+            mPauseButton.setVisibility(View.VISIBLE);
         } else {
             mShutterButton.setImageResource(R.drawable.btn_new_shutter_video);
             if (!mController.isVideoCaptureIntent()) {
                 showSwitcher();
             }
             mRecordingTimeView.setVisibility(View.GONE);
+            mPauseButton.setVisibility(View.GONE);
         }
     }
 
@@ -811,4 +822,24 @@
         Log.v(TAG, "Surface destroyed");
         mController.stopPreview();
     }
+
+     @Override
+    public void onButtonPause() {
+        mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
+            R.drawable.ic_pausing_indicator, 0, 0, 0);
+                mController.onButtonPause();
+    }
+
+    @Override
+    public void onButtonContinue() {
+        mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
+            R.drawable.ic_recording_indicator, 0, 0, 0);
+        mController.onButtonContinue();
+    }
+
+    public void resetPauseButton() {
+        mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
+            R.drawable.ic_recording_indicator, 0, 0, 0);
+        mPauseButton.setPaused(false);
+    }
 }