From b2ef15eda138bab58bbded7c9831e5599d4c835c Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Wed, 20 Apr 2016 17:02:20 -0700 Subject: Snap: Add support for focus distance * Hook up available metadata to the new focus manager. Change-Id: I793df67a2682d8bb2dee994193111227dd8c8d5a --- src/com/android/camera/FocusOverlayManager.java | 92 +++++++++++++++++++++++++ src/com/android/camera/PhotoModule.java | 20 +++++- src/com/android/camera/PhotoUI.java | 1 - src/com/android/camera/VideoModule.java | 16 +++++ src/com/android/camera/VideoUI.java | 1 - 5 files changed, 127 insertions(+), 3 deletions(-) diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java index 20d5cff62..6c6769e5e 100755 --- a/src/com/android/camera/FocusOverlayManager.java +++ b/src/com/android/camera/FocusOverlayManager.java @@ -31,6 +31,7 @@ import org.codeaurora.snapcam.R; import com.android.camera.app.CameraApp; import com.android.camera.ui.focus.CameraCoordinateTransformer; import com.android.camera.ui.focus.FocusRing; +import com.android.camera.ui.motion.LinearScale; import com.android.camera.util.CameraUtil; import com.android.camera.util.UsageStatistics; @@ -115,6 +116,7 @@ public class FocusOverlayManager { public void startFaceDetection(); public void stopFaceDetection(); public void setFocusParameters(); + public void setFocusRatio(float ratio); } private class MainHandler extends Handler { @@ -282,6 +284,7 @@ public class FocusOverlayManager { } public void onAutoFocus(boolean focused, boolean shutterButtonPressed) { + updateFocusDistance(); if (mState == STATE_FOCUSING_SNAP_ON_FINISH) { // Take the picture no matter focus succeeds or fails. No need // to play the AF sound if we're about to play the shutter @@ -344,6 +347,7 @@ public class FocusOverlayManager { } mHandler.sendEmptyMessageDelayed(RESET_FACE_DETECTION, RESET_FACE_DETECTION_DELAY); + updateFocusDistance(); mPreviousMoving = moving; } @@ -618,4 +622,92 @@ public class FocusOverlayManager { return mTouchAFRunning; } + private static class FocusInfo { + public final float near; + public final float far; + public final float current; + + public FocusInfo(float _near, float _far, float _current) { + near = _near; + far = _far; + current = _current; + } + } + + private FocusInfo getFocusInfoFromParameters( + String currentParam, String minParam, String maxParam) { + try { + String current = mParameters.get(currentParam); + if (current != null) { + float min = Float.parseFloat(mParameters.get(minParam)); + float max = Float.parseFloat(mParameters.get(maxParam)); + if (!(min == 0.0f && max == 0.0f)) { + return new FocusInfo(min, max, Float.parseFloat(current)); + } + } + } catch (Exception e) { + // skip it + } + return null; + } + + private FocusInfo getFocusInfo() { + // focus positon is horrifically buggy on some HALs. try to + // make the best of it and attempt a few different techniques + // to get an accurate measurement + + // older QCOM (Bacon) + FocusInfo info = getFocusInfoFromParameters("current-focus-position", + "min-focus-pos-index", "max-focus-pos-index"); + if (info != null) { + return info; + } + + // newer QCOM (Crackling) + info = getFocusInfoFromParameters("cur-focus-scale", + "min-focus-pos-ratio", "max-focus-pos-ratio"); + if (info != null) { + return info; + } + + return null; + } + + /** + * Compute the focus range from the camera characteristics and build + * a linear scale model that maps a focus distance to a ratio between + * the min and max range. + */ + private LinearScale getDiopterToRatioCalculator(FocusInfo focusInfo) { + // From the android documentation: + // + // 0.0f represents farthest focus, and LENS_INFO_MINIMUM_FOCUS_DISTANCE + // represents the nearest focus the device can achieve. + // + // Example: + // + // Infinity Hyperfocal Minimum Camera + // <----------|-----------------------------| | + // [0.0] [0.31] [14.29] + if (focusInfo.near == 0.0f && focusInfo.far == 0.0f) { + return new LinearScale(0, 0, 0, 0); + } + + if (focusInfo.near > focusInfo.far) { + return new LinearScale(focusInfo.far, focusInfo.near, 0, 1); + } + + return new LinearScale(focusInfo.near, focusInfo.far, 0, 1); + } + + private void updateFocusDistance() { + final FocusInfo focusInfo = getFocusInfo(); + if (focusInfo != null) { + LinearScale range = getDiopterToRatioCalculator(focusInfo); + if (range.isInDomain(focusInfo.current) && (mFocusRing.isPassiveFocusRunning() || + mFocusRing.isActiveFocusRunning())) { + mListener.setFocusRatio(range.scale(focusInfo.current)); + } + } + } } diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index e7e01fbfa..609b54a75 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -167,6 +167,7 @@ public class PhotoModule private static final int ON_PREVIEW_STARTED = 13; private static final int INSTANT_CAPTURE = 14; private static final int UNLOCK_CAM_SHUTTER = 15; + private static final int SET_FOCUS_RATIO = 16; private static final int NO_DEPTH_EFFECT = 0; private static final int DEPTH_EFFECT_SUCCESS = 1; @@ -176,7 +177,6 @@ public class PhotoModule private static final int SUBJECT_NOT_FOUND = 5; private static final int TOUCH_TO_FOCUS = 6; - // The subset of parameters we need to update in setCameraParameters(). private static final int UPDATE_PARAM_INITIALIZE = 1; private static final int UPDATE_PARAM_ZOOM = 2; @@ -574,6 +574,11 @@ public class PhotoModule mUI.enableShutter(true); break; } + + case SET_FOCUS_RATIO: { + mUI.getFocusRing().setRadiusRatio((Float)msg.obj); + break; + } } } } @@ -1061,6 +1066,14 @@ public class PhotoModule } } + @Override + public void setFocusRatio(float ratio) { + mHandler.removeMessages(SET_FOCUS_RATIO); + Message m = mHandler.obtainMessage(SET_FOCUS_RATIO); + m.obj = ratio; + mHandler.sendMessage(m); + } + // TODO: need to check cached background apps memory and longshot ION memory private boolean isLongshotNeedCancel() { @@ -1786,6 +1799,8 @@ public class PhotoModule setCameraState(IDLE); break; } + mCameraDevice.refreshParameters(); + mFocusManager.setParameters(mCameraDevice.getParameters()); mFocusManager.onAutoFocus(focused, mUI.isShutterPressed()); } } @@ -1796,6 +1811,8 @@ public class PhotoModule @Override public void onAutoFocusMoving( boolean moving, CameraProxy camera) { + mCameraDevice.refreshParameters(); + mFocusManager.setParameters(mCameraDevice.getParameters()); mFocusManager.onAutoFocusMoving(moving); } } @@ -4498,6 +4515,7 @@ public class PhotoModule CameraUtil.dumpParameters(mParameters); mCameraDevice.setParameters(mParameters); + mFocusManager.setParameters(mParameters); // Switch to gcam module if HDR+ was selected if (doModeSwitch && !mIsImageCaptureIntent) { diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index 9fb121ff8..736221c5f 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -67,7 +67,6 @@ import com.android.camera.ui.CameraRootView; import com.android.camera.ui.CountDownView; import com.android.camera.ui.CountDownView.OnCountDownFinishedListener; import com.android.camera.ui.FaceView; -import com.android.camera.ui.FocusIndicator; import com.android.camera.ui.ListSubMenu; import com.android.camera.ui.ModuleSwitcher; import com.android.camera.ui.PieRenderer; diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 1155899d9..28766f4aa 100644 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -108,6 +108,7 @@ public class VideoModule implements CameraModule, private static final int SWITCH_CAMERA = 8; private static final int SWITCH_CAMERA_START_ANIMATION = 9; private static final int HANDLE_FLASH_TORCH_DELAY = 10; + private static final int SET_FOCUS_RATIO = 11; private static final int SCREEN_DELAY = 2 * 60 * 1000; @@ -446,6 +447,11 @@ public class VideoModule implements CameraModule, break; } + case SET_FOCUS_RATIO: { + mUI.getFocusRing().setRadiusRatio((Float)msg.obj); + break; + } + default: Log.v(TAG, "Unhandled message: " + msg.what); break; @@ -962,10 +968,20 @@ public class VideoModule implements CameraModule, if (mPaused) return; //setCameraState(IDLE); + mCameraDevice.refreshParameters(); + mFocusManager.setParameters(mCameraDevice.getParameters()); mFocusManager.onAutoFocus(focused, false); } } + @Override + public void setFocusRatio(float ratio) { + mHandler.removeMessages(SET_FOCUS_RATIO); + Message m = mHandler.obtainMessage(SET_FOCUS_RATIO); + m.obj = ratio; + mHandler.sendMessage(m); + } + private void readVideoPreferences() { // The preference stores values from ListPreference and is thus string type for all values. // We need to convert it to int manually. diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java index 6dc041d67..0c1840afd 100755 --- a/src/com/android/camera/VideoUI.java +++ b/src/com/android/camera/VideoUI.java @@ -53,7 +53,6 @@ import com.android.camera.ui.AbstractSettingPopup; import com.android.camera.ui.CameraControls; import com.android.camera.ui.CameraRootView; import com.android.camera.ui.FaceView; -import com.android.camera.ui.FocusIndicator; import com.android.camera.ui.ListSubMenu; import com.android.camera.ui.ModuleSwitcher; import com.android.camera.ui.PieRenderer; -- cgit v1.2.3