Fix focus area in front camera.

Front camera preview is mirrored. Change to use matrix to
calculate the focus area. So the focus area will be
correct in all orientations in front or back camera.

bug:5446617
bug:5461028
Change-Id: I2d39a22cd9f034c5028843ca3d4abe0f9962f18a
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index ecff831..931095e 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -377,7 +377,10 @@
         mPreviewFrame = findViewById(R.id.camera_preview);
         mPreviewFrame.setOnTouchListener(this);
         mFocusIndicator = (RotateLayout) findViewById(R.id.focus_indicator_rotate_layout);
-        mFocusManager.initialize(mFocusIndicator, mPreviewFrame, mFaceView, this);
+        CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+        boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
+        mFocusManager.initialize(mFocusIndicator, mPreviewFrame, mFaceView, this,
+                mirror, mDisplayOrientation);
         mFocusManager.initializeSoundPlayer(getResources().openRawResourceFd(R.raw.camera_focus));
         mImageSaver = new ImageSaver();
         Util.initializeScreenBrightness(getWindow(), getContentResolver());
diff --git a/src/com/android/camera/FocusManager.java b/src/com/android/camera/FocusManager.java
index 228e2d1..86b92c2 100644
--- a/src/com/android/camera/FocusManager.java
+++ b/src/com/android/camera/FocusManager.java
@@ -21,7 +21,9 @@
 import com.android.camera.ui.FocusIndicatorView;
 
 import android.content.res.AssetFileDescriptor;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.hardware.Camera.Area;
 import android.hardware.Camera.Parameters;
 import android.os.Handler;
@@ -57,6 +59,7 @@
     private boolean mInLongPress;
     private boolean mLockAeAwbNeeded;
     private boolean mAeAwbLock;
+    private Matrix mMatrix;
     private SoundPlayer mSoundPlayer;
     private View mFocusIndicatorRotateLayout;
     private FocusIndicatorView mFocusIndicator;
@@ -98,6 +101,7 @@
         mPreferences = preferences;
         mDefaultFocusMode = defaultFocusMode;
         mHandler = new MainHandler();
+        mMatrix = new Matrix();
     }
 
     // This has to be initialized before initialize().
@@ -111,13 +115,22 @@
     }
 
     public void initialize(View focusIndicatorRotate, View previewFrame,
-            FaceView faceView, Listener listener) {
+            FaceView faceView, Listener listener, boolean mirror, int displayOrientation) {
         mFocusIndicatorRotateLayout = focusIndicatorRotate;
         mFocusIndicator = (FocusIndicatorView) focusIndicatorRotate.findViewById(
                 R.id.focus_indicator);
         mPreviewFrame = previewFrame;
         mFaceView = faceView;
         mListener = listener;
+
+        Matrix matrix = new Matrix();
+        Util.prepareMatrix(matrix, mirror, displayOrientation,
+                previewFrame.getWidth(), previewFrame.getHeight());
+        // In face detection, the matrix converts the driver coordinates to UI
+        // coordinates. In tap focus, the inverted matrix converts the UI
+        // coordinates to driver coordinates.
+        matrix.invert(mMatrix);
+
         if (mParameters != null) {
             mInitialized = true;
         } else {
@@ -270,9 +283,9 @@
         // Convert the coordinates to driver format.
         // AE area is bigger because exposure is sensitive and
         // easy to over- or underexposure if area is too small.
-        calculateTapArea(focusWidth, focusHeight, 1, x, y, previewWidth, previewHeight,
+        calculateTapArea(focusWidth, focusHeight, 1f, x, y, previewWidth, previewHeight,
                 mFocusArea.get(0).rect);
-        calculateTapArea(focusWidth, focusHeight, 1.5, x, y, previewWidth, previewHeight,
+        calculateTapArea(focusWidth, focusHeight, 1.5f, x, y, previewWidth, previewHeight,
                 mMeteringArea.get(0).rect);
 
         // Use margin to set the focus indicator to the touched area.
@@ -451,23 +464,16 @@
         mMeteringArea = null;
     }
 
-    public void calculateTapArea(int focusWidth, int focusHeight, double areaMultiple,
+    public void calculateTapArea(int focusWidth, int focusHeight, float areaMultiple,
             int x, int y, int previewWidth, int previewHeight, Rect rect) {
         int areaWidth = (int)(focusWidth * areaMultiple);
         int areaHeight = (int)(focusHeight * areaMultiple);
-        int areaLeft = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
-        int areaTop = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);
-        convertToFocusArea(areaLeft, areaTop, areaWidth, areaHeight, previewWidth, previewHeight,
-                rect);
-    }
+        int left = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
+        int top = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);
 
-    // Convert the touch point to the focus area in driver format.
-    public static void convertToFocusArea(int left, int top, int focusWidth, int focusHeight,
-            int previewWidth, int previewHeight, Rect rect) {
-        rect.left = Math.round((float) left / previewWidth * 2000 - 1000);
-        rect.top = Math.round((float) top / previewHeight * 2000 - 1000);
-        rect.right = Math.round((float) (left + focusWidth) / previewWidth * 2000 - 1000);
-        rect.bottom = Math.round((float) (top + focusHeight) / previewHeight * 2000 - 1000);
+        RectF rectF = new RectF(left, top, left + areaWidth, top + areaHeight);
+        mMatrix.mapRect(rectF);
+        Util.rectFToRect(rectF, rect);
     }
 
     public boolean isFocusCompleted() {
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index 31a54d5..4c28e56 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -27,6 +27,8 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.hardware.Camera;
 import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.Parameters;
@@ -522,6 +524,18 @@
         }
     }
 
+    public static void dumpRect(RectF rect, String msg) {
+        Log.v(TAG, msg + "=(" + rect.left + "," + rect.top
+                + "," + rect.right + "," + rect.bottom + ")");
+    }
+
+    public static void rectFToRect(RectF rectF, Rect rect) {
+        rect.left = Math.round(rectF.left);
+        rect.top = Math.round(rectF.top);
+        rect.right = Math.round(rectF.right);
+        rect.bottom = Math.round(rectF.bottom);
+    }
+
     public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation,
             int viewWidth, int viewHeight) {
         // Need mirror for front camera.
diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java
index 167d8b9..9018886 100644
--- a/src/com/android/camera/ui/FaceView.java
+++ b/src/com/android/camera/ui/FaceView.java
@@ -117,17 +117,11 @@
         mPause = false;
     }
 
-    private void dumpRect(RectF rect, String msg) {
-        Log.v(TAG, msg + "=(" + rect.left + "," + rect.top
-                + "," + rect.right + "," + rect.bottom + ")");
-    }
-
     @Override
     protected void onDraw(Canvas canvas) {
         if (mFaces != null && mFaces.length > 0) {
             // Prepare the matrix.
-            Util.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, getWidth(),
-                    getHeight());
+            Util.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, getWidth(), getHeight());
 
             // Focus indicator is directional. Rotate the matrix and the canvas
             // so it looks correctly in all orientations.
@@ -137,9 +131,9 @@
             for (int i = 0; i < mFaces.length; i++) {
                 // Transform the coordinates.
                 mRect.set(mFaces[i].rect);
-                if (LOGV) dumpRect(mRect, "Original rect");
+                if (LOGV) Util.dumpRect(mRect, "Original rect");
                 mMatrix.mapRect(mRect);
-                if (LOGV) dumpRect(mRect, "Transformed rect");
+                if (LOGV) Util.dumpRect(mRect, "Transformed rect");
 
                 mFaceIndicator.setBounds(Math.round(mRect.left), Math.round(mRect.top),
                         Math.round(mRect.right), Math.round(mRect.bottom));
diff --git a/tests/src/com/android/camera/unittest/CameraTest.java b/tests/src/com/android/camera/unittest/CameraTest.java
index ad0eed5..0e1242c 100644
--- a/tests/src/com/android/camera/unittest/CameraTest.java
+++ b/tests/src/com/android/camera/unittest/CameraTest.java
@@ -73,22 +73,6 @@
         assertEquals(180, Util.roundOrientation(180, 270));
     }
 
-    public void testConvertToFocusArea() {
-        Rect rect = new Rect();
-        FocusManager.convertToFocusArea(0, 0, 100, 100, 800, 480, rect);
-        assertEquals(new Rect(-1000, -1000, -750, -583), rect);
-        FocusManager.convertToFocusArea(0, 0, 400, 240, 800, 480, rect);
-        assertEquals(new Rect(-1000, -1000, 0, 0), rect);
-        FocusManager.convertToFocusArea(400, 240, 400, 240, 800, 480, rect);
-        assertEquals(new Rect(0, 0, 1000, 1000), rect);
-        FocusManager.convertToFocusArea(200, 120, 400, 240, 800, 480, rect);
-        assertEquals(new Rect(-500, -500, 500, 500), rect);
-        FocusManager.convertToFocusArea(0, 0, 800, 480, 800, 480, rect);
-        assertEquals(new Rect(-1000, -1000, 1000, 1000), rect);
-        FocusManager.convertToFocusArea(860, 620, 100, 100, 960, 720, rect);
-        assertEquals(new Rect(792, 722, 1000, 1000), rect);
-    }
-
     public void testPrepareMatrix() {
         Matrix matrix = new Matrix();
         float[] points;