Merge "DO NOT MERGE - Shutter button left handed support" into gb-ub-photos-denali
diff --git a/src/com/android/camera/CaptureLayoutHelper.java b/src/com/android/camera/CaptureLayoutHelper.java
index d343503..ea7d867 100644
--- a/src/com/android/camera/CaptureLayoutHelper.java
+++ b/src/com/android/camera/CaptureLayoutHelper.java
@@ -17,6 +17,7 @@
 package com.android.camera;
 
 import android.content.Context;
+import android.graphics.Matrix;
 import android.graphics.RectF;
 
 import com.android.camera.app.CameraApp;
@@ -49,6 +50,8 @@
      */
     private float mAspectRatio = TextureViewHelper.MATCH_SCREEN;
     private PositionConfiguration mPositionConfiguration = null;
+    private int mRotation = 0;
+    private boolean mShowBottomBar = true;
 
     /**
      * PositionConfiguration contains the layout info for bottom bar and preview
@@ -86,6 +89,15 @@
     }
 
     /**
+     * Sets whether bottom bar will show or not. This will affect the calculation
+     * of uncovered preview area, which is used to lay out mode list, mode options,
+     * etc.
+     */
+    public void setShowBottomBar(boolean showBottomBar) {
+        mShowBottomBar = showBottomBar;
+    }
+
+    /**
      * Updates bottom bar rect and preview rect. This gets called whenever
      * preview aspect ratio changes or main activity layout size changes.
      */
@@ -93,7 +105,8 @@
         if (mWindowWidth == 0 || mWindowHeight == 0) {
             return;
         }
-        mPositionConfiguration = getPositionConfiguration(mWindowWidth, mWindowHeight, mAspectRatio);
+        mPositionConfiguration = getPositionConfiguration(mWindowWidth, mWindowHeight, mAspectRatio,
+                mRotation);
     }
 
     /**
@@ -146,17 +159,38 @@
             return new RectF();
         }
 
+        if (!RectF.intersects(mPositionConfiguration.mBottomBarRect,
+                mPositionConfiguration.mPreviewRect) || !mShowBottomBar) {
+            return mPositionConfiguration.mPreviewRect;
+        }
+
         if (mWindowHeight > mWindowWidth) {
             // Portrait.
-            return new RectF(mPositionConfiguration.mPreviewRect.left,
-                    mPositionConfiguration.mPreviewRect.top,
-                    mPositionConfiguration.mPreviewRect.right,
-                    mPositionConfiguration.mBottomBarRect.top);
+            if (mRotation >= 180) {
+                // Reverse portrait, bottom bar align top.
+                return new RectF(mPositionConfiguration.mPreviewRect.left,
+                        mPositionConfiguration.mBottomBarRect.bottom,
+                        mPositionConfiguration.mPreviewRect.right,
+                        mPositionConfiguration.mPreviewRect.bottom);
+            } else {
+                return new RectF(mPositionConfiguration.mPreviewRect.left,
+                        mPositionConfiguration.mPreviewRect.top,
+                        mPositionConfiguration.mPreviewRect.right,
+                        mPositionConfiguration.mBottomBarRect.top);
+            }
         } else {
-            return new RectF(mPositionConfiguration.mPreviewRect.left,
-                    mPositionConfiguration.mPreviewRect.top,
-                    mPositionConfiguration.mBottomBarRect.left,
-                    mPositionConfiguration.mPreviewRect.bottom);
+            if (mRotation >= 180) {
+                // Reverse landscape, bottom bar align left.
+                return new RectF(mPositionConfiguration.mBottomBarRect.right,
+                        mPositionConfiguration.mPreviewRect.top,
+                        mPositionConfiguration.mPreviewRect.right,
+                        mPositionConfiguration.mPreviewRect.bottom);
+            } else {
+                return new RectF(mPositionConfiguration.mPreviewRect.left,
+                        mPositionConfiguration.mPreviewRect.top,
+                        mPositionConfiguration.mBottomBarRect.left,
+                        mPositionConfiguration.mPreviewRect.bottom);
+            }
         }
     }
 
@@ -176,9 +210,10 @@
     }
 
     @Override
-    public void onNonDecorWindowSizeChanged(int width, int height) {
+    public void onNonDecorWindowSizeChanged(int width, int height, int rotation) {
         mWindowWidth = width;
         mWindowHeight = height;
+        mRotation = rotation;
         updatePositionConfiguration();
     }
 
@@ -191,11 +226,12 @@
      * @param height height of the main activity layout, excluding system decor
      *               such as status bar, nav bar, etc.
      * @param previewAspectRatio aspect ratio of the preview
+     * @param rotation rotation from the natural orientation
      * @return a custom position configuration that contains bottom bar rect,
      *         preview rect and whether bottom bar should be overlaid.
      */
     private PositionConfiguration getPositionConfiguration(int width, int height,
-            float previewAspectRatio) {
+            float previewAspectRatio, int rotation) {
         boolean landscape = width > height;
 
         // If the aspect ratio is defined as fill the screen, then preview should
@@ -209,76 +245,85 @@
             } else {
                 config.mBottomBarRect.set(0, height - mBottomBarOptimalHeight, width, height);
             }
-            return config;
-        }
-
-        if (previewAspectRatio < 1) {
-            previewAspectRatio = 1 / previewAspectRatio;
-        }
-        // Get the bottom bar width and height.
-        float barSize;
-        int longerEdge = Math.max(width, height);
-        int shorterEdge = Math.min(width, height);
-
-        // Check the remaining space if fit short edge.
-        float spaceNeededAlongLongerEdge = shorterEdge * previewAspectRatio;
-        float remainingSpaceAlongLongerEdge = longerEdge - spaceNeededAlongLongerEdge;
-
-        float previewShorterEdge;
-        float previewLongerEdge;
-        if (remainingSpaceAlongLongerEdge <= 0) {
-            // Preview aspect ratio > screen aspect ratio: fit longer edge.
-            previewLongerEdge = longerEdge;
-            previewShorterEdge = longerEdge / previewAspectRatio;
-            barSize = mBottomBarOptimalHeight;
-            config.mBottomBarOverlay = true;
-
-            if (landscape) {
-                config.mPreviewRect.set(0, height / 2 - previewShorterEdge / 2, previewLongerEdge,
-                        height / 2 + previewShorterEdge / 2);
-                config.mBottomBarRect.set(width - barSize, height / 2 - previewShorterEdge / 2,
-                        width, height / 2 + previewShorterEdge / 2);
-            } else {
-                config.mPreviewRect.set(width / 2 - previewShorterEdge / 2, 0,
-                        width / 2 + previewShorterEdge / 2, previewLongerEdge);
-                config.mBottomBarRect.set(width / 2 - previewShorterEdge / 2, height - barSize,
-                        width / 2 + previewShorterEdge / 2, height);
-            }
-        } else if (remainingSpaceAlongLongerEdge <= mBottomBarMinHeight) {
-            // Need to scale down the preview to fit in the space excluding the bottom bar.
-            previewLongerEdge = longerEdge - mBottomBarMinHeight;
-            previewShorterEdge = previewLongerEdge / previewAspectRatio;
-            barSize = mBottomBarMinHeight;
-            config.mBottomBarOverlay = false;
-            if (landscape) {
-                config.mPreviewRect.set(0, height / 2 - previewShorterEdge / 2, previewLongerEdge,
-                        height / 2 + previewShorterEdge / 2);
-                config.mBottomBarRect.set(width - barSize, height / 2 - previewShorterEdge / 2,
-                        width, height / 2 + previewShorterEdge / 2);
-            } else {
-                config.mPreviewRect.set(width / 2 - previewShorterEdge / 2, 0,
-                        width / 2 + previewShorterEdge / 2, previewLongerEdge);
-                config.mBottomBarRect.set(width / 2 - previewShorterEdge / 2, height - barSize,
-                        width / 2 + previewShorterEdge / 2, height);
-            }
         } else {
-            // Fit shorter edge.
-            barSize = remainingSpaceAlongLongerEdge <= mBottomBarMaxHeight ?
-                    remainingSpaceAlongLongerEdge: mBottomBarMaxHeight;
-            previewShorterEdge = shorterEdge;
-            previewLongerEdge = shorterEdge * previewAspectRatio;
-            config.mBottomBarOverlay = false;
-            if (landscape) {
-                float right = width - barSize;
-                float left = right - previewLongerEdge;
-                config.mPreviewRect.set(left, 0, right, previewShorterEdge);
-                config.mBottomBarRect.set(width - barSize, 0, width, height);
-            } else {
-                float bottom = height - barSize;
-                float top = bottom - previewLongerEdge;
-                config.mPreviewRect.set(0, top, previewShorterEdge, bottom);
-                config.mBottomBarRect.set(0, height - barSize, width, height);
+            if (previewAspectRatio < 1) {
+                previewAspectRatio = 1 / previewAspectRatio;
             }
+            // Get the bottom bar width and height.
+            float barSize;
+            int longerEdge = Math.max(width, height);
+            int shorterEdge = Math.min(width, height);
+
+            // Check the remaining space if fit short edge.
+            float spaceNeededAlongLongerEdge = shorterEdge * previewAspectRatio;
+            float remainingSpaceAlongLongerEdge = longerEdge - spaceNeededAlongLongerEdge;
+
+            float previewShorterEdge;
+            float previewLongerEdge;
+            if (remainingSpaceAlongLongerEdge <= 0) {
+                // Preview aspect ratio > screen aspect ratio: fit longer edge.
+                previewLongerEdge = longerEdge;
+                previewShorterEdge = longerEdge / previewAspectRatio;
+                barSize = mBottomBarOptimalHeight;
+                config.mBottomBarOverlay = true;
+
+                if (landscape) {
+                    config.mPreviewRect.set(0, height / 2 - previewShorterEdge / 2, previewLongerEdge,
+                            height / 2 + previewShorterEdge / 2);
+                    config.mBottomBarRect.set(width - barSize, height / 2 - previewShorterEdge / 2,
+                            width, height / 2 + previewShorterEdge / 2);
+                } else {
+                    config.mPreviewRect.set(width / 2 - previewShorterEdge / 2, 0,
+                            width / 2 + previewShorterEdge / 2, previewLongerEdge);
+                    config.mBottomBarRect.set(width / 2 - previewShorterEdge / 2, height - barSize,
+                            width / 2 + previewShorterEdge / 2, height);
+                }
+            } else if (remainingSpaceAlongLongerEdge <= mBottomBarMinHeight) {
+                // Need to scale down the preview to fit in the space excluding the bottom bar.
+                previewLongerEdge = longerEdge - mBottomBarMinHeight;
+                previewShorterEdge = previewLongerEdge / previewAspectRatio;
+                barSize = mBottomBarMinHeight;
+                config.mBottomBarOverlay = false;
+                if (landscape) {
+                    config.mPreviewRect.set(0, height / 2 - previewShorterEdge / 2, previewLongerEdge,
+                            height / 2 + previewShorterEdge / 2);
+                    config.mBottomBarRect.set(width - barSize, height / 2 - previewShorterEdge / 2,
+                            width, height / 2 + previewShorterEdge / 2);
+                } else {
+                    config.mPreviewRect.set(width / 2 - previewShorterEdge / 2, 0,
+                            width / 2 + previewShorterEdge / 2, previewLongerEdge);
+                    config.mBottomBarRect.set(width / 2 - previewShorterEdge / 2, height - barSize,
+                            width / 2 + previewShorterEdge / 2, height);
+                }
+            } else {
+                // Fit shorter edge.
+                barSize = remainingSpaceAlongLongerEdge <= mBottomBarMaxHeight ?
+                        remainingSpaceAlongLongerEdge : mBottomBarMaxHeight;
+                previewShorterEdge = shorterEdge;
+                previewLongerEdge = shorterEdge * previewAspectRatio;
+                config.mBottomBarOverlay = false;
+                if (landscape) {
+                    float right = width - barSize;
+                    float left = right - previewLongerEdge;
+                    config.mPreviewRect.set(left, 0, right, previewShorterEdge);
+                    config.mBottomBarRect.set(width - barSize, 0, width, height);
+                } else {
+                    float bottom = height - barSize;
+                    float top = bottom - previewLongerEdge;
+                    config.mPreviewRect.set(0, top, previewShorterEdge, bottom);
+                    config.mBottomBarRect.set(0, height - barSize, width, height);
+                }
+            }
+        }
+
+        if (rotation >= 180) {
+            // Rotate 180 degrees.
+            Matrix rotate = new Matrix();
+            rotate.setRotate(180, width / 2, height / 2);
+            if (!config.mBottomBarOverlay) {
+                rotate.mapRect(config.mPreviewRect);
+            }
+            rotate.mapRect(config.mBottomBarRect);
         }
         return config;
     }
diff --git a/src/com/android/camera/TextureViewHelper.java b/src/com/android/camera/TextureViewHelper.java
index 8bf03b4..0c3e123 100644
--- a/src/com/android/camera/TextureViewHelper.java
+++ b/src/com/android/camera/TextureViewHelper.java
@@ -25,6 +25,7 @@
 
 import com.android.camera.debug.Log;
 import com.android.camera.ui.PreviewStatusListener;
+import com.android.camera.util.CameraUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -38,6 +39,7 @@
 
     private static final Log.Tag TAG = new Log.Tag("TexViewHelper");
     public static final float MATCH_SCREEN = 0f;
+    private static final int UNSET = -1;
     private TextureView mPreview;
     private int mWidth = 0;
     private int mHeight = 0;
@@ -55,6 +57,7 @@
             new ArrayList<PreviewStatusListener.PreviewAreaChangedListener>();
     private OnLayoutChangeListener mOnLayoutChangeListener = null;
     private CaptureLayoutHelper mCaptureLayoutHelper = null;
+    private int mOrientation = UNSET;
 
     public TextureViewHelper(TextureView preview, CaptureLayoutHelper helper) {
         mPreview = preview;
@@ -79,9 +82,11 @@
                                int oldTop, int oldRight, int oldBottom) {
         int width = right - left;
         int height = bottom - top;
-        if (mWidth != width || mHeight != height) {
+        int rotation = CameraUtil.getDisplayRotation(mPreview.getContext());
+        if (mWidth != width || mHeight != height || mOrientation != rotation) {
             mWidth = width;
             mHeight = height;
+            mOrientation = rotation;
             if (mAutoAdjustTransform) {
                 updateTransform();
             } else {
diff --git a/src/com/android/camera/app/CameraAppUI.java b/src/com/android/camera/app/CameraAppUI.java
index 05fec8a..2717278 100644
--- a/src/com/android/camera/app/CameraAppUI.java
+++ b/src/com/android/camera/app/CameraAppUI.java
@@ -536,7 +536,7 @@
      * decor such as status bar and nav bar) has changed.
      */
     public interface NonDecorWindowSizeChangedListener {
-        public void onNonDecorWindowSizeChanged(int width, int height);
+        public void onNonDecorWindowSizeChanged(int width, int height, int rotation);
     }
 
     private final CameraModuleScreenShotProvider mCameraModuleScreenShotProvider =
@@ -775,6 +775,9 @@
                     if ((rotation - mLastRotation + 360) % 360 == 180
                             && mPreviewStatusListener != null) {
                         mPreviewStatusListener.onPreviewFlipped();
+                        mIndicatorBottomBarWrapper.requestLayout();
+                        mModeListView.requestLayout();
+                        mTextureView.requestLayout();
                     }
                     mLastRotation = rotation;
                 }
@@ -1091,7 +1094,8 @@
                         mModeOptionsOverlay.requestLayout();
                         mBottomBar.requestLayout();
                     }
-                });
+                }
+        );
     }
 
     /**
@@ -1384,6 +1388,9 @@
     public void resetBottomControls(ModuleController module, int moduleIndex) {
         if (areBottomControlsUsed(module)) {
             setBottomBarShutterIcon(moduleIndex);
+            mCaptureLayoutHelper.setShowBottomBar(true);
+        } else {
+            mCaptureLayoutHelper.setShowBottomBar(false);
         }
     }
 
diff --git a/src/com/android/camera/ui/MainActivityLayout.java b/src/com/android/camera/ui/MainActivityLayout.java
index 52e49e2..fdee0e5 100644
--- a/src/com/android/camera/ui/MainActivityLayout.java
+++ b/src/com/android/camera/ui/MainActivityLayout.java
@@ -28,6 +28,7 @@
 
 import com.android.camera.app.CameraAppUI;
 import com.android.camera.debug.Log;
+import com.android.camera.util.CameraUtil;
 import com.android.camera.util.UsageStatistics;
 import com.android.camera.widget.FilmstripLayout;
 import com.android.camera2.R;
@@ -150,7 +151,8 @@
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         if (mNonDecorWindowSizeChangedListener != null) {
             mNonDecorWindowSizeChangedListener.onNonDecorWindowSizeChanged(
-                    MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
+                    MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec),
+                    CameraUtil.getDisplayRotation(getContext()));
         }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
@@ -165,7 +167,8 @@
         mNonDecorWindowSizeChangedListener = listener;
         if (mNonDecorWindowSizeChangedListener != null) {
             mNonDecorWindowSizeChangedListener.onNonDecorWindowSizeChanged(
-                    getMeasuredWidth(), getMeasuredHeight());
+                    getMeasuredWidth(), getMeasuredHeight(),
+                    CameraUtil.getDisplayRotation(getContext()));
         }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/camera/widget/ModeOptionsOverlay.java b/src/com/android/camera/widget/ModeOptionsOverlay.java
index e7ca57f..178d939 100644
--- a/src/com/android/camera/widget/ModeOptionsOverlay.java
+++ b/src/com/android/camera/widget/ModeOptionsOverlay.java
@@ -121,39 +121,17 @@
 
     @Override
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        setLayoutDimensions();
-    }
-
-    /**
-     * The overlay takes its horizontal dimension from the preview.  The vertical
-     * dimension of the overlay is determined by its parent layout, which has
-     * knowledge of the bottom bar dimensions.
-     */
-    private void setLayoutDimensions() {
         if (mCaptureLayoutHelper == null) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
             Log.e(TAG, "Capture layout helper needs to be set first.");
-            return;
-        }
-
-        RectF previewRect = mCaptureLayoutHelper.getPreviewRect();
-        int previewWidth = (int) previewRect.width();
-        int previewHeight = (int) previewRect.height();
-
-        if (previewWidth == 0 || previewHeight == 0) {
-            return;
-        }
-
-        boolean isPortrait = Configuration.ORIENTATION_PORTRAIT
-            == getResources().getConfiguration().orientation;
-
-        ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams();
-        if (isPortrait) {
-            params.width = previewWidth;
         } else {
-            params.height = previewHeight;
+            RectF uncoveredPreviewRect = mCaptureLayoutHelper.getUncoveredPreviewRect();
+            super.onMeasure(MeasureSpec.makeMeasureSpec(
+                            (int) uncoveredPreviewRect.width(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec((int) uncoveredPreviewRect.height(),
+                            MeasureSpec.EXACTLY)
+            );
         }
-        setLayoutParams(params);
     }
 
     /**