Merge "SnapdragonCamera:Fix getting location without permission" into camera.lnx.1.0-dev.1.0
diff --git a/assets/dependency.json b/assets/dependency.json
index 6c8584c..cbc9658 100644
--- a/assets/dependency.json
+++ b/assets/dependency.json
@@ -86,6 +86,14 @@
     "103":
     {"pref_camera2_coloreffect_key":"0"}
     ,
+    "104":
+    {"pref_camera2_coloreffect_key":"0"}
+    ,
+    "105":
+    {"pref_camera2_flashmode_key":"off",
+      "pref_camera2_coloreffect_key":"0",
+      "pref_camera2_longshot_key":"off"}
+    ,
     "106":
     {"pref_camera2_coloreffect_key":"0"}
     ,
@@ -95,13 +103,8 @@
     "108":
     {"pref_camera2_coloreffect_key":"0"}
     ,
-    "104":
+    "109":
     {"pref_camera2_coloreffect_key":"0"}
-    ,
-    "105":
-      {"pref_camera2_flashmode_key":"off",
-        "pref_camera2_coloreffect_key":"0",
-        "pref_camera2_longshot_key":"off"}
   },
   "pref_camera2_clearsight_key":
   {
diff --git a/res/layout/bestpicture_page.xml b/res/layout/bestpicture_page.xml
old mode 100644
new mode 100755
index d6b6022..5a1b604
--- a/res/layout/bestpicture_page.xml
+++ b/res/layout/bestpicture_page.xml
@@ -34,9 +34,9 @@
     <ImageView
         android:id="@+id/image_view"
         android:adjustViewBounds="true"
-        android:scaleType="fitXY"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:scaleType="fitCenter"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
         android:layout_gravity="center" />
     <RelativeLayout
         android:layout_width="match_parent"
diff --git a/res/layout/scene_mode_instructional.xml b/res/layout/scene_mode_instructional.xml
index 588dc35..2181e31 100644
--- a/res/layout/scene_mode_instructional.xml
+++ b/res/layout/scene_mode_instructional.xml
@@ -45,15 +45,13 @@
         <ImageView
             android:id="@+id/scene_mode_icon"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:src="@drawable/chroma_flash"/>
+            android:layout_height="wrap_content" />
         <TextView
             android:id="@+id/scene_mode_name"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:gravity="center_vertical"
             android:layout_toRightOf="@id/scene_mode_icon"
-            android:text="@string/pref_camera_scenemode_entry_chromaflash"
             android:textColor="@android:color/black"
             android:textAppearance="?android:attr/textAppearanceMedium" />
 
@@ -66,7 +64,6 @@
         android:layout_marginTop="15dp"
         android:layout_marginLeft="30dp"
         android:layout_marginRight="30dp"
-        android:text="@string/pref_camera2_scene_mode_chroma_flash_instructional_content"
         android:textColor="@android:color/black"
         android:layout_below="@id/title" />
     <CheckBox
diff --git a/res/layout/scene_mode_instructional_landscape.xml b/res/layout/scene_mode_instructional_landscape.xml
new file mode 100644
index 0000000..c5f89f5
--- /dev/null
+++ b/res/layout/scene_mode_instructional_landscape.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Copyright (c) 2016, 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.
+    -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/mode_layout_rect"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="@android:color/transparent"
+    android:gravity="center">
+    <LinearLayout
+        android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="25dp"
+        android:orientation="horizontal"
+        android:gravity="center">
+        <ImageView
+            android:id="@+id/scene_mode_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+        <TextView
+            android:id="@+id/scene_mode_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:layout_toRightOf="@id/scene_mode_icon"
+            android:textColor="@android:color/black"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/scene_mode_instructional"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="25dp"
+        android:layout_marginTop="30dp"
+        android:layout_marginRight="15dp"
+        android:textColor="@android:color/black"
+        android:layout_below="@id/title" />
+    <CheckBox
+        android:id="@+id/remember_selected"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="15dp"
+        android:layout_marginLeft="25dp"
+        android:layout_below="@id/scene_mode_instructional"
+        android:text="@string/pref_camera2_not_show_again"
+        android:textColor="@android:color/black"/>
+
+    <View
+        android:id="@+id/separator"
+        android:layout_width="wrap_content"
+        android:layout_height="1dp"
+        android:layout_marginTop="15dp"
+        android:layout_marginBottom="15dp"
+        android:layout_below="@id/remember_selected"
+        android:background="#c0c0c0" />
+
+    <Button
+        android:id="@+id/scene_mode_instructional_ok"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/separator"
+        android:background="@android:color/transparent"
+        android:layout_marginRight="30dp"
+        android:layout_alignParentRight="true"
+        android:text="@string/pref_camera2_scene_mode_instructional_ok"
+        android:textColor="@android:color/black"/>
+</RelativeLayout>
+
diff --git a/res/layout/scene_mode_label.xml b/res/layout/scene_mode_label.xml
index aa5ef21..652a1c1 100644
--- a/res/layout/scene_mode_label.xml
+++ b/res/layout/scene_mode_label.xml
@@ -33,18 +33,23 @@
             android:layout_height="wrap_content"
             android:layout_marginRight="20dp"
             android:background="#90000000"
-            android:orientation="horizontal">
+            android:orientation="horizontal"
+            android:gravity="center_vertical">
             <TextView
                 android:id="@+id/scene_mode_label"
                 android:singleLine="true"
-                android:text="@string/pref_camera_scenemode_entry_chromaflash"
                 android:textColor="@android:color/white"
                 android:textSize="16dp"
                 style="@style/OnViewfinderSceneLabel" />
             <ImageView
                 android:id="@+id/scene_mode_label_close"
-                android:src="@drawable/x"
-                style="@style/OnViewfinderSceneLabel"/>
+                android:layout_width="15dp"
+                android:layout_height="15dp"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="10dp"
+                android:layout_marginTop="5dp"
+                android:layout_marginBottom="5dp"
+                android:src="@drawable/x" />
         </LinearLayout>
     </com.android.camera.ui.RotateLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/xml/setting_menu_preferences.xml b/res/xml/setting_menu_preferences.xml
index 5cf6c0d..80097f4 100644
--- a/res/xml/setting_menu_preferences.xml
+++ b/res/xml/setting_menu_preferences.xml
@@ -159,7 +159,7 @@
             android:layout="@layout/preference"
             android:title="@string/pref_camera2_clearsight_title" />
 
-        <ListPreference
+        <SwitchPreference
             android:defaultValue="false"
             android:key="pref_camera2_mpo_key"
             android:layout="@layout/preference"
@@ -196,11 +196,14 @@
             android:layout="@layout/preference"
             android:title="@string/pref_camera_dis_title" />
 
-        <SwitchPreference
-            android:defaultValue="false"
+        <ListPreference
+            android:defaultValue="@string/pref_camera_noise_reduction_default"
+            android:entries="@array/pref_camera2_noise_reduction_entries"
+            android:entryValues="@array/pref_camera2_noise_reduction_entryvalues"
             android:icon="@drawable/noise_reduction"
             android:key="pref_camera2_noise_reduction_key"
             android:layout="@layout/preference"
+            android:summary="%s"
             android:title="@string/pref_camera_noise_reduction_title" />
 
         <ListPreference
diff --git a/rs/rotator.rs b/rs/rotator.rs
index 2c57951..62257d2 100755
--- a/rs/rotator.rs
+++ b/rs/rotator.rs
@@ -50,6 +50,10 @@
         if(x >= width - pad)
             return (uchar)0;
         rsSetElementAt_uchar(gOut, yValue, (width-1-x-pad)*height + y);
+    } else if (degree == 0) {
+        if(x >= width - pad)
+            return (uchar)0;
+         rsSetElementAt_uchar(gOut, yValue, x*height + y);
     }
 
 
@@ -71,6 +75,11 @@
                  return (uchar)0;
             rsSetElementAt_uchar(gOut, uValue, ySize + (width-1-x-pad)/2*height + y -1);
             rsSetElementAt_uchar(gOut, vValue, ySize + (width-1-x-pad)/2*height + y);
+        } else if (degree == 0) {
+            if(x >= (width - pad))
+                 return (uchar)0;
+            rsSetElementAt_uchar(gOut, uValue, ySize + x/2*height + y - 1);
+            rsSetElementAt_uchar(gOut, vValue, ySize + x/2*height + y);
         }
     }
     return (uchar)0;
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
old mode 100755
new mode 100644
index 2b363db..e870161
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -56,11 +56,14 @@
 import android.media.MediaActionSound;
 import android.media.MediaMetadataRetriever;
 import android.media.MediaRecorder;
+import android.media.EncoderCapabilities;
+import android.media.EncoderCapabilities.VideoEncoderCap;
 import android.net.Uri;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Bundle;
 import android.os.Message;
 import android.os.SystemClock;
 import android.provider.MediaStore;
@@ -76,7 +79,6 @@
 import android.widget.Toast;
 
 import com.android.camera.exif.ExifInterface;
-import com.android.camera.Exif;
 import com.android.camera.imageprocessor.filter.BlurbusterFilter;
 import com.android.camera.imageprocessor.filter.ChromaflashFilter;
 import com.android.camera.imageprocessor.filter.ImageFilter;
@@ -236,6 +238,13 @@
     private int mChosenImageFormat;
     private Toast mToast;
 
+    private boolean mStartRecPending = false;
+    private boolean mStopRecPending = false;
+
+    boolean mUnsupportedResolution = false;
+
+    private static final int SDCARD_SIZE_LIMIT = 4000 * 1024 * 1024;
+
     /**
      * A {@link CameraCaptureSession } for camera preview.
      */
@@ -312,6 +321,7 @@
     private MediaActionSound mSound;
     private Size mSupportedMaxPictureSize;
 
+
     private class SelfieThread extends Thread {
         public void run() {
             try {
@@ -632,10 +642,10 @@
                 break;
             }
             case STATE_AF_AE_LOCKED: {
-                    Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
-                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
-                    Log.d(TAG, "STATE_AF_AE_LOCKED id: " + id + " afState:" + afState + " aeState:" + aeState);
-                    break;
+                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
+                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+                Log.d(TAG, "STATE_AF_AE_LOCKED id: " + id + " afState:" + afState + " aeState:" + aeState);
+                break;
             }
             case STATE_WAITING_TOUCH_FOCUS:
                 break;
@@ -913,7 +923,7 @@
 
                         @Override
                         public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
-                            Log.e(TAG, "cameracapturesession - onConfigureFailed "+id);
+                            Log.e(TAG, "cameracapturesession - onConfigureFailed "+ id);
                             if (mActivity.isFinishing()) {
                                 return;
                             }
@@ -986,6 +996,9 @@
     }
 
     public void setAFModeToPreview(int id, int afMode) {
+        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            return;
+        }
         Log.d(TAG, "setAFModeToPreview " + afMode);
         mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AF_MODE, afMode);
         applyAFRegions(mPreviewRequestBuilder[id], id);
@@ -994,14 +1007,17 @@
         try {
             mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
                     .build(), mCaptureCallback, mCameraHandler);
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
 
     public void setFlashModeToPreview(int id, boolean isFlashOn) {
         Log.d(TAG, "setFlashModeToPreview " + isFlashOn);
-        if(isFlashOn) {
+        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            return;
+        }
+        if (isFlashOn) {
             mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
             mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
         } else {
@@ -1014,23 +1030,26 @@
         try {
             mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
                     .build(), mCaptureCallback, mCameraHandler);
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
 
     public void setFocusDistanceToPreview(int id, float fd) {
+        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            return;
+        }
         mPreviewRequestBuilder[id].set(CaptureRequest.LENS_FOCUS_DISTANCE, fd);
         mPreviewRequestBuilder[id].setTag(id);
         try {
-            if(id == MONO_ID && !canStartMonoPreview()) {
+            if (id == MONO_ID && !canStartMonoPreview()) {
                 mCaptureSession[id].capture(mPreviewRequestBuilder[id]
                         .build(), mCaptureCallback, mCameraHandler);
             } else {
                 mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
                         .build(), mCaptureCallback, mCameraHandler);
             }
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
@@ -1123,7 +1142,9 @@
      * Lock the focus as the first step for a still image capture.
      */
     private void lockFocus(int id) {
-        if (mActivity == null || mCameraDevice[id] == null) {
+        if (mActivity == null || mCameraDevice[id] == null
+                || !checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            mUI.enableShutter(true);
             warningToast("Camera is not ready yet to take a picture.");
             return;
         }
@@ -1166,14 +1187,15 @@
             mLockRequestHashCode[id] = request.hashCode();
             mState[id] = STATE_WAITING_AF_LOCK;
             mCaptureSession[id].capture(request, mCaptureCallback, mCameraHandler);
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
 
     private void autoFocusTrigger(int id) {
         Log.d(TAG, "autoFocusTrigger " + id);
-        if (null == mActivity || null == mCameraDevice[id]) {
+        if (null == mActivity || null == mCameraDevice[id]
+                || !checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
             warningToast("Camera is not ready yet to take a picture.");
             return;
         }
@@ -1190,7 +1212,7 @@
             Message message = mCameraHandler.obtainMessage(
                     CANCEL_TOUCH_FOCUS, Integer.valueOf(mCameraId[id]), 0);
             mCameraHandler.sendMessageDelayed(message, CANCEL_TOUCH_FOCUS_DELAY);
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
@@ -1383,7 +1405,7 @@
     private void captureVideoSnapshot(final int id) {
         Log.d(TAG, "captureStillPicture " + id);
         try {
-            if (null == mActivity || null == mCameraDevice[id]) {
+            if (null == mActivity || null == mCameraDevice[id] || mCurrentSession == null) {
                 warningToast("Camera is not ready yet to take a video snapshot.");
                 return;
             }
@@ -1433,6 +1455,9 @@
      */
     private void runPrecaptureSequence(int id) {
         Log.d(TAG, "runPrecaptureSequence: " + id);
+        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            return;
+        }
         try {
             CaptureRequest.Builder builder = getRequestBuilder(id);
             builder.setTag(id);
@@ -1443,7 +1468,7 @@
 
             mState[id] = STATE_WAITING_PRECAPTURE;
             mCaptureSession[id].capture(request, mCaptureCallback, mCameraHandler);
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
@@ -1588,6 +1613,9 @@
      */
     public void unlockFocus(int id) {
         Log.d(TAG, "unlockFocus " + id);
+        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            return;
+        }
         try {
             CaptureRequest.Builder builder = getRequestBuilder(id);
             builder.setTag(id);
@@ -1619,12 +1647,8 @@
                     }
                 });
             }
-        } catch (NullPointerException e) {
+        } catch (NullPointerException | IllegalStateException | CameraAccessException e) {
             Log.w(TAG, "Session is already closed");
-        } catch (IllegalStateException e) {
-            Log.w(TAG, "Session is already closed");
-        } catch (CameraAccessException e) {
-            e.printStackTrace();
         }
     }
 
@@ -1645,6 +1669,15 @@
         }
     }
 
+    public boolean isAllSessionClosed() {
+        for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {
+            if (mCaptureSession[i] != null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private void closeSessions() {
         for (int i = MAX_NUM_CAM-1; i >= 0; i--) {
             if (null != mCaptureSession[i]) {
@@ -1727,13 +1760,16 @@
      * Lock the exposure for capture
      */
     private void lockExposure(int id) {
+        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            return;
+        }
         Log.d(TAG, "lockExposure: " + id);
         try {
             applySettingsForLockExposure(mPreviewRequestBuilder[id], id);
             mState[id] = STATE_WAITING_AE_LOCK;
             mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(),
                     mCaptureCallback, mCameraHandler);
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
@@ -1918,6 +1954,7 @@
         mFirstPreviewLoaded = false;
         stopBackgroundThread();
         mLastJpegData = null;
+        setProModeVisible();
     }
 
     @Override
@@ -2132,14 +2169,9 @@
         });
         mUI.enableShutter(true);
         mUI.enableVideo(true);
-        String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
-        boolean promode = false;
-        if (scene != null) {
-            int mode = Integer.parseInt(scene);
-            if (mode == SettingsManager.SCENE_MODE_PROMODE_INT) promode = true;
-        }
-        mUI.initializeProMode(promode);
+        setProModeVisible();
 
+        String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
         if(isPanoSetting(scene)) {
             mActivity.onModuleSelected(ModuleSwitcher.PANOCAPTURE_MODULE_INDEX);
         }
@@ -2403,8 +2435,8 @@
 
     @Override
     public void onCountDownFinished() {
-        mUI.showUIAfterCountDown();
         checkSelfieFlashAndTakePicture();
+        mUI.showUIAfterCountDown();
     }
 
     @Override
@@ -2603,30 +2635,54 @@
         }
     }
 
-    private void startRecordingVideo(final int cameraId) {
+    private boolean startRecordingVideo(final int cameraId) {
         if (null == mCameraDevice[cameraId]) {
-            return;
+            return false;
         }
         Log.d(TAG, "StartRecordingVideo " + cameraId);
+        mStartRecPending = true;
         mIsRecordingVideo = true;
         mMediaRecorderPausing = false;
         mUI.hideUIwhileRecording();
-        mUI.clearFocus();
-        mCameraHandler.removeMessages(CANCEL_TOUCH_FOCUS, mCameraId[cameraId]);
-        mState[cameraId] = STATE_PREVIEW;
-        mControlAFMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
-        closePreviewSession();
-        mFrameProcessor.onClose();
-        boolean changed = mUI.setPreviewSize(mVideoPreviewSize.getWidth(),
-                mVideoPreviewSize.getHeight());
-        if (changed) {
-            mUI.hideSurfaceView();
-            mUI.showSurfaceView();
+
+        mActivity.updateStorageSpaceAndHint();
+        if (mActivity.getStorageSpaceBytes() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
+            Log.w(TAG, "Storage issue, ignore the start request");
+            mStartRecPending = false;
+            mIsRecordingVideo = false;
+            return false;
         }
-        mUI.resetTrackingFocus();
 
         try {
             setUpMediaRecorder(cameraId);
+            if (mUnsupportedResolution == true ) {
+                Log.v(TAG, "Unsupported Resolution according to target");
+                mStartRecPending = false;
+                mIsRecordingVideo = false;
+                return false;
+            }
+            if (mMediaRecorder == null) {
+                Log.e(TAG, "Fail to initialize media recorder");
+                mStartRecPending = false;
+                mIsRecordingVideo = false;
+                return false;
+            }
+
+            requestAudioFocus();
+            mUI.clearFocus();
+            mCameraHandler.removeMessages(CANCEL_TOUCH_FOCUS, mCameraId[cameraId]);
+            mState[cameraId] = STATE_PREVIEW;
+            mControlAFMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+            closePreviewSession();
+            mFrameProcessor.onClose();
+            boolean changed = mUI.setPreviewSize(mVideoPreviewSize.getWidth(),
+                    mVideoPreviewSize.getHeight());
+            if (changed) {
+                mUI.hideSurfaceView();
+                mUI.showSurfaceView();
+            }
+            mUI.resetTrackingFocus();
+
             createVideoSnapshotImageReader();
             mVideoRequestBuilder = mCameraDevice[cameraId].createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
             mVideoRequestBuilder.setTag(cameraId);
@@ -2660,8 +2716,8 @@
                         CameraConstrainedHighSpeedCaptureSession session =
                                     (CameraConstrainedHighSpeedCaptureSession) mCurrentSession;
                         try {
-                            List list = session
-                                        .createHighSpeedRequestList(mVideoRequestBuilder.build());
+                            List list = CameraUtil
+                                 .createHighSpeedRequestList(mVideoRequestBuilder.build(),cameraId);
                             session.setRepeatingBurst(list, mCaptureCallback, mCameraHandler);
                         } catch (CameraAccessException e) {
                             Log.e(TAG, "Failed to start high speed video recording "
@@ -2676,7 +2732,17 @@
                                         + e.getMessage());
                             e.printStackTrace();
                         }
-                        mMediaRecorder.start();
+                        try {
+                            mMediaRecorder.start(); // Recording is now started
+                        } catch (RuntimeException e) {
+                            Toast.makeText(mActivity,"Could not start media recorder.\n " +
+                                    "Can't start video recording.", Toast.LENGTH_LONG).show();
+                            releaseMediaRecorder();
+                            releaseAudioFocus();
+                            mStartRecPending = false;
+                            mIsRecordingVideo = false;
+                            return;
+                        }
                         mUI.clearFocus();
                         mUI.resetPauseButton();
                         mRecordingTotalTime = 0L;
@@ -2705,11 +2771,23 @@
                         try {
                             setUpVideoCaptureRequestBuilder(mVideoRequestBuilder);
                             mCurrentSession.setRepeatingRequest(mVideoRequestBuilder.build(),
-                                mCaptureCallback, mCameraHandler);
+                                    mCaptureCallback, mCameraHandler);
                         } catch (CameraAccessException e) {
                             e.printStackTrace();
+                        } catch (IllegalStateException e) {
+                            e.printStackTrace();
                         }
-                        mMediaRecorder.start();
+                        try {
+                            mMediaRecorder.start(); // Recording is now started
+                        } catch (RuntimeException e) {
+                            Toast.makeText(mActivity,"Could not start media recorder.\n " +
+                                    "Can't start video recording.", Toast.LENGTH_LONG).show();
+                            releaseMediaRecorder();
+                            releaseAudioFocus();
+                            mStartRecPending = false;
+                            mIsRecordingVideo = false;
+                            return;
+                        }
                         mUI.clearFocus();
                         mUI.resetPauseButton();
                         mRecordingTotalTime = 0L;
@@ -2730,6 +2808,8 @@
         } catch (IOException e) {
             e.printStackTrace();
         }
+        mStartRecPending = false;
+        return true;
     }
 
     private void updateTimeLapseSetting() {
@@ -2799,7 +2879,7 @@
     private void applyVideoStabilization(CaptureRequest.Builder builder) {
         String value = mSettingsManager.getValue(SettingsManager.KEY_DIS);
         if (value == null) return;
-        if (value.equals("enable")) {
+        if (value.equals("on")) {
             builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, CaptureRequest
                     .CONTROL_VIDEO_STABILIZATION_MODE_ON);
         } else {
@@ -2903,6 +2983,7 @@
     private void stopRecordingVideo(int cameraId) {
         Log.d(TAG, "stopRecordingVideo " + cameraId);
 
+        mStopRecPending = true;
         boolean shouldAddToMediaStoreNow = false;
         // Stop recording
         mFrameProcessor.setVideoOutputSurface(null);
@@ -2916,7 +2997,7 @@
             AccessibilityUtils.makeAnnouncement(mUI.getVideoButton(),
                     mActivity.getString(R.string.video_recording_stopped));
         } catch (RuntimeException e) {
-            Log.e(TAG, "MediaRecoder stop fail",  e);
+            Log.w(TAG, "MediaRecoder stop fail",  e);
             if (mVideoFilename != null) deleteVideoFile(mVideoFilename);
         }
         if (shouldAddToMediaStoreNow) {
@@ -2943,6 +3024,7 @@
         createSessions();
         mUI.showUIafterRecording();
         mUI.resetTrackingFocus();
+        mStopRecPending = false;
     }
 
     private void closePreviewSession() {
@@ -3024,11 +3106,19 @@
             size = CameraSettings.getTimeLapseQualityFor(size);
         }
 
+        Intent intent = mActivity.getIntent();
+        Bundle myExtras = intent.getExtras();
+
         if (mMediaRecorder == null) mMediaRecorder = new MediaRecorder();
 
         updateHFRSetting();
         boolean hfr = mHighSpeedCapture && !mHighSpeedRecordingMode;
+
         mProfile = CamcorderProfile.get(cameraId, size);
+        int videoWidth = mProfile.videoFrameWidth;
+        int videoHeight = mProfile.videoFrameHeight;
+        mUnsupportedResolution = false;
+
         int videoEncoder = SettingTranslation
                 .getVideoEncoder(mSettingsManager.getValue(SettingsManager.KEY_VIDEO_ENCODER));
         int audioEncoder = SettingTranslation
@@ -3081,6 +3171,54 @@
             mMediaRecorder.setVideoEncodingBitRate(scaledBitrate);
         }
 
+        long requestedSizeLimit = 0;
+        if (isVideoCaptureIntent() && myExtras != null) {
+            requestedSizeLimit = myExtras.getLong(MediaStore.EXTRA_SIZE_LIMIT);
+        }
+        //check if codec supports the resolution, otherwise throw toast
+        List<VideoEncoderCap> videoEncoders = EncoderCapabilities.getVideoEncoders();
+        for (VideoEncoderCap videoEnc: videoEncoders) {
+            if (videoEnc.mCodec == videoEncoder) {
+                if (videoWidth > videoEnc.mMaxFrameWidth ||
+                        videoWidth < videoEnc.mMinFrameWidth ||
+                        videoHeight > videoEnc.mMaxFrameHeight ||
+                        videoHeight < videoEnc.mMinFrameHeight) {
+                    Log.e(TAG, "Selected codec " + videoEncoder +
+                            " does not support "+ videoWidth + "x" + videoHeight
+                            + " resolution");
+                    Log.e(TAG, "Codec capabilities: " +
+                            "mMinFrameWidth = " + videoEnc.mMinFrameWidth + " , " +
+                            "mMinFrameHeight = " + videoEnc.mMinFrameHeight + " , " +
+                            "mMaxFrameWidth = " + videoEnc.mMaxFrameWidth + " , " +
+                            "mMaxFrameHeight = " + videoEnc.mMaxFrameHeight);
+                    mUnsupportedResolution = true;
+                    RotateTextToast.makeText(mActivity, R.string.error_app_unsupported,
+                            Toast.LENGTH_LONG).show();
+                    return;
+                }
+                break;
+            }
+        }
+
+        // Set maximum file size.
+        long maxFileSize = mActivity.getStorageSpaceBytes() - Storage.LOW_STORAGE_THRESHOLD_BYTES;
+        if (requestedSizeLimit > 0 && requestedSizeLimit < maxFileSize) {
+            maxFileSize = requestedSizeLimit;
+        }
+
+        if (Storage.isSaveSDCard() && maxFileSize > SDCARD_SIZE_LIMIT) {
+            maxFileSize = SDCARD_SIZE_LIMIT;
+        }
+        Log.i(TAG, "MediaRecorder setMaxFileSize: " + maxFileSize);
+        try {
+            mMediaRecorder.setMaxFileSize(maxFileSize);
+        } catch (RuntimeException exception) {
+            // We are going to ignore failure of setMaxFileSize here, as
+            // a) The composer selected may simply not support it, or
+            // b) The underlying media framework may not handle 64-bit range
+            // on the size restriction.
+        }
+
         Location loc = mLocationManager.getCurrentLocation();
         if (loc != null) {
             mMediaRecorder.setLocation((float) loc.getLatitude(),
@@ -3110,11 +3248,17 @@
     }
 
     public void onVideoButtonClick() {
+        if (isRecorderReady() == false) return;
+
         if (getCameraMode() == DUAL_MODE) return;
         if (mIsRecordingVideo) {
             stopRecordingVideo(getMainCameraId());
         } else {
-            startRecordingVideo(getMainCameraId());
+            if (!startRecordingVideo(getMainCameraId())) {
+                // Show ui when start recording failed.
+                mUI.showUIafterRecording();
+                releaseMediaRecorder();
+            }
         }
     }
 
@@ -3200,7 +3344,7 @@
     }
 
     private void estimateJpegFileSize() {
-    String quality = mSettingsManager.getValue(SettingsManager
+        String quality = mSettingsManager.getValue(SettingsManager
             .KEY_JPEG_QUALITY);
         int[] ratios = mActivity.getResources().getIntArray(R.array.jpegquality_compression_ratio);
         String[] qualities = mActivity.getResources().getStringArray(
@@ -3307,6 +3451,9 @@
     }
 
     private boolean applyPreferenceToPreview(int cameraId, String key, String value) {
+        if (!checkSessionAndBuilder(mCaptureSession[cameraId], mPreviewRequestBuilder[cameraId])) {
+            return false;
+        }
         boolean updatePreview = false;
         switch (key) {
             case SettingsManager.KEY_WHITE_BALANCE:
@@ -3341,6 +3488,9 @@
     }
 
     private void applyZoomAndUpdate(int id) {
+        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
+            return;
+        }
         applyZoom(mPreviewRequestBuilder[id], id);
         try {
             if(id == MONO_ID && !canStartMonoPreview()) {
@@ -3350,7 +3500,7 @@
                 mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
                         .build(), mCaptureCallback, mCameraHandler);
             }
-        } catch (CameraAccessException e) {
+        } catch (CameraAccessException | IllegalStateException e) {
             e.printStackTrace();
         }
     }
@@ -3464,11 +3614,11 @@
     }
 
     private void applyFaceDetection(CaptureRequest.Builder request) {
-            String value = mSettingsManager.getValue(SettingsManager.KEY_FACE_DETECTION);
-            if (value != null && value.equals("on")) {
-                request.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE,
-                        CaptureRequest.STATISTICS_FACE_DETECT_MODE_SIMPLE);
-            }
+        String value = mSettingsManager.getValue(SettingsManager.KEY_FACE_DETECTION);
+        if (value != null && value.equals("on")) {
+            request.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE,
+                    CaptureRequest.STATISTICS_FACE_DETECT_MODE_SIMPLE);
+        }
     }
 
     private void applyFlash(CaptureRequest.Builder request, int id) {
@@ -3681,30 +3831,39 @@
         }
         if (updatePreviewBayer) {
             try {
-                mCaptureSession[BAYER_ID].setRepeatingRequest(mPreviewRequestBuilder[BAYER_ID]
-                        .build(), mCaptureCallback, mCameraHandler);
-            } catch (CameraAccessException e) {
+                if (checkSessionAndBuilder(mCaptureSession[BAYER_ID],
+                        mPreviewRequestBuilder[BAYER_ID])) {
+                    mCaptureSession[BAYER_ID].setRepeatingRequest(mPreviewRequestBuilder[BAYER_ID]
+                            .build(), mCaptureCallback, mCameraHandler);
+                }
+            } catch (CameraAccessException | IllegalStateException e) {
                 e.printStackTrace();
             }
         }
         if (updatePreviewMono) {
             try {
-                if(canStartMonoPreview()) {
-                    mCaptureSession[MONO_ID].setRepeatingRequest(mPreviewRequestBuilder[MONO_ID]
-                            .build(), mCaptureCallback, mCameraHandler);
-                } else {
-                    mCaptureSession[MONO_ID].capture(mPreviewRequestBuilder[MONO_ID]
-                            .build(), mCaptureCallback, mCameraHandler);
+                if (checkSessionAndBuilder(mCaptureSession[MONO_ID],
+                        mPreviewRequestBuilder[MONO_ID])) {
+                    if (canStartMonoPreview()) {
+                        mCaptureSession[MONO_ID].setRepeatingRequest(mPreviewRequestBuilder[MONO_ID]
+                                .build(), mCaptureCallback, mCameraHandler);
+                    } else {
+                        mCaptureSession[MONO_ID].capture(mPreviewRequestBuilder[MONO_ID]
+                                .build(), mCaptureCallback, mCameraHandler);
+                    }
                 }
-            } catch (CameraAccessException e) {
+            } catch (CameraAccessException | IllegalStateException e) {
                 e.printStackTrace();
             }
         }
         if (updatePreviewFront) {
             try {
-                mCaptureSession[FRONT_ID].setRepeatingRequest(mPreviewRequestBuilder[FRONT_ID]
-                        .build(), mCaptureCallback, mCameraHandler);
-            } catch (CameraAccessException e) {
+                if (checkSessionAndBuilder(mCaptureSession[FRONT_ID],
+                        mPreviewRequestBuilder[FRONT_ID])) {
+                    mCaptureSession[FRONT_ID].setRepeatingRequest(mPreviewRequestBuilder[FRONT_ID]
+                            .build(), mCaptureCallback, mCameraHandler);
+                }
+            } catch (CameraAccessException | IllegalStateException e) {
                 e.printStackTrace();
             }
         }
@@ -3745,25 +3904,36 @@
     }
 
     public void restartSession(boolean isSurfaceChanged) {
-        if(isSurfaceChanged) {
-            mUI.hideSurfaceView();
-        }
+        Log.d(TAG, "restartSession isSurfaceChanged = " + isSurfaceChanged);
+        if (isAllSessionClosed()) return;
+
         closeProcessors();
         closeSessions();
+
+        if(isSurfaceChanged) {
+            mUI.hideSurfaceView();
+            mUI.showSurfaceView();
+        }
+
         initializeValues();
         updatePreviewSize();
         openProcessors();
-        if(isSurfaceChanged) {
-            mUI.showSurfaceView();
-        } else {
-            createSessions();
-        }
+        createSessions();
 
         if(isTrackingFocusSettingOn()) {
             mUI.resetTrackingFocus();
         }
+        resetStateMachine();
     }
 
+    private void resetStateMachine() {
+        for (int i = 0; i < MAX_NUM_CAM; i++) {
+            mState[i] = STATE_PREVIEW;
+        }
+        mUI.enableShutter(true);
+    }
+
+
     private Size getOptimalPreviewSize(Size pictureSize, Size[] prevSizes, int screenW, int
             screenH) {
         if (pictureSize.getWidth() <= screenH && pictureSize.getHeight() <= screenW) {
@@ -4027,6 +4197,36 @@
         }
     }
 
+    private void showToast(String tips) {
+        if (mToast == null) {
+            mToast = Toast.makeText(mActivity, tips, Toast.LENGTH_LONG);
+        }
+        mToast.setText(tips);
+        mToast.show();
+    }
+
+    private boolean isRecorderReady() {
+        if ((mStartRecPending == true || mStopRecPending == true))
+            return false;
+        else
+            return true;
+    }
+
+    /*
+     * Make sure we're not recording music playing in the background, ask the
+     * MediaPlaybackService to pause playback.
+     */
+    private void requestAudioFocus() {
+        AudioManager am = (AudioManager)mActivity.getSystemService(Context.AUDIO_SERVICE);
+        // Send request to obtain audio focus. This will stop other
+        // music stream.
+        int result = am.requestAudioFocus(null, AudioManager.STREAM_MUSIC,
+                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+        if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
+            Log.v(TAG, "Audio focus request failed");
+        }
+    }
+
     private void releaseAudioFocus() {
         AudioManager am = (AudioManager)mActivity.getSystemService(Context.AUDIO_SERVICE);
         int result = am.abandonAudioFocus(null);
@@ -4035,12 +4235,9 @@
         }
     }
 
-    private void showToast(String tips) {
-        if (mToast == null) {
-            mToast = Toast.makeText(mActivity, tips, Toast.LENGTH_LONG);
-        }
-        mToast.setText(tips);
-        mToast.show();
+    private boolean isVideoCaptureIntent() {
+        String action = mActivity.getIntent().getAction();
+        return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
     }
 
     private void resetScreenOn() {
@@ -4058,4 +4255,21 @@
         mHandler.removeMessages(CLEAR_SCREEN_DELAY);
         mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
     }
+
+
+    private void setProModeVisible() {
+        String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+        boolean promode = false;
+        if (scene != null) {
+            int mode = Integer.parseInt(scene);
+            if (mode == SettingsManager.SCENE_MODE_PROMODE_INT) {
+                promode = true;
+            }
+        }
+        mUI.initializeProMode(!mPaused && promode);
+    }
+	
+    boolean checkSessionAndBuilder(CameraCaptureSession session, CaptureRequest.Builder builder) {
+        return session != null && builder != null;
+    }
 }
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index aed62aa..1cb7d75 100644
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -228,7 +228,7 @@
         return mDisplaySize;
     }
 
-    public CaptureUI(CameraActivity activity, CaptureModule module, View parent) {
+    public CaptureUI(CameraActivity activity, final CaptureModule module, View parent) {
         mActivity = activity;
         mModule = module;
         mRootView = parent;
@@ -298,8 +298,10 @@
         mMakeupButton.setOnClickListener(new View.OnClickListener(){
             @Override
             public void onClick(View v) {
-                toggleMakeup();
-                updateMenus();
+                if (module != null && !module.isAllSessionClosed()) {
+                    toggleMakeup();
+                    updateMenus();
+                }
             }
         });
         setMakeupButtonIcon();
@@ -315,6 +317,7 @@
         initSceneModeButton();
         initSwitchCamera();
         initFlashButton();
+        updateMenus();
 
         mRecordingTimeView = (TextView) mRootView.findViewById(R.id.recording_time);
         mRecordingTimeRect = (RotateLayout) mRootView.findViewById(R.id.recording_time_rect);
@@ -448,6 +451,7 @@
         initFlashButton();
         setMakeupButtonIcon();
         showSceneModeLabel();
+        updateMenus();
         if(mModule.isTrackingFocusSettingOn()) {
             mTrackingFocusRenderer.setVisible(false);
             mTrackingFocusRenderer.setVisible(true);
@@ -651,11 +655,15 @@
     }
 
     private void showSceneInstructionalDialog(int orientation) {
+        int layoutId = R.layout.scene_mode_instructional;
+        if ( orientation == 90 || orientation == 270 ) {
+            layoutId = R.layout.scene_mode_instructional_landscape;
+        }
         LayoutInflater inflater =
                 (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View view = inflater.inflate(R.layout.scene_mode_instructional, null);
+        View view = inflater.inflate(layoutId, null);
 
-        int index = mSettingsManager.getValueIndex(SettingsManager.KEY_SCENE_MODE);
+       final int index = mSettingsManager.getValueIndex(SettingsManager.KEY_SCENE_MODE);
         TextView name = (TextView)view.findViewById(R.id.scene_mode_name);
         CharSequence sceneModeNameArray[] =
                 mSettingsManager.getEntries(SettingsManager.KEY_SCENE_MODE);
@@ -724,12 +732,9 @@
         dialogWindow.setGravity(Gravity.CENTER);
         lp.width = lp.height = dialogSize;
         dialogWindow.setAttributes(lp);
-        if ( orientation == 180 ) {
-            dialogSize -= 40;
-            RelativeLayout layout = (RelativeLayout)view.findViewById(R.id.mode_layout_rect);
-            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(dialogSize, dialogSize);
-            layout.setLayoutParams(params);
-        }
+        RelativeLayout layout = (RelativeLayout)view.findViewById(R.id.mode_layout_rect);
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(dialogSize, dialogSize);
+        layout.setLayoutParams(params);
     }
 
     private void showSceneModeLabel() {
@@ -1042,13 +1047,18 @@
         boolean enableSceneMenu = true;
         String makeupValue = mSettingsManager.getValue(SettingsManager.KEY_MAKEUP);
         int colorEffect = mSettingsManager.getValueIndex(SettingsManager.KEY_COLOR_EFFECT);
+        String sceneMode = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
         if (makeupValue != null && !makeupValue.equals("0")) {
             enableSceneMenu = false;
             enableFilterMenu = false;
         } else if (colorEffect != 0 || mFilterMenuStatus == FILTER_MENU_ON){
             enableSceneMenu = false;
             enableMakeupMenu = false;
+        }else if ( sceneMode != null && !sceneMode.equals("0")){
+             enableMakeupMenu = false;
+             enableFilterMenu = false;
         }
+
         mMakeupButton.setEnabled(enableMakeupMenu);
         mFilterModeSwitcher.setEnabled(enableFilterMenu);
         mSceneModeSwitcher.setEnabled(enableSceneMenu);
diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java
index a30dd94..401289f 100644
--- a/src/com/android/camera/ComboPreferences.java
+++ b/src/com/android/camera/ComboPreferences.java
@@ -68,7 +68,7 @@
         }
     }
 
-    private static String getLocalSharedPreferencesName(
+    public static String getLocalSharedPreferencesName(
             Context context, int cameraId) {
         return context.getPackageName() + "_preferences_" + cameraId;
     }
diff --git a/src/com/android/camera/PanoCaptureUI.java b/src/com/android/camera/PanoCaptureUI.java
index 5e96929..a25ff9f 100644
--- a/src/com/android/camera/PanoCaptureUI.java
+++ b/src/com/android/camera/PanoCaptureUI.java
@@ -455,9 +455,13 @@
     }
 
     private void showSceneInstructionalDialog(int orientation) {
+        int layoutId = R.layout.scene_mode_instructional;
+        if ( orientation == 90 || orientation == 270 ) {
+            layoutId = R.layout.scene_mode_instructional_landscape;
+        }
         LayoutInflater inflater =
                 (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View view = inflater.inflate(R.layout.scene_mode_instructional, null);
+        View view = inflater.inflate(layoutId, null);
 
         TextView name = (TextView)view.findViewById(R.id.scene_mode_name);
         name.setText(R.string.pref_camera_scenemode_entry_panorama);
@@ -516,11 +520,8 @@
         dialogWindow.setGravity(Gravity.CENTER);
         lp.width = lp.height = dialogSize;
         dialogWindow.setAttributes(lp);
-        if ( orientation == 180 ) {
-            dialogSize -= 40;
-            RelativeLayout layout = (RelativeLayout)view.findViewById(R.id.mode_layout_rect);
-            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(dialogSize, dialogSize);
-            layout.setLayoutParams(params);
-        }
+        RelativeLayout layout = (RelativeLayout)view.findViewById(R.id.mode_layout_rect);
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(dialogSize, dialogSize);
+        layout.setLayoutParams(params);
     }
 }
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index 7c42f5c..a784c34 100755
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -2369,7 +2369,7 @@
             String zsl = mPreferences.getString(CameraSettings.KEY_ZSL,
                     mActivity.getString(R.string.pref_camera_zsl_default));
             mUI.overrideSettings(CameraSettings.KEY_ZSL, zsl);
-            mUI.startCountDown(seconds, isShutterSoundOn());
+            mUI.startCountDown(seconds, playSound);
         } else {
             mSnapshotOnIdle = false;
             initiateSnap();
diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java
index c1c6442..6adbcfb 100644
--- a/src/com/android/camera/SettingsManager.java
+++ b/src/com/android/camera/SettingsManager.java
@@ -451,6 +451,28 @@
         return pref.findIndexOfValue(value);
     }
 
+    private boolean setFocusValue(String key, float value) {
+        boolean result = false;
+        String prefName = ComboPreferences.getLocalSharedPreferencesName(mContext, mCameraId);
+        SharedPreferences sharedPreferences = mContext.getSharedPreferences(prefName,
+                Context.MODE_PRIVATE);
+        float prefValue = sharedPreferences.getFloat(key, 0.5f);
+        if (prefValue != value) {
+            SharedPreferences.Editor editor = sharedPreferences.edit();
+            editor.putFloat(key, value);
+            editor.apply();
+            result = true;
+        }
+        return result;
+    }
+
+    public float getFocusValue(String key) {
+        String prefName = ComboPreferences.getLocalSharedPreferencesName(mContext, mCameraId);
+        SharedPreferences sharedPreferences = mContext.getSharedPreferences(prefName,
+                Context.MODE_PRIVATE);
+        return sharedPreferences.getFloat(key, 0.5f);
+    }
+
     public boolean isOverriden(String key) {
         Values values = mValuesMap.get(key);
         return values.overriddenValue != null;
@@ -479,12 +501,15 @@
         }
     }
 
-    public void setFocusDistance(float value) {
-        List<SettingState> list = new ArrayList<>();
-        Values values = new Values("" + value, null);
-        SettingState ss = new SettingState(KEY_FOCUS_DISTANCE, values);
-        list.add(ss);
-        notifyListeners(list);
+    public void setFocusDistance(String key, float value, float minFocus) {
+        boolean isSuccess = setFocusValue(key, value);
+        if (isSuccess) {
+            List<SettingState> list = new ArrayList<>();
+            Values values = new Values("" + value * minFocus, null);
+            SettingState ss = new SettingState(KEY_FOCUS_DISTANCE, values);
+            list.add(ss);
+            notifyListeners(list);
+        }
     }
 
     private void updateMapAndNotify(ListPreference pref) {
@@ -1076,6 +1101,11 @@
         return mCharacteristics.get(cameraId).get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
     }
 
+    public StreamConfigurationMap getStreamConfigurationMap(int cameraId){
+        return mCharacteristics.get(cameraId)
+                .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+    }
+
     public List<String> getSupportedColorEffects(int cameraId) {
         int[] flashModes = mCharacteristics.get(cameraId).get(CameraCharacteristics
                 .CONTROL_AVAILABLE_EFFECTS);
diff --git a/src/com/android/camera/imageprocessor/FrameProcessor.java b/src/com/android/camera/imageprocessor/FrameProcessor.java
index 5dc50c4..519d774 100755
--- a/src/com/android/camera/imageprocessor/FrameProcessor.java
+++ b/src/com/android/camera/imageprocessor/FrameProcessor.java
@@ -160,6 +160,9 @@
         if(mModule.getMainCameraCharacteristics() != null) {
             degree = mModule.getMainCameraCharacteristics().
                     get(CameraCharacteristics.SENSOR_ORIENTATION);
+            if (mModule.getMainCameraId() == CaptureModule.FRONT_ID) {
+                degree = Math.abs(degree - 90);
+            }
         }
         mRsRotator.set_degree(degree);
         mRsYuvToRGB.set_gIn(mProcessAllocation);
diff --git a/src/com/android/camera/ui/OneUICameraControls.java b/src/com/android/camera/ui/OneUICameraControls.java
index 0388b57..3dce60d 100755
--- a/src/com/android/camera/ui/OneUICameraControls.java
+++ b/src/com/android/camera/ui/OneUICameraControls.java
@@ -532,6 +532,7 @@
         mProModeOn = promode;
         initializeProMode(mProModeOn);
         resetProModeIcons();
+        mProMode.reinit();
     }
 
     private void resetProModeIcons() {
diff --git a/src/com/android/camera/ui/PanoCaptureProcessView.java b/src/com/android/camera/ui/PanoCaptureProcessView.java
index 2b37fd6..95e9a09 100644
--- a/src/com/android/camera/ui/PanoCaptureProcessView.java
+++ b/src/com/android/camera/ui/PanoCaptureProcessView.java
@@ -120,6 +120,7 @@
     private static final boolean DEBUG = false; //TODO: This has to be false before release
     private BitmapArrayOutputStream mBitmapStream;
     private static boolean mIsSupported = false;
+    private Object mBitmapStreamLock = new Object();
 
     private boolean mIsFrameProcessing = false;
     enum PANO_STATUS {
@@ -337,13 +338,15 @@
 
     public void onPause() {
         mSensorManager.unregisterListener(this, mRotationSensor);
-        if(mBitmapStream != null) {
-            try {
-                mBitmapStream.close();
-            } catch (IOException e) {
-                //Ignore
+        synchronized (mBitmapStreamLock) {
+            if(mBitmapStream != null) {
+                try {
+                    mBitmapStream.close();
+                } catch (IOException e) {
+                    //Ignore
+                }
+                mBitmapStream = null;
             }
-            mBitmapStream = null;
         }
     }
 
@@ -510,13 +513,16 @@
         }
 
         private void doTask(BitmapTask bitmapTask) {
-            if(mBitmapStream == null) {
-                mBitmapStream = new BitmapArrayOutputStream(1024*1204);
+            int rtv = -1;
+            synchronized (mBitmapStreamLock) {
+                if(mBitmapStream == null) {
+                    mBitmapStream = new BitmapArrayOutputStream(1024*1204);
+                }
+                mBitmapStream.reset();
+                bitmapTask.bitmap.compress(Bitmap.CompressFormat.JPEG, 100, mBitmapStream);
+                rtv = callNativeProcessKeyFrame(mBitmapStream.toByteArray(), mBitmapStream.size(),
+                        bitmapTask.x, bitmapTask.y, 0, bitmapTask.dir);
             }
-            mBitmapStream.reset();
-            bitmapTask.bitmap.compress(Bitmap.CompressFormat.JPEG, 100, mBitmapStream);
-            int rtv = callNativeProcessKeyFrame(mBitmapStream.toByteArray(), mBitmapStream.size(),
-                    bitmapTask.x, bitmapTask.y, 0, bitmapTask.dir);
             if(rtv < 0) {
                 mShouldFinish = true;
                 stopPano(false, mActivity.getResources().getString(R.string.panocapture_direction_is_changed));
diff --git a/src/com/android/camera/ui/ProMode.java b/src/com/android/camera/ui/ProMode.java
index dbd89ec..b55d0c4 100644
--- a/src/com/android/camera/ui/ProMode.java
+++ b/src/com/android/camera/ui/ProMode.java
@@ -169,6 +169,10 @@
         mCurveMeasure = new PathMeasure(mCurvePath, false);
     }
 
+    public void reinit() {
+        init();
+    }
+
     public void setOrientation(int orientation) {
         mOrientation = orientation;
         if (mAddedViews != null) {
@@ -199,7 +203,7 @@
         if (mMode == MANUAL_MODE) {
             minFocus = mSettingsManager
                     .getMinimumFocusDistance(mSettingsManager.getCurrentCameraId());
-            float value = 0.5f;
+            float value = mSettingsManager.getFocusValue(SettingsManager.KEY_FOCUS_DISTANCE);
             setSlider(value);
             int stride = mCurveRight - mCurveLeft;
             for (int i = 0; i < 2; i++) {
@@ -288,7 +292,7 @@
 
     public void setSlider(float slider) {
         mSlider = slider;
-        mSettingsManager.setFocusDistance(mSlider * minFocus);
+        mSettingsManager.setFocusDistance(SettingsManager.KEY_FOCUS_DISTANCE, mSlider, minFocus);
         mUI.updateProModeText(mMode, "Manual");
         invalidate();
     }
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 838f8d9..cb414ba 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -71,9 +71,22 @@
 import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
+import java.util.ArrayList;
 import java.util.Locale;
+import android.util.Range;
 import java.util.StringTokenizer;
 
+import com.android.camera.SettingsManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.utils.SurfaceUtils;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
 /**
  * Collection of utility functions used in this package.
  */
@@ -1275,4 +1288,85 @@
                     (long) rhs.getWidth() * rhs.getHeight());
         }
     }
+
+    public static List<CaptureRequest> createHighSpeedRequestList(CaptureRequest request
+            ,int cameraId) throws CameraAccessException {
+        if (request == null) {
+            throw new IllegalArgumentException("Input capture request must not be null");
+        }
+        Collection<Surface> outputSurfaces = request.getTargets();
+        Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+
+        StreamConfigurationMap config =
+                SettingsManager.getInstance().getStreamConfigurationMap(cameraId);
+        SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config);
+
+        // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize
+        // the preview frame rate, should use maxBatch size for that high speed stream
+        // configuration. We choose the former for now.
+        int requestListSize = fpsRange.getUpper() / 30;
+        List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+
+        // Prepare the Request builders: need carry over the request controls.
+        // First, create a request builder that will only include preview or recording target.
+        CameraMetadataNative requestMetadata = new CameraMetadataNative(request.getNativeCopy());
+        // Note that after this step, the requestMetadata is mutated (swapped) and can not be used
+        // for next request builder creation.
+        CaptureRequest.Builder singleTargetRequestBuilder = new CaptureRequest.Builder(
+                requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
+        singleTargetRequestBuilder.setTag(cameraId);
+
+        // Overwrite the capture intent to make sure a good value is set.
+        Iterator<Surface> iterator = outputSurfaces.iterator();
+        Surface firstSurface = iterator.next();
+        Surface secondSurface = null;
+        if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(firstSurface)) {
+            singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
+                    CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
+        } else {
+            // Video only, or preview + video
+            singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
+                    CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
+        }
+        singleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
+
+        // Second, Create a request builder that will include both preview and recording targets.
+        CaptureRequest.Builder doubleTargetRequestBuilder = null;
+        if (outputSurfaces.size() == 2) {
+            // Have to create a new copy, the original one was mutated after a new
+            // CaptureRequest.Builder creation.
+            requestMetadata = new CameraMetadataNative(request.getNativeCopy());
+            doubleTargetRequestBuilder = new CaptureRequest.Builder(
+                    requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
+            doubleTargetRequestBuilder.setTag(cameraId);
+            doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
+                    CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
+            doubleTargetRequestBuilder.addTarget(firstSurface);
+            secondSurface = iterator.next();
+            doubleTargetRequestBuilder.addTarget(secondSurface);
+            doubleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
+            // Make sure singleTargetRequestBuilder contains only recording surface for
+            // preview + recording case.
+            Surface recordingSurface = firstSurface;
+            if (!SurfaceUtils.isSurfaceForHwVideoEncoder(recordingSurface)) {
+                recordingSurface = secondSurface;
+            }
+            singleTargetRequestBuilder.addTarget(recordingSurface);
+        } else {
+            // Single output case: either recording or preview.
+            singleTargetRequestBuilder.addTarget(firstSurface);
+        }
+
+        // Generate the final request list.
+        for (int i = 0; i < requestListSize; i++) {
+            if (i == 0 && doubleTargetRequestBuilder != null) {
+                // First request should be recording + preview request
+                requestList.add(doubleTargetRequestBuilder.build());
+            } else {
+                requestList.add(singleTargetRequestBuilder.build());
+            }
+        }
+
+        return Collections.unmodifiableList(requestList);
+    }
 }
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
index bd54dc7..944bf08 100755
--- a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
+++ b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
@@ -912,6 +912,12 @@
             mImageEncodeHandler.obtainMessage(MSG_START_CAPTURE).sendToTarget();
 
             short encodeRequest = 0;
+            /* In same case, timeout will reset ClearSightNativeEngine object, so fields
+               in the object is not initial, need to return and skip process.
+            */
+            if (ClearSightNativeEngine.getInstance().getReferenceImage(true) == null) {
+                return;
+            }
             long csTs = ClearSightNativeEngine.getInstance().getReferenceImage(true).getTimestamp();
             CaptureRequest.Builder csRequest = createEncodeReprocRequest(
                     ClearSightNativeEngine.getInstance().getReferenceResult(true), CAM_TYPE_BAYER);