1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.one.v2.autofocus; 18 19 import android.hardware.camera2.CaptureResult; 20 import androidx.annotation.Nullable; 21 22 import com.android.camera.async.Updatable; 23 24 import java.util.Set; 25 26 import javax.annotation.ParametersAreNonnullByDefault; 27 import javax.annotation.concurrent.NotThreadSafe; 28 29 /** 30 * Tracks the finite state machines used by the camera2 api for AF and AE 31 * triggers. That is, the state machine waits for a TRIGGER_START followed by 32 * one of the done states, at which point a callback is invoked and the state 33 * machine resets. 34 * <p> 35 * In other words, this implements the state machine defined by the following 36 * regex, such that a callback is invoked each time the state machine reaches 37 * the end. 38 * 39 * <pre> 40 * (.* TRIGGER_START .* [DONE_STATES])+ 41 * </pre> 42 * <p> 43 * See the android documentation for {@link CaptureResult#CONTROL_AF_STATE} and 44 * {@link CaptureResult#CONTROL_AE_STATE} for the transition tables which this 45 * is based on. 46 */ 47 @ParametersAreNonnullByDefault 48 @NotThreadSafe 49 final class TriggerStateMachine { 50 private static enum State { 51 WAITING_FOR_TRIGGER, 52 TRIGGERED 53 } 54 55 private final int mTriggerStart; 56 private final Set<Integer> mDoneStates; 57 private State mCurrentState; 58 @Nullable 59 private Long mLastTriggerFrameNumber; 60 @Nullable 61 private Long mLastFinishFrameNumber; 62 TriggerStateMachine(int triggerStart, Set<Integer> doneStates)63 public TriggerStateMachine(int triggerStart, Set<Integer> doneStates) { 64 mTriggerStart = triggerStart; 65 mDoneStates = doneStates; 66 mCurrentState = State.WAITING_FOR_TRIGGER; 67 mLastTriggerFrameNumber = null; 68 mLastFinishFrameNumber = null; 69 } 70 71 /** 72 * @return True upon completion of a cycle of the state machine. 73 */ update(long frameNumber, @Nullable Integer triggerState, @Nullable Integer state)74 public boolean update(long frameNumber, @Nullable Integer triggerState, @Nullable Integer 75 state) { 76 boolean triggeredNow = triggerState != null && triggerState == mTriggerStart; 77 boolean doneNow = mDoneStates.contains(state); 78 79 if (mCurrentState == State.WAITING_FOR_TRIGGER) { 80 if (mLastTriggerFrameNumber == null || frameNumber > mLastTriggerFrameNumber) { 81 if (triggeredNow) { 82 mCurrentState = State.TRIGGERED; 83 mLastTriggerFrameNumber = frameNumber; 84 } 85 } 86 } 87 88 if (mCurrentState == State.TRIGGERED) { 89 if (mLastFinishFrameNumber == null || frameNumber > mLastFinishFrameNumber) { 90 if (doneNow) { 91 mCurrentState = State.WAITING_FOR_TRIGGER; 92 mLastFinishFrameNumber = frameNumber; 93 return true; 94 } 95 } 96 } 97 98 return false; 99 } 100 } 101