/* * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.ex.camera2.utils; import android.os.SystemClock; import android.util.Log; import com.android.ex.camera2.exceptions.TimeoutRuntimeException; import java.util.Arrays; import java.util.Collection; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * Block until a specific state change occurs. * *
Provides wait calls that block until the next unobserved state of the * requested type arrives. Unobserved states are states that have occurred since * the last wait, or that will be received from the camera device in the * future.
* *Thread interruptions are not supported; interrupting a thread that is either * waiting with {@link #waitForState} / {@link #waitForAnyOfStates} or is currently in * {@link StateChangeListener#onStateChanged} (provided by {@link #getListener}) will result in an * {@link UnsupportedOperationException} being raised on that thread.
*/ public final class StateWaiter { private static final String TAG = "StateWaiter"; private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); private final String[] mStateNames; private final int mStateCount; private final StateChangeListener mListener; /** Guard waitForState, waitForAnyState to only have one waiter */ private final AtomicBoolean mWaiting = new AtomicBoolean(false); private final LinkedBlockingQueueAll {@code state}/{@code states} arguments used in other methods must be * in the range of {@code [0, stateNames.length - 1]}.
* * @param stateNames an array of string names, used to mark the range of the valid states */ public StateWaiter(String[] stateNames) { mStateCount = stateNames.length; mStateNames = new String[mStateCount]; System.arraycopy(stateNames, /*srcPos*/0, mStateNames, /*dstPos*/0, mStateCount); mListener = new StateChangeListener() { @Override public void onStateChanged(int state) { queueStateTransition(checkStateInRange(state)); } }; } public StateChangeListener getListener() { return mListener; } /** * Wait until the desired state is observed, checking all state * transitions since the last time a state was waited on. * *Any intermediate state transitions that is not {@code state} are ignored.
* *Note: Only one waiter allowed at a time!
* * @param state state to observe a transition to * @param timeoutMs how long to wait in milliseconds * * @throws IllegalArgumentException if {@code state} was out of range * @throws TimeoutRuntimeException if the desired state is not observed before timeout. * @throws IllegalStateException if another thread is already waiting for a state transition */ public void waitForState(int state, long timeoutMs) { Integer[] stateArray = { checkStateInRange(state) }; waitForAnyOfStates(Arrays.asList(stateArray), timeoutMs); } /** * Wait until the one of the desired {@code states} is observed, checking all * state transitions since the last time a state was waited on. * *Any intermediate state transitions that are not in {@code states} are ignored.
* *Note: Only one waiter allowed at a time!
* * @param states Set of desired states to observe a transition to. * @param timeoutMs how long to wait in milliseconds * * @return the state reached * * @throws IllegalArgumentException if {@code state} was out of range * @throws TimeoutRuntimeException if none of the states is observed before timeout. * @throws IllegalStateException if another thread is already waiting for a state transition */ public int waitForAnyOfStates(Collection