Support for rotation lock in video recording hints

Bug: 13545160
Change-Id: I73c20e5a6701cc9b89ce6871b6541320fe7317e1
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 7d73246..bb3125d 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -475,6 +475,7 @@
         if (mOrientation != newOrientation) {
             mOrientation = newOrientation;
         }
+        mUI.onOrientationChanged(orientation);
 
     }
 
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 79b8ccf..161e051 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -33,6 +33,7 @@
 import com.android.camera.ui.PreviewOverlay;
 import com.android.camera.ui.PreviewStatusListener;
 import com.android.camera.ui.RotateLayout;
+import com.android.camera.widget.VideoRecordingHints;
 import com.android.camera2.R;
 
 import java.util.List;
@@ -49,7 +50,7 @@
     // An review image having same size as preview. It is displayed when
     // recording is stopped in capture intent.
     private ImageView mReviewImage;
-    private View mVideoHints;
+    private VideoRecordingHints mVideoHints;
     private TextView mRecordingTimeView;
     private LinearLayout mLabelsLinearLayout;
     private View mTimeLapseLabel;
@@ -108,7 +109,7 @@
         initializeMiscControls();
         mAnimationManager = new AnimationManager();
         mFocusUI = (FocusOverlay) mRootView.findViewById(R.id.focus_overlay);
-        mVideoHints = mRootView.findViewById(R.id.video_shooting_hints);
+        mVideoHints = (VideoRecordingHints) mRootView.findViewById(R.id.video_shooting_hints);
     }
 
     public void setPreviewSize(int width, int height) {
@@ -276,6 +277,10 @@
         return new Point(mRootView.getMeasuredWidth(), mRootView.getMeasuredHeight());
     }
 
+    public void onOrientationChanged(int orientation) {
+        mVideoHints.onOrientationChanged(orientation);
+    }
+
     private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener {
         @Override
         public void onZoomValueChanged(int index) {
diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java
deleted file mode 100644
index e05b0cb..0000000
--- a/src/com/android/camera/ui/CameraControls.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-public class CameraControls extends RotatableLayout {
-
-    public CameraControls(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setMeasureAllChildren(true);
-    }
-
-    public CameraControls(Context context) {
-        super(context);
-        setMeasureAllChildren(true);
-    }
-
-    @Override
-    public void onFinishInflate() {
-        super.onFinishInflate();
-    }
-}
diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java
deleted file mode 100644
index 85948c6..0000000
--- a/src/com/android/camera/ui/RotatableLayout.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera.ui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import com.android.camera.debug.Log;
-import com.android.camera.util.CameraUtil;
-
-/* RotatableLayout rotates itself as well as all its children when orientation
- * changes. Specifically, when going from portrait to landscape, camera
- * controls move from the bottom of the screen to right side of the screen
- * (i.e. counter clockwise). Similarly, when the screen changes to portrait, we
- * need to move the controls from right side to the bottom of the screen, which
- * is a clockwise rotation.
- */
-
-public class RotatableLayout extends FrameLayout {
-
-    private static final Log.Tag TAG = new Log.Tag("RotatableLayout");
-    private static final int UNKOWN_ORIENTATION = -1;
-    // Initial orientation of the layout (ORIENTATION_PORTRAIT, or ORIENTATION_LANDSCAPE)
-    private int mInitialOrientation;
-    private int mPrevRotation = UNKOWN_ORIENTATION;
-    private boolean mIsDefaultToPortrait = false;
-
-    public RotatableLayout(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        init();
-    }
-
-    public RotatableLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public RotatableLayout(Context context) {
-        super(context);
-        init();
-    }
-
-    private void init() {
-        mInitialOrientation = getResources().getConfiguration().orientation;
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        // Before the first time this view is attached to window, device rotation
-        // will not trigger onConfigurationChanged callback. So in the first run
-        // we need to rotate the view if necessary. After that, onConfigurationChanged
-        // call will track all the subsequent device rotation.
-        if (mPrevRotation == UNKOWN_ORIENTATION) {
-            mIsDefaultToPortrait = CameraUtil.isDefaultToPortrait((Activity) getContext());
-            if (mIsDefaultToPortrait) {
-                // Natural orientation for tablet is landscape
-                mPrevRotation =  mInitialOrientation == Configuration.ORIENTATION_PORTRAIT ?
-                        0 : 90;
-            } else {
-                // When tablet orientation is 0 or 270 (i.e. getUnifiedOrientation
-                // = 0 or 90), we load the layout resource without any rotation.
-                mPrevRotation =  mInitialOrientation == Configuration.ORIENTATION_LANDSCAPE ?
-                        0 : 270;
-            }
-
-            // check if there is any rotation before the view is attached to window
-            rotateIfNeeded();
-        }
-    }
-
-    private void rotateIfNeeded() {
-        if (mPrevRotation == UNKOWN_ORIENTATION) {
-            return;
-        }
-        int rotation = CameraUtil.getDisplayRotation((Activity) getContext());
-        int diff = (rotation - mPrevRotation + 360) % 360;
-        if ( diff == 0) {
-            // No rotation
-            return;
-        } else if (diff == 180) {
-            // 180-degree rotation
-            mPrevRotation = rotation;
-            flipChildren();
-            return;
-        }
-        // 90 or 270-degree rotation
-        boolean clockwise = isClockWiseRotation(mPrevRotation, rotation);
-        mPrevRotation = rotation;
-        rotateLayout(clockwise);
-    }
-
-    protected int getUnifiedRotation() {
-        // all the layout code assumes camera device orientation to be portrait
-        // adjust rotation for landscape
-        int rotation = CameraUtil.getDisplayRotation((Activity) getContext());
-        if (!mIsDefaultToPortrait) {
-            return (rotation + 90) % 360;
-        }
-        return rotation;
-    }
-
-    public void checkLayoutFlip() {
-        int currentRotation = CameraUtil.getDisplayRotation((Activity) getContext());
-        if ((currentRotation - mPrevRotation + 360) % 360 == 180) {
-            mPrevRotation = currentRotation;
-            flipChildren();
-            requestLayout();
-        }
-    }
-
-    @Override
-    public void onWindowVisibilityChanged(int visibility) {
-        if (visibility == View.VISIBLE) {
-            // Make sure when coming back from onPause, the layout is rotated correctly
-            checkLayoutFlip();
-        }
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration config) {
-        super.onConfigurationChanged(config);
-        rotateIfNeeded();
-    }
-
-    protected void rotateLayout(boolean clockwise) {
-        // Change the size of the layout
-        ViewGroup.LayoutParams lp = getLayoutParams();
-        int width = lp.width;
-        int height = lp.height;
-        lp.height = width;
-        lp.width = height;
-        setLayoutParams(lp);
-
-        // rotate all the children
-        rotateChildren(clockwise);
-    }
-
-    protected void rotateChildren(boolean clockwise) {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            rotate(child, clockwise);
-        }
-    }
-
-    protected void flipChildren() {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            flip(child);
-        }
-    }
-
-    public static boolean isClockWiseRotation(int prevRotation, int currentRotation) {
-        if (prevRotation == (currentRotation + 90) % 360) {
-            return true;
-        }
-        return false;
-    }
-
-    public static void rotate(View view, boolean isClockwise) {
-        if (isClockwise) {
-            rotateClockwise(view);
-        } else {
-            rotateCounterClockwise(view);
-        }
-    }
-
-    private static boolean contains(int value, int mask) {
-        return (value & mask) == mask;
-    }
-
-    public static void rotateClockwise(View view) {
-        if (view == null) return;
-        LayoutParams lp = (LayoutParams) view.getLayoutParams();
-        int gravity = lp.gravity;
-        int ngravity = 0;
-        // rotate gravity
-        if (contains(gravity, Gravity.LEFT)) {
-            ngravity |= Gravity.TOP;
-        }
-        if (contains(gravity, Gravity.RIGHT)) {
-            ngravity |= Gravity.BOTTOM;
-        }
-        if (contains(gravity, Gravity.TOP)) {
-            ngravity |= Gravity.RIGHT;
-        }
-        if (contains(gravity, Gravity.BOTTOM)) {
-            ngravity |= Gravity.LEFT;
-        }
-        if (contains(gravity, Gravity.CENTER)) {
-            ngravity |= Gravity.CENTER;
-        }
-        if (contains(gravity, Gravity.CENTER_HORIZONTAL)) {
-            ngravity |= Gravity.CENTER_VERTICAL;
-        }
-        if (contains(gravity, Gravity.CENTER_VERTICAL)) {
-            ngravity |= Gravity.CENTER_HORIZONTAL;
-        }
-        lp.gravity = ngravity;
-        int ml = lp.leftMargin;
-        int mr = lp.rightMargin;
-        int mt = lp.topMargin;
-        int mb = lp.bottomMargin;
-        lp.leftMargin = mb;
-        lp.rightMargin = mt;
-        lp.topMargin = ml;
-        lp.bottomMargin = mr;
-        int width = lp.width;
-        int height = lp.height;
-        lp.width = height;
-        lp.height = width;
-        view.setLayoutParams(lp);
-    }
-
-    public static void rotateCounterClockwise(View view) {
-        if (view == null) return;
-        LayoutParams lp = (LayoutParams) view.getLayoutParams();
-        int gravity = lp.gravity;
-        int ngravity = 0;
-        // change gravity
-        if (contains(gravity, Gravity.RIGHT)) {
-            ngravity |= Gravity.TOP;
-        }
-        if (contains(gravity, Gravity.LEFT)) {
-            ngravity |= Gravity.BOTTOM;
-        }
-        if (contains(gravity, Gravity.TOP)) {
-            ngravity |= Gravity.LEFT;
-        }
-        if (contains(gravity, Gravity.BOTTOM)) {
-            ngravity |= Gravity.RIGHT;
-        }
-        if (contains(gravity, Gravity.CENTER)) {
-            ngravity |= Gravity.CENTER;
-        }
-        if (contains(gravity, Gravity.CENTER_HORIZONTAL)) {
-            ngravity |= Gravity.CENTER_VERTICAL;
-        }
-        if (contains(gravity, Gravity.CENTER_VERTICAL)) {
-            ngravity |= Gravity.CENTER_HORIZONTAL;
-        }
-        lp.gravity = ngravity;
-        int ml = lp.leftMargin;
-        int mr = lp.rightMargin;
-        int mt = lp.topMargin;
-        int mb = lp.bottomMargin;
-        lp.leftMargin = mt;
-        lp.rightMargin = mb;
-        lp.topMargin = mr;
-        lp.bottomMargin = ml;
-        int width = lp.width;
-        int height = lp.height;
-        lp.width = height;
-        lp.height = width;
-        view.setLayoutParams(lp);
-    }
-
-    // Rotate a given view 180 degrees
-    public static void flip(View view) {
-        rotateClockwise(view);
-        rotateClockwise(view);
-    }
-}
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 4aafead..a633905 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -410,11 +410,12 @@
     /**
      * Calculate the default orientation of the device based on the width and
      * height of the display when rotation = 0 (i.e. natural width and height)
-     * @param activity the activity context
+     * @param context current context
      * @return whether the default orientation of the device is portrait
      */
-    public static boolean isDefaultToPortrait(Activity activity) {
-        Display currentDisplay = activity.getWindowManager().getDefaultDisplay();
+    public static boolean isDefaultToPortrait(Context context) {
+        Display currentDisplay = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
+                .getDefaultDisplay();
         Point displaySize = new Point();
         currentDisplay.getSize(displaySize);
         int orientation = currentDisplay.getRotation();
diff --git a/src/com/android/camera/widget/VideoRecordingHints.java b/src/com/android/camera/widget/VideoRecordingHints.java
index 294ec3c..c931dfb 100644
--- a/src/com/android/camera/widget/VideoRecordingHints.java
+++ b/src/com/android/camera/widget/VideoRecordingHints.java
@@ -20,12 +20,13 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.OrientationEventListener;
 import android.view.View;
 
+import com.android.camera.util.CameraUtil;
 import com.android.camera2.R;
 
 /**
@@ -48,12 +49,14 @@
     private final Drawable mRotateArrows;
     private final Drawable mPhoneGraphic;
     private final int mPhoneGraphicHalfHeight;
+    private final boolean mIsDefaultToPortrait;
     private float mRotation = INITIAL_ROTATION;
     private final ValueAnimator mRotationAnimation;
     private final ObjectAnimator mAlphaAnimator;
     private boolean mIsInLandscape = false;
     private int mCenterX = UNSET;
     private int mCenterY = UNSET;
+    private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
 
     public VideoRecordingHints(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -135,7 +138,7 @@
                 // Do nothing.
             }
         });
-
+        mIsDefaultToPortrait = CameraUtil.isDefaultToPortrait(context);
     }
 
     /**
@@ -154,8 +157,7 @@
     @Override
     public void onVisibilityChanged(View v, int visibility) {
         super.onVisibilityChanged(v, visibility);
-        if (getVisibility() == VISIBLE && getResources().getConfiguration().orientation ==
-                Configuration.ORIENTATION_PORTRAIT) {
+        if (getVisibility() == VISIBLE && !isInLandscape()) {
             continueRotationAnimation();
         } else if (getVisibility() != VISIBLE) {
             mRotationAnimation.cancel();
@@ -164,17 +166,6 @@
     }
 
     @Override
-    public void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (getVisibility() == VISIBLE && getResources().getConfiguration().orientation ==
-                Configuration.ORIENTATION_PORTRAIT) {
-            continueRotationAnimation();
-        }
-        mIsInLandscape = getResources().getConfiguration().orientation ==
-                Configuration.ORIENTATION_LANDSCAPE;
-    }
-
-    @Override
     public void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         // Center drawables in the layout
@@ -188,24 +179,6 @@
     }
 
     @Override
-    public void onConfigurationChanged(Configuration config) {
-        super.onConfigurationChanged(config);
-        if (getVisibility() == VISIBLE) {
-            if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
-                mRotationAnimation.cancel();
-                // Start fading out.
-                if (mAlphaAnimator.isRunning()) {
-                    return;
-                }
-                mAlphaAnimator.start();
-            } else {
-                continueRotationAnimation();
-            }
-        }
-        mIsInLandscape = config.orientation == Configuration.ORIENTATION_LANDSCAPE;
-    }
-
-    @Override
     public void draw(Canvas canvas) {
         super.draw(canvas);
         // Don't draw anything after the fade-out animation in landscape.
@@ -226,4 +199,42 @@
         }
     }
 
+    /**
+     * Handles orientation change by starting/stopping the video hint based on the
+     * new orientation.
+     */
+    public void onOrientationChanged(int orientation) {
+        if (mLastOrientation == orientation) {
+            return;
+        }
+        mLastOrientation = orientation;
+        if (mLastOrientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
+            return;
+        }
+
+        mIsInLandscape = isInLandscape();
+        if (getVisibility() == VISIBLE) {
+            if (mIsInLandscape) {
+                // Landscape.
+                mRotationAnimation.cancel();
+                // Start fading out.
+                if (mAlphaAnimator.isRunning()) {
+                    return;
+                }
+                mAlphaAnimator.start();
+            } else {
+                // Portrait.
+                continueRotationAnimation();
+            }
+        }
+    }
+
+    /**
+     * Returns whether the device is in landscape based on the natural orientation
+     * and rotation from natural orientation.
+     */
+    private boolean isInLandscape() {
+        return (mLastOrientation % 180 == 90 && mIsDefaultToPortrait)
+                || (mLastOrientation % 180 == 0 && !mIsDefaultToPortrait);
+    }
 }