Add comments to the action package

pull/580/head
Mattia Iavarone 6 years ago
parent 0ce7d30319
commit 03b0fb5971
  1. 50
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/Action.java
  2. 12
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/ActionCallback.java
  3. 49
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/ActionHolder.java
  4. 8
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/ActionWrapper.java
  5. 17
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/Actions.java
  6. 30
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/BaseAction.java
  7. 11
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/CompletionCallback.java
  8. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/TimeoutAction.java
  9. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/ExposureLock.java
  10. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/FocusLock.java
  11. 6
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/LockAction.java
  12. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/lock/WhiteBalanceLock.java

@ -1,5 +1,7 @@
package com.otaliastudios.cameraview.engine.action; package com.otaliastudios.cameraview.engine.action;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult; import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.TotalCaptureResult;
@ -8,22 +10,70 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
/**
* The Action class encapsulates logic for completing an action in a Camera2 environment.
* In this case, we are often interested in constantly receiving the {@link CaptureResult}
* and {@link CaptureRequest} callbacks, as well as applying changes to a {@link CaptureRequest.Builder}
* and having them applied to the sensor.
*
* The Action class receives the given callbacks and can operate over the engine
* through the {@link ActionHolder} object.
*
* Each Action operates on a given state in a given moment. This base class offers the
* {@link #STATE_COMPLETED} state which is common to all actions.
*
* See {@link BaseAction} for a base implementation.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public interface Action { public interface Action {
int STATE_COMPLETED = Integer.MAX_VALUE; int STATE_COMPLETED = Integer.MAX_VALUE;
/**
* Returns the current state.
* @return the state
*/
int getState(); int getState();
/**
* Starts this action.
* @param holder the holder
*/
void start(@NonNull ActionHolder holder); void start(@NonNull ActionHolder holder);
/**
* Adds an {@link ActionCallback} to receive state
* change events.
* @param callback a callback
*/
void addCallback(@NonNull ActionCallback callback); void addCallback(@NonNull ActionCallback callback);
/**
* Removes a previously added callback.
* @param callback a callback
*/
void removeCallback(@NonNull ActionCallback callback); void removeCallback(@NonNull ActionCallback callback);
/**
* Called from {@link CaptureCallback#onCaptureStarted(CameraCaptureSession, CaptureRequest, long, long)}.
* @param holder the holder
* @param request the request
*/
void onCaptureStarted(@NonNull ActionHolder holder, @NonNull CaptureRequest request); void onCaptureStarted(@NonNull ActionHolder holder, @NonNull CaptureRequest request);
/**
* Called from {@link CaptureCallback#onCaptureProgressed(CameraCaptureSession, CaptureRequest, CaptureResult)}.
* @param holder the holder
* @param request the request
* @param result the result
*/
void onCaptureProgressed(@NonNull ActionHolder holder, @NonNull CaptureRequest request, @NonNull CaptureResult result); void onCaptureProgressed(@NonNull ActionHolder holder, @NonNull CaptureRequest request, @NonNull CaptureResult result);
/**
* Called from {@link CaptureCallback#onCaptureCompleted(CameraCaptureSession, CaptureRequest, TotalCaptureResult)}.
* @param holder the holder
* @param request the request
* @param result the result
*/
void onCaptureCompleted(@NonNull ActionHolder holder, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result); void onCaptureCompleted(@NonNull ActionHolder holder, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result);
} }

@ -5,7 +5,19 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
/**
* A callback for {@link Action} state changes.
* See the action class.
*
* See also {@link CompletionCallback}.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public interface ActionCallback { public interface ActionCallback {
/**
* Action state has just changed.
* @param action action
* @param state new state
*/
void onActionStateChanged(@NonNull Action action, int state); void onActionStateChanged(@NonNull Action action, int state);
} }

@ -10,23 +10,72 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
/**
* The holder of {@link Action}.
*
* This class should keep a list or set of currently running actions, and offers
* to them the base Camera2 objects that are needed to apply changes.
*
* This class, or an holder of it, should also forward the capture callbacks
* to all {@link Action}s. See {@link com.otaliastudios.cameraview.engine.Camera2Engine} for
* our implementation.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public interface ActionHolder { public interface ActionHolder {
/**
* Adds a new action
* @param action action
*/
void addAction(@NonNull Action action); void addAction(@NonNull Action action);
/**
* Removes a previously added action
* @param action action
*/
void removeAction(@NonNull Action action); void removeAction(@NonNull Action action);
/**
* Returns the {@link CameraCharacteristics} of the current
* camera device.
* @param action action
* @return characteristics
*/
@NonNull @NonNull
CameraCharacteristics getCharacteristics(@NonNull Action action); CameraCharacteristics getCharacteristics(@NonNull Action action);
/**
* Returns the latest {@link TotalCaptureResult}. Can be used
* by actions to start querying the state before receiving their
* first frame.
* @param action action
* @return last result
*/
@NonNull @NonNull
TotalCaptureResult getLastResult(@NonNull Action action); TotalCaptureResult getLastResult(@NonNull Action action);
/**
* Returns the current {@link CaptureRequest.Builder} so that
* actions can apply changes to it and later submit them.
* @param action action
* @return the builder
*/
@NonNull @NonNull
CaptureRequest.Builder getBuilder(@NonNull Action action); CaptureRequest.Builder getBuilder(@NonNull Action action);
/**
* Applies the current builder (as per {@link #getBuilder(Action)})
* as a repeating request on the preview.
* @param source action
*/
void applyBuilder(@NonNull Action source); void applyBuilder(@NonNull Action source);
/**
* Applies the given builder as a single capture request.
* Callers can catch the exception and choose what to do.
* @param source action
* @param builder builder
* @throws CameraAccessException camera exception
*/
void applyBuilder(@NonNull Action source, @NonNull CaptureRequest.Builder builder) throws CameraAccessException; void applyBuilder(@NonNull Action source, @NonNull CaptureRequest.Builder builder) throws CameraAccessException;
} }

@ -8,9 +8,17 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
/**
* A simple wrapper around a {@link BaseAction}.
* This can be used to add functionality around a base action.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public abstract class ActionWrapper extends BaseAction { public abstract class ActionWrapper extends BaseAction {
/**
* Should return the wrapped action.
* @return the wrapped action
*/
@NonNull @NonNull
public abstract BaseAction getAction(); public abstract BaseAction getAction();

@ -11,14 +11,31 @@ import androidx.annotation.RequiresApi;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
/**
* Utilities for creating {@link Action} sequences.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class Actions { public class Actions {
/**
* Creates a {@link BaseAction} that executes all the child actions
* together, at the same time, and completes once all of them are
* completed.
* @param actions input actions
* @return a new action
*/
@NonNull @NonNull
public static BaseAction together(@NonNull BaseAction... actions) { public static BaseAction together(@NonNull BaseAction... actions) {
return new TogetherAction(Arrays.asList(actions)); return new TogetherAction(Arrays.asList(actions));
} }
/**
* Creates a {@link BaseAction} that executes all the child actions
* in sequence, waiting for the first to complete, then going on with
* the second and so on, finally completing when all are completed.
* @param actions input actions
* @return a new action
*/
@NonNull @NonNull
public static BaseAction sequence(@NonNull BaseAction... actions) { public static BaseAction sequence(@NonNull BaseAction... actions) {
return new SequenceAction(Arrays.asList(actions)); return new SequenceAction(Arrays.asList(actions));

@ -11,6 +11,17 @@ import androidx.annotation.RequiresApi;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* The base implementation of {@link Action} that should always be subclassed,
* instead of implementing the root interface itself.
*
* It holds a list of callbacks and dispatches events to them, plus it cares about
* its own lifecycle:
* - when {@link #start(ActionHolder)} is called, we add ourselves to the holder list
* - when {@link #STATE_COMPLETED} is reached, we remove ouverselves from the holder list
*
* This is very important in all cases.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public abstract class BaseAction implements Action { public abstract class BaseAction implements Action {
@ -30,6 +41,11 @@ public abstract class BaseAction implements Action {
onStart(holder); onStart(holder);
} }
/**
* Action was started and will soon receive events from the
* holder stream.
* @param holder holder
*/
protected void onStart(@NonNull ActionHolder holder) { protected void onStart(@NonNull ActionHolder holder) {
// Overrideable // Overrideable
} }
@ -49,6 +65,11 @@ public abstract class BaseAction implements Action {
// Overrideable // Overrideable
} }
/**
* Called by subclasses to notify of their state. If state is {@link #STATE_COMPLETED},
* this removes this action from the holder.
* @param newState new state
*/
protected void setState(int newState) { protected void setState(int newState) {
if (newState != state) { if (newState != state) {
state = newState; state = newState;
@ -61,10 +82,19 @@ public abstract class BaseAction implements Action {
} }
} }
/**
* Whether this action has reached the completed state.
* @return true if completed
*/
@SuppressWarnings("WeakerAccess")
public boolean isCompleted() { public boolean isCompleted() {
return state == STATE_COMPLETED; return state == STATE_COMPLETED;
} }
/**
* Returns the holder.
* @return the holder
*/
@NonNull @NonNull
protected ActionHolder getHolder() { protected ActionHolder getHolder() {
return holder; return holder;

@ -5,16 +5,23 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
/**
* A special {@link ActionCallback} that just checks for the
* completed state. Handy as an inner anonymous class.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public abstract class CompletionCallback implements ActionCallback { public abstract class CompletionCallback implements ActionCallback {
@Override @Override
public void onActionStateChanged(@NonNull Action action, int state) { public final void onActionStateChanged(@NonNull Action action, int state) {
if (state == Action.STATE_COMPLETED) { if (state == Action.STATE_COMPLETED) {
onActionCompleted(action); onActionCompleted(action);
} }
} }
@SuppressWarnings("WeakerAccess") /**
* The given action has just reached the completed state.
* @param action action
*/
protected abstract void onActionCompleted(@NonNull Action action); protected abstract void onActionCompleted(@NonNull Action action);
} }

@ -7,6 +7,10 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
/**
* An {@link Action} that wraps another, and forces the completion
* after the given timeout in milliseconds is reached.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class TimeoutAction extends ActionWrapper { public class TimeoutAction extends ActionWrapper {

@ -13,9 +13,9 @@ import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.engine.action.ActionHolder; import com.otaliastudios.cameraview.engine.action.ActionHolder;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class AutoExposureLock extends BaseLock { public class ExposureLock extends BaseLock {
private final static String TAG = AutoExposureLock.class.getSimpleName(); private final static String TAG = ExposureLock.class.getSimpleName();
private final static CameraLogger LOG = CameraLogger.create(TAG); private final static CameraLogger LOG = CameraLogger.create(TAG);
@Override @Override

@ -13,9 +13,9 @@ import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.engine.action.ActionHolder; import com.otaliastudios.cameraview.engine.action.ActionHolder;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class AutoFocusLock extends BaseLock { public class FocusLock extends BaseLock {
private final static String TAG = AutoFocusLock.class.getSimpleName(); private final static String TAG = FocusLock.class.getSimpleName();
private final static CameraLogger LOG = CameraLogger.create(TAG); private final static CameraLogger LOG = CameraLogger.create(TAG);
@Override @Override

@ -13,9 +13,9 @@ import com.otaliastudios.cameraview.engine.action.BaseAction;
public class LockAction extends ActionWrapper { public class LockAction extends ActionWrapper {
private final BaseAction action = Actions.together( private final BaseAction action = Actions.together(
new AutoExposureLock(), new ExposureLock(),
new AutoFocusLock(), new FocusLock(),
new AutoWhiteBalanceLock() new WhiteBalanceLock()
); );
@NonNull @NonNull

@ -13,9 +13,9 @@ import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.engine.action.ActionHolder; import com.otaliastudios.cameraview.engine.action.ActionHolder;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class AutoWhiteBalanceLock extends BaseLock { public class WhiteBalanceLock extends BaseLock {
private final static String TAG = AutoWhiteBalanceLock.class.getSimpleName(); private final static String TAG = WhiteBalanceLock.class.getSimpleName();
private final static CameraLogger LOG = CameraLogger.create(TAG); private final static CameraLogger LOG = CameraLogger.create(TAG);
@Override @Override
Loading…
Cancel
Save