| /* |
| * Copyright (C) 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.portability; |
| |
| import android.os.SystemClock; |
| |
| import com.android.ex.camera2.portability.debug.Log; |
| |
| public abstract class CameraStateHolder { |
| private static final Log.Tag TAG = new Log.Tag("CamStateHolder"); |
| |
| private int mState; |
| private boolean mInvalid; |
| |
| /** |
| * Construct a new instance of @{link CameraStateHolder} with an initial state. |
| * |
| * @param state The initial state. |
| */ |
| public CameraStateHolder(int state) { |
| setState(state); |
| mInvalid = false; |
| } |
| |
| /** |
| * Change to a new state. |
| * |
| * @param state The new state. |
| */ |
| public synchronized void setState(int state) { |
| if (mState != state) { |
| Log.v(TAG, "setState - state = " + Integer.toBinaryString(state)); |
| } |
| mState = state; |
| this.notifyAll(); |
| } |
| |
| /** |
| * Obtain the current state. |
| * |
| * @return The current state. |
| */ |
| public synchronized int getState() { |
| return mState; |
| } |
| |
| /** |
| * Change the state to be invalid. Once invalidated, the state will be invalid forever. |
| */ |
| public synchronized void invalidate() { |
| mInvalid = true; |
| } |
| |
| /** |
| * Whether the state is invalid. |
| * |
| * @return True if the state is invalid. |
| */ |
| public synchronized boolean isInvalid() { |
| return mInvalid; |
| } |
| |
| private static interface ConditionChecker { |
| /** |
| * @return Whether the condition holds. |
| */ |
| boolean success(); |
| } |
| |
| /** |
| * A helper method used by {@link #waitToAvoidStates(int)} and |
| * {@link #waitForStates(int)}. This method will wait until the |
| * condition is successful. |
| * |
| * @param stateChecker The state checker to be used. |
| * @param timeoutMs The timeout limit in milliseconds. |
| * @return {@code false} if the wait is interrupted or timeout limit is |
| * reached. |
| */ |
| private boolean waitForCondition(ConditionChecker stateChecker, |
| long timeoutMs) { |
| long timeBound = SystemClock.uptimeMillis() + timeoutMs; |
| synchronized (this) { |
| while (!stateChecker.success()) { |
| try { |
| this.wait(timeoutMs); |
| } catch (InterruptedException ex) { |
| if (SystemClock.uptimeMillis() > timeBound) { |
| // Timeout. |
| Log.w(TAG, "Timeout waiting."); |
| } |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Block the current thread until the state becomes one of the |
| * specified. |
| * |
| * @param states Expected states. |
| * @return {@code false} if the wait is interrupted or timeout limit is |
| * reached. |
| */ |
| public boolean waitForStates(final int states) { |
| Log.v(TAG, "waitForStates - states = " + Integer.toBinaryString(states)); |
| return waitForCondition(new ConditionChecker() { |
| @Override |
| public boolean success() { |
| return (states | getState()) == states; |
| } |
| }, CameraAgent.CAMERA_OPERATION_TIMEOUT_MS); |
| } |
| |
| /** |
| * Block the current thread until the state becomes NOT one of the |
| * specified. |
| * |
| * @param states States to avoid. |
| * @return {@code false} if the wait is interrupted or timeout limit is |
| * reached. |
| */ |
| public boolean waitToAvoidStates(final int states) { |
| Log.v(TAG, "waitToAvoidStates - states = " + Integer.toBinaryString(states)); |
| return waitForCondition(new ConditionChecker() { |
| @Override |
| public boolean success() { |
| return (states & getState()) == 0; |
| } |
| }, CameraAgent.CAMERA_OPERATION_TIMEOUT_MS); |
| } |
| } |