Merge "In debug_ui mode, show CAF result state, length of AF scan, fps, for camera2 API." into ub-camera-glacier
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 4c30695..4748099 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -67,7 +67,7 @@
     <color name="bright_foreground_holo_dark">#fff3f3f3</color>
     <color name="face_detect_start">#ffffff00</color>
     <color name="focus_debug">#90ffffff</color>
-    <color name="focus_debug_light">#50ffffff</color>
+    <color name="focus_debug_text">#b0ffffff</color>
     <color name="focus_debug_success">#9000ff00</color>
     <color name="focus_debug_fail">#90ff0000</color>
     <color name="gray">#FFAAAAAA</color>
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 03d191f..8fe036a 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -30,6 +30,7 @@
 import android.location.Location;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.provider.MediaStore;
 import android.view.KeyEvent;
 import android.view.OrientationEventListener;
@@ -201,6 +202,10 @@
 
     /** True if in AF tap-to-focus sequence. */
     private boolean mTapToFocusWaitForActiveScan = false;
+    /** Records beginning frame of each AF scan. */
+    private long mAutoFocusScanStartFrame = -1;
+    /** Records beginning time of each AF scan in uptimeMillis. */
+    private long mAutoFocusScanStartTime;
 
     /** Persistence of Tap to Focus target UI after scan complete. */
     private static final int FOCUS_HOLD_UI_MILLIS = 0;
@@ -768,13 +773,14 @@
                 true,
                 (int) (Settings3A.getAutoFocusRegionWidth() * mZoomValue * minEdge),
                 (int) (Settings3A.getMeteringRegionWidth() * mZoomValue * minEdge));
+        mUI.showAutoFocusInProgress();
     }
 
     /**
      * Update UI based on AF state changes.
      */
     @Override
-    public void onFocusStatusUpdate(final AutoFocusState state) {
+    public void onFocusStatusUpdate(final AutoFocusState state, long frameNumber) {
         Log.v(TAG, "AF status is state:" + state);
 
         switch (state) {
@@ -784,7 +790,6 @@
                     @Override
                     public void run() {
                         setAutoFocusTargetPassive();
-                        mUI.showAutoFocusInProgress();
                     }
                 });
                 break;
@@ -796,8 +801,7 @@
                 mMainHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        setAutoFocusTargetPassive();
-                        mMainHandler.post(mHideAutoFocusTargetRunnable);
+                        mUI.setPassiveFocusSuccess(state == AutoFocusState.PASSIVE_FOCUSED);
                     }
                 });
                 break;
@@ -810,6 +814,40 @@
                 }
                 break;
         }
+
+        if (CAPTURE_DEBUG_UI) {
+            measureAutoFocusScans(state, frameNumber);
+        }
+    }
+
+    private void measureAutoFocusScans(final AutoFocusState state, long frameNumber) {
+        // Log AF scan lengths.
+        boolean passive = false;
+        switch (state) {
+            case PASSIVE_SCAN:
+            case ACTIVE_SCAN:
+                if (mAutoFocusScanStartFrame == -1) {
+                    mAutoFocusScanStartFrame = frameNumber;
+                    mAutoFocusScanStartTime = SystemClock.uptimeMillis();
+                }
+                break;
+            case PASSIVE_FOCUSED:
+            case PASSIVE_UNFOCUSED:
+                passive = true;
+            case ACTIVE_FOCUSED:
+            case ACTIVE_UNFOCUSED:
+                if (mAutoFocusScanStartFrame != -1) {
+                    long frames = frameNumber - mAutoFocusScanStartFrame;
+                    long dt = SystemClock.uptimeMillis() - mAutoFocusScanStartTime;
+                    int fps = Math.round(frames * 1000f / dt);
+                    String report = String.format("%s scan: fps=%d frames=%d",
+                            passive ? "CAF" : "AF", fps, frames);
+                    Log.v(TAG, report);
+                    mUI.showDebugMessage(String.format("%d / %d", frames, fps));
+                    mAutoFocusScanStartFrame = -1;
+                }
+                break;
+        }
     }
 
     @Override
diff --git a/src/com/android/camera/CaptureModuleUI.java b/src/com/android/camera/CaptureModuleUI.java
index 9b3b6ab..67fb12f 100644
--- a/src/com/android/camera/CaptureModuleUI.java
+++ b/src/com/android/camera/CaptureModuleUI.java
@@ -25,7 +25,6 @@
 import android.view.TextureView;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.ImageView;
 
 import com.android.camera.debug.Log;
 import com.android.camera.ui.CountDownView;
@@ -33,7 +32,6 @@
 import com.android.camera.ui.PreviewOverlay.OnZoomChangedListener;
 import com.android.camera.ui.PreviewStatusListener;
 import com.android.camera.ui.ProgressOverlay;
-import com.android.camera.util.UsageStatistics;
 import com.android.camera2.R;
 
 /**
@@ -199,6 +197,14 @@
         mFocusUI.onFocusFailed();
     }
 
+    public void setPassiveFocusSuccess(boolean success) {
+        mFocusUI.setPassiveFocusSuccess(success);
+    }
+
+    public void showDebugMessage(String message) {
+        mFocusUI.showDebugMessage(message);
+    }
+
     public void setAutoFocusTarget(int x, int y, boolean isPassiveScan, int afSize, int aeSize) {
         mFocusUI.setFocusPosition(x, y, isPassiveScan, afSize, aeSize);
     }
diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java
index a48c11e..1c5e00a 100644
--- a/src/com/android/camera/FocusOverlayManager.java
+++ b/src/com/android/camera/FocusOverlayManager.java
@@ -118,6 +118,8 @@
         public void onFocusStarted();
         public void onFocusSucceeded();
         public void onFocusFailed();
+        public void setPassiveFocusSuccess(boolean success);
+        public void showDebugMessage(String message);
         public void pauseFaceDetection();
         public void resumeFaceDetection();
     }
diff --git a/src/com/android/camera/one/OneCamera.java b/src/com/android/camera/one/OneCamera.java
index ab0f95e..1b7ecca 100644
--- a/src/com/android/camera/one/OneCamera.java
+++ b/src/com/android/camera/one/OneCamera.java
@@ -204,8 +204,9 @@
          * Called when state of auto focus system changes.
          *
          * @param state Current auto focus state.
+         * @param frameNumber Frame number if available.
          */
-        public void onFocusStatusUpdate(AutoFocusState state);
+        public void onFocusStatusUpdate(AutoFocusState state, long frameNumber);
     }
 
     /**
diff --git a/src/com/android/camera/one/v2/OneCameraImpl.java b/src/com/android/camera/one/v2/OneCameraImpl.java
index 16a027f..e27755d 100644
--- a/src/com/android/camera/one/v2/OneCameraImpl.java
+++ b/src/com/android/camera/one/v2/OneCameraImpl.java
@@ -615,7 +615,7 @@
 
         // Report state change when AF state has changed.
         if (resultAFState != mLastResultAFState && mFocusStateListener != null) {
-            mFocusStateListener.onFocusStatusUpdate(resultAFState);
+            mFocusStateListener.onFocusStatusUpdate(resultAFState, result.getFrameNumber());
         }
         mLastResultAFState = resultAFState;
     }
diff --git a/src/com/android/camera/one/v2/OneCameraZslImpl.java b/src/com/android/camera/one/v2/OneCameraZslImpl.java
index ca3f9f3..34284dd 100644
--- a/src/com/android/camera/one/v2/OneCameraZslImpl.java
+++ b/src/com/android/camera/one/v2/OneCameraZslImpl.java
@@ -305,7 +305,8 @@
                             CaptureResult result) {
                         mFocusStateListener.onFocusStatusUpdate(
                                 AutoFocusHelper.stateFromCamera2State(
-                                        result.get(CaptureResult.CONTROL_AF_STATE)));
+                                        result.get(CaptureResult.CONTROL_AF_STATE)),
+                                result.getFrameNumber());
                     }
                 });
 
diff --git a/src/com/android/camera/ui/FocusOverlay.java b/src/com/android/camera/ui/FocusOverlay.java
index dd21650..bd913d4 100644
--- a/src/com/android/camera/ui/FocusOverlay.java
+++ b/src/com/android/camera/ui/FocusOverlay.java
@@ -48,15 +48,16 @@
     private final Rect mBounds = new Rect();
     private final ValueAnimator mFocusAnimation = new ValueAnimator();
 
-    private Paint mDebugPaint;
-    private Paint mDebugAEPaint;
+    private Paint mDebugSolidPaint;
+    private Paint mDebugCornersPaint;
+    private Paint mDebugTextPaint;
     private int mDebugStartColor;
-    private int mDebugPassiveColor;
     private int mDebugSuccessColor;
     private int mDebugFailColor;
-    private Rect mFocusDebugAFRect;
-    private Rect mFocusDebugAERect;
+    private Rect mFocusDebugSolidRect;
+    private Rect mFocusDebugCornersRect;
     private boolean mIsPassiveScan;
+    private String mDebugMessage;
 
     private int mPositionX;
     private int mPositionY;
@@ -75,18 +76,20 @@
         if (CAPTURE_DEBUG_UI) {
             Resources res = getResources();
             mDebugStartColor = res.getColor(R.color.focus_debug);
-            mDebugPassiveColor = res.getColor(R.color.focus_debug_light);
             mDebugSuccessColor = res.getColor(R.color.focus_debug_success);
             mDebugFailColor = res.getColor(R.color.focus_debug_fail);
-            mDebugPaint = new Paint();
-            mDebugPaint.setColor(res.getColor(R.color.focus_debug));
-            mDebugPaint.setAntiAlias(true);
-            mDebugPaint.setStyle(Paint.Style.STROKE);
-            mDebugPaint.setStrokeWidth(res.getDimension(R.dimen.focus_debug_stroke));
-            mDebugAEPaint = new Paint(mDebugPaint);
-            mDebugAEPaint.setColor(res.getColor(R.color.focus_debug));
-            mFocusDebugAFRect = new Rect();
-            mFocusDebugAERect = new Rect();
+            mDebugTextPaint= new Paint();
+            mDebugTextPaint.setColor(res.getColor(R.color.focus_debug_text));
+            mDebugTextPaint.setStyle(Paint.Style.FILL);
+            mDebugSolidPaint = new Paint();
+            mDebugSolidPaint.setColor(res.getColor(R.color.focus_debug));
+            mDebugSolidPaint.setAntiAlias(true);
+            mDebugSolidPaint.setStyle(Paint.Style.STROKE);
+            mDebugSolidPaint.setStrokeWidth(res.getDimension(R.dimen.focus_debug_stroke));
+            mDebugCornersPaint = new Paint(mDebugSolidPaint);
+            mDebugCornersPaint.setColor(res.getColor(R.color.focus_debug));
+            mFocusDebugSolidRect = new Rect();
+            mFocusDebugCornersRect = new Rect();
         }
     }
 
@@ -122,15 +125,24 @@
 
         if (CAPTURE_DEBUG_UI) {
             mFocusOuterRing.setBounds(0, 0, 0, 0);
-            mFocusDebugAFRect.set(x - aFsize / 2, y - aFsize / 2, x + aFsize / 2, y + aFsize / 2);
-            // If AE region is different size than AF region and active scan.
-            if (aFsize != aEsize && !isPassiveScan) {
-                mFocusDebugAERect.set(x - aEsize / 2, y - aEsize / 2, x + aEsize / 2,
-                        y + aEsize / 2);
+            if (isPassiveScan) {
+                // Use AE rect only.
+                mFocusDebugSolidRect.setEmpty();
+                int avg = (aFsize + aEsize) / 2;
+                mFocusDebugCornersRect.set(x - avg / 2, y - avg / 2, x + avg / 2, y + avg / 2);
             } else {
-                mFocusDebugAERect.set(0, 0, 0, 0);
+                mFocusDebugSolidRect.set(x - aFsize / 2, y - aFsize / 2, x + aFsize / 2,
+                        y + aFsize / 2);
+                // If AE region is different size than AF region and active scan.
+                if (aFsize != aEsize) {
+                    mFocusDebugCornersRect.set(x - aEsize / 2, y - aEsize / 2, x + aEsize / 2,
+                            y + aEsize / 2);
+                } else {
+                    mFocusDebugCornersRect.setEmpty();
+                }
             }
-            mDebugPaint.setColor(isPassiveScan ? mDebugPassiveColor : mDebugStartColor);
+            mDebugSolidPaint.setColor(mDebugStartColor);
+            mDebugCornersPaint.setColor(mDebugStartColor);
         }
 
         if (getVisibility() != VISIBLE) {
@@ -139,6 +151,15 @@
         invalidate();
     }
 
+    /**
+     * This is called in:
+     * <ul>
+     * <li>API1 non-CAF after autoFocus().</li>
+     * <li>API1 CAF mode for onAutoFocusMoving(true).</li>
+     * <li>API2 for transition to ACTIVE_SCANNING or PASSIVE_SCANNING.</li>
+     * <ul>
+     * TODO after PhotoModule/GcamModule deprecation: Do not use this for CAF.
+     */
     @Override
     public void onFocusStarted() {
         mShowIndicator = true;
@@ -152,28 +173,68 @@
             }
         });
         mFocusAnimation.start();
+        if (CAPTURE_DEBUG_UI) {
+            mDebugMessage = null;
+        }
     }
 
+    /**
+     * This is called in:
+     * <ul>
+     * <li>API1 non-CAF for onAutoFocus(true).</li>
+     * <li>API2 non-CAF for transition to FOCUSED_LOCKED.</li>
+     * <li>API1 CAF mode for onAutoFocusMoving(false).</li>
+     * <ul>
+     * TODO after PhotoModule/GcamModule deprecation: Do not use this for CAF.
+     */
     @Override
     public void onFocusSucceeded() {
         mFocusAnimation.cancel();
         mShowIndicator = false;
         if (CAPTURE_DEBUG_UI && !mIsPassiveScan) {
-            mDebugPaint.setColor(mDebugSuccessColor);
+            mDebugSolidPaint.setColor(mDebugSuccessColor);
         }
         invalidate();
     }
 
+    /**
+     * This is called in:
+     * <ul>
+     * <li>API1 non-CAF for onAutoFocus(false).</li>
+     * <li>API2 non-CAF for transition to NOT_FOCUSED_LOCKED.</li>
+     * <ul>
+     */
     @Override
     public void onFocusFailed() {
         mFocusAnimation.cancel();
         mShowIndicator = false;
         if (CAPTURE_DEBUG_UI && !mIsPassiveScan) {
-            mDebugPaint.setColor(mDebugFailColor);
+            mDebugSolidPaint.setColor(mDebugFailColor);
         }
         invalidate();
     }
 
+    /**
+     * This is called in:
+     * API2 for CAF state changes to PASSIVE_FOCUSED or PASSIVE_UNFOCUSED.
+     */
+    @Override
+    public void setPassiveFocusSuccess(boolean success) {
+        mFocusAnimation.cancel();
+        mShowIndicator = false;
+        if (CAPTURE_DEBUG_UI) {
+            mDebugCornersPaint.setColor(success ? mDebugSuccessColor : mDebugFailColor);
+        }
+        invalidate();
+    }
+
+    @Override
+    public void showDebugMessage(String message) {
+        if (CAPTURE_DEBUG_UI) {
+            mDebugMessage = message;
+        }
+    }
+
     @Override
     public void pauseFaceDetection() {
         // TODO: Add face detection support.
@@ -195,18 +256,23 @@
             mFocusIndicator.draw(canvas);
             canvas.restore();
         }
-        if (CAPTURE_DEBUG_UI && mFocusDebugAFRect != null) {
-            canvas.drawRect(mFocusDebugAFRect, mDebugPaint);
-            float delta = 0.1f * mFocusDebugAERect.width();
-            float left = mFocusDebugAERect.left;
-            float top = mFocusDebugAERect.top;
-            float right = mFocusDebugAERect.right;
-            float bot = mFocusDebugAERect.bottom;
+        if (CAPTURE_DEBUG_UI) {
+            canvas.drawRect(mFocusDebugSolidRect, mDebugSolidPaint);
+            float delta = 0.1f * mFocusDebugCornersRect.width();
+            float left = mFocusDebugCornersRect.left;
+            float top = mFocusDebugCornersRect.top;
+            float right = mFocusDebugCornersRect.right;
+            float bot = mFocusDebugCornersRect.bottom;
 
-            canvas.drawLines(new float[]{left, top + delta, left, top, left, top, left + delta, top}, mDebugAEPaint);
-            canvas.drawLines(new float[]{right, top + delta, right, top, right, top, right - delta, top}, mDebugAEPaint);
-            canvas.drawLines(new float[]{left, bot - delta, left, bot, left, bot, left + delta, bot}, mDebugAEPaint);
-            canvas.drawLines(new float[]{right, bot - delta, right, bot, right, bot, right - delta, bot}, mDebugAEPaint);
+            canvas.drawLines(new float[]{left, top + delta, left, top, left, top, left + delta, top}, mDebugCornersPaint);
+            canvas.drawLines(new float[]{right, top + delta, right, top, right, top, right - delta, top}, mDebugCornersPaint);
+            canvas.drawLines(new float[]{left, bot - delta, left, bot, left, bot, left + delta, bot}, mDebugCornersPaint);
+            canvas.drawLines(new float[]{right, bot - delta, right, bot, right, bot, right - delta, bot}, mDebugCornersPaint);
+
+            if (mDebugMessage != null) {
+                mDebugTextPaint.setTextSize(40);
+                canvas.drawText(mDebugMessage, left - 4, bot + 44, mDebugTextPaint);
+            }
         }
     }
 }