From 06fbf93f0687c2c93f8fb62b6d73dbf0a8a39d3f Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Wed, 16 Oct 2019 20:47:02 +0200 Subject: [PATCH] Make Holder.getLastResult nullable. Fixes #621 --- .../cameraview/engine/Camera2Engine.java | 2 +- .../engine/action/ActionHolder.java | 3 +- .../cameraview/engine/lock/ExposureLock.java | 14 ++++++--- .../cameraview/engine/lock/FocusLock.java | 29 +++++++++++-------- .../engine/lock/WhiteBalanceLock.java | 15 +++++++--- .../engine/meter/ExposureMeter.java | 14 ++++++--- .../engine/meter/ExposureReset.java | 5 ++-- .../cameraview/engine/meter/FocusMeter.java | 18 ++++++++---- .../cameraview/engine/meter/FocusReset.java | 4 ++- .../engine/meter/WhiteBalanceMeter.java | 15 +++++++--- .../picture/Snapshot2PictureRecorder.java | 8 ++++- 11 files changed, 87 insertions(+), 40 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java index 71420ed3..ac657b46 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -1446,7 +1446,7 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv return mCameraCharacteristics; } - @NonNull + @Nullable @Override public TotalCaptureResult getLastResult(@NonNull Action action) { return mLastRepeatingResult; diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/ActionHolder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/ActionHolder.java index 792aa590..7da89570 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/ActionHolder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/ActionHolder.java @@ -8,6 +8,7 @@ import android.hardware.camera2.TotalCaptureResult; import android.os.Build; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; /** @@ -51,7 +52,7 @@ public interface ActionHolder { * @param action action * @return last result */ - @NonNull + @Nullable TotalCaptureResult getLastResult(@NonNull Action action); /** diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/ExposureLock.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/ExposureLock.java index dd3f91ab..923a89dd 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/ExposureLock.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/ExposureLock.java @@ -40,10 +40,16 @@ public class ExposureLock extends BaseLock { @Override protected boolean checkShouldSkip(@NonNull ActionHolder holder) { - Integer aeState = holder.getLastResult(this).get(CaptureResult.CONTROL_AE_STATE); - boolean result = aeState != null && aeState == CaptureResult.CONTROL_AE_STATE_LOCKED; - LOG.i("checkShouldSkip:", result); - return result; + CaptureResult lastResult = holder.getLastResult(this); + if (lastResult != null) { + Integer aeState = lastResult.get(CaptureResult.CONTROL_AE_STATE); + boolean result = aeState != null && aeState == CaptureResult.CONTROL_AE_STATE_LOCKED; + LOG.i("checkShouldSkip:", result); + return result; + } else { + LOG.i("checkShouldSkip: false - lastResult is null."); + return false; + } } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/FocusLock.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/FocusLock.java index fc0d69a5..408bea2b 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/FocusLock.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/FocusLock.java @@ -35,18 +35,23 @@ public class FocusLock extends BaseLock { @Override protected boolean checkShouldSkip(@NonNull ActionHolder holder) { CaptureResult lastResult = holder.getLastResult(this); - Integer afState = lastResult.get(CaptureResult.CONTROL_AF_STATE); - boolean afStateOk = afState != null && - (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED - || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED - || afState == CaptureResult.CONTROL_AF_STATE_INACTIVE - || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED - || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED); - Integer afMode = lastResult.get(CaptureResult.CONTROL_AF_MODE); - boolean afModeOk = afMode != null && afMode == CaptureResult.CONTROL_AF_MODE_AUTO; - boolean result = afStateOk && afModeOk; - LOG.i("checkShouldSkip:", result); - return result; + if (lastResult != null) { + Integer afState = lastResult.get(CaptureResult.CONTROL_AF_STATE); + boolean afStateOk = afState != null && + (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED + || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED + || afState == CaptureResult.CONTROL_AF_STATE_INACTIVE + || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED + || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED); + Integer afMode = lastResult.get(CaptureResult.CONTROL_AF_MODE); + boolean afModeOk = afMode != null && afMode == CaptureResult.CONTROL_AF_MODE_AUTO; + boolean result = afStateOk && afModeOk; + LOG.i("checkShouldSkip:", result); + return result; + } else { + LOG.i("checkShouldSkip: false - lastResult is null."); + return false; + } } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/WhiteBalanceLock.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/WhiteBalanceLock.java index c56dcc64..ae547933 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/WhiteBalanceLock.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/WhiteBalanceLock.java @@ -33,10 +33,17 @@ public class WhiteBalanceLock extends BaseLock { @Override protected boolean checkShouldSkip(@NonNull ActionHolder holder) { - Integer awbState = holder.getLastResult(this).get(CaptureResult.CONTROL_AWB_STATE); - boolean result = awbState != null && awbState == CaptureRequest.CONTROL_AWB_STATE_LOCKED; - LOG.i("checkShouldSkip:", result); - return result; + CaptureResult lastResult = holder.getLastResult(this); + if (lastResult != null) { + Integer awbState = lastResult.get(CaptureResult.CONTROL_AWB_STATE); + boolean result = awbState != null + && awbState == CaptureRequest.CONTROL_AWB_STATE_LOCKED; + LOG.i("checkShouldSkip:", result); + return result; + } else { + LOG.i("checkShouldSkip: false - lastResult is null."); + return false; + } } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureMeter.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureMeter.java index 64c6d361..ed904932 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureMeter.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureMeter.java @@ -50,10 +50,16 @@ public class ExposureMeter extends BaseMeter { @Override protected boolean checkShouldSkip(@NonNull ActionHolder holder) { - Integer aeState = holder.getLastResult(this).get(CaptureResult.CONTROL_AE_STATE); - boolean result = aeState != null && aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED; - LOG.i("checkShouldSkip:", result); - return result; + CaptureResult lastResult = holder.getLastResult(this); + if (lastResult != null) { + Integer aeState = lastResult.get(CaptureResult.CONTROL_AE_STATE); + boolean result = aeState != null && aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED; + LOG.i("checkShouldSkip:", result); + return result; + } else { + LOG.i("checkShouldSkip: false - lastResult is null."); + return false; + } } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureReset.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureReset.java index c3755df7..fc676d3b 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureReset.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureReset.java @@ -37,8 +37,9 @@ public class ExposureReset extends BaseReset { } // NOTE: precapture might not be supported, in which case I think it will be ignored. - Integer trigger = holder.getLastResult(this) - .get(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER); + CaptureResult lastResult = holder.getLastResult(this); + Integer trigger = lastResult == null ? null + : lastResult.get(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER); LOG.i("onStarted:", "last precapture trigger is", trigger); if (trigger != null && trigger == CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START) { LOG.i("onStarted:", "canceling precapture."); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusMeter.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusMeter.java index 4d5c2f85..e7b59bfd 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusMeter.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusMeter.java @@ -40,12 +40,18 @@ public class FocusMeter extends BaseMeter { @Override protected boolean checkShouldSkip(@NonNull ActionHolder holder) { - Integer afState = holder.getLastResult(this).get(CaptureResult.CONTROL_AF_STATE); - boolean result = afState != null && - (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || - afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED); - LOG.i("checkShouldSkip:", result); - return result; + CaptureResult lastResult = holder.getLastResult(this); + if (lastResult != null) { + Integer afState = lastResult.get(CaptureResult.CONTROL_AF_STATE); + boolean result = afState != null && + (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || + afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED); + LOG.i("checkShouldSkip:", result); + return result; + } else { + LOG.i("checkShouldSkip: false - lastResult is null."); + return false; + } } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusReset.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusReset.java index c1d1883a..afe4e49d 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusReset.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusReset.java @@ -36,7 +36,9 @@ public class FocusReset extends BaseReset { } // NOTE: trigger might not be supported, in which case I think it will be ignored. - Integer trigger = holder.getLastResult(this).get(CaptureResult.CONTROL_AF_TRIGGER); + CaptureResult lastResult = holder.getLastResult(this); + Integer trigger = lastResult == null ? null + : lastResult.get(CaptureResult.CONTROL_AF_TRIGGER); LOG.w("onStarted:", "last focus trigger is", trigger); if (trigger != null && trigger == CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START) { holder.getBuilder(this).set(CaptureRequest.CONTROL_AF_TRIGGER, diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/WhiteBalanceMeter.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/WhiteBalanceMeter.java index 0217b815..df13cbb2 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/WhiteBalanceMeter.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/WhiteBalanceMeter.java @@ -40,10 +40,17 @@ public class WhiteBalanceMeter extends BaseMeter { @Override protected boolean checkShouldSkip(@NonNull ActionHolder holder) { - Integer awbState = holder.getLastResult(this).get(CaptureResult.CONTROL_AWB_STATE); - boolean result = awbState != null && awbState == CaptureRequest.CONTROL_AWB_STATE_CONVERGED; - LOG.i("checkShouldSkip:", result); - return result; + CaptureResult lastResult = holder.getLastResult(this); + if (lastResult != null) { + Integer awbState = lastResult.get(CaptureResult.CONTROL_AWB_STATE); + boolean result = awbState != null + && awbState == CaptureRequest.CONTROL_AWB_STATE_CONVERGED; + LOG.i("checkShouldSkip:", result); + return result; + } else { + LOG.i("checkShouldSkip: false - lastResult is null."); + return false; + } } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Snapshot2PictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Snapshot2PictureRecorder.java index c618b359..8e074ff3 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Snapshot2PictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Snapshot2PictureRecorder.java @@ -106,7 +106,13 @@ public class Snapshot2PictureRecorder extends SnapshotGlPictureRecorder { } }); - Integer aeState = mHolder.getLastResult(mAction).get(CaptureResult.CONTROL_AE_STATE); + CaptureResult lastResult = mHolder.getLastResult(mAction); + if (lastResult == null) { + LOG.w("Picture snapshot requested very early, before the first preview frame.", + "Metering might not work as intended."); + } + Integer aeState = lastResult == null ? null + : lastResult.get(CaptureResult.CONTROL_AE_STATE); mActionNeeded = engine.getPictureSnapshotMetering() && aeState != null && aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED;