CameraStateHolder.java revision a0842b40441db5332a5290f941021636b1182761
1/* 2 * Copyright (C) 2014 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 17package com.android.ex.camera2.portability; 18 19import android.os.SystemClock; 20 21import com.android.ex.camera2.portability.debug.Log; 22 23public abstract class CameraStateHolder { 24 private static final Log.Tag TAG = new Log.Tag("CamStateHolder"); 25 26 /** Camera states **/ 27 // These states are defined bitwise so we can easily to specify a set of 28 // states together. 29 public static final int CAMERA_UNOPENED = 1; 30 public static final int CAMERA_IDLE = 1 << 1; 31 public static final int CAMERA_UNLOCKED = 1 << 2; 32 public static final int CAMERA_CAPTURING = 1 << 3; 33 public static final int CAMERA_FOCUSING = 1 << 4; 34 35 private int mState; 36 37 public CameraStateHolder() { 38 setState(CAMERA_UNOPENED); 39 } 40 41 public CameraStateHolder(int state) { 42 setState(state); 43 } 44 45 public synchronized void setState(int state) { 46 mState = state; 47 this.notifyAll(); 48 } 49 50 public synchronized int getState() { 51 return mState; 52 } 53 54 private static interface ConditionChecker { 55 /** 56 * @return Whether the condition holds. 57 */ 58 boolean success(); 59 } 60 61 /** 62 * A helper method used by {@link #waitToAvoidStates(int)} and 63 * {@link #waitForStates(int)}. This method will wait until the 64 * condition is successful. 65 * 66 * @param stateChecker The state checker to be used. 67 * @param timeoutMs The timeout limit in milliseconds. 68 * @return {@code false} if the wait is interrupted or timeout limit is 69 * reached. 70 */ 71 private boolean waitForCondition(ConditionChecker stateChecker, 72 long timeoutMs) { 73 long timeBound = SystemClock.uptimeMillis() + timeoutMs; 74 synchronized (this) { 75 while (!stateChecker.success()) { 76 try { 77 this.wait(timeoutMs); 78 } catch (InterruptedException ex) { 79 if (SystemClock.uptimeMillis() > timeBound) { 80 // Timeout. 81 Log.w(TAG, "Timeout waiting."); 82 } 83 return false; 84 } 85 } 86 } 87 return true; 88 } 89 90 /** 91 * Block the current thread until the state becomes one of the 92 * specified. 93 * 94 * @param states Expected states. 95 * @return {@code false} if the wait is interrupted or timeout limit is 96 * reached. 97 */ 98 public boolean waitForStates(final int states) { 99 return waitForCondition(new ConditionChecker() { 100 @Override 101 public boolean success() { 102 return (states | getState()) == states; 103 } 104 }, CameraAgent.CAMERA_OPERATION_TIMEOUT_MS); 105 } 106 107 /** 108 * Block the current thread until the state becomes NOT one of the 109 * specified. 110 * 111 * @param states States to avoid. 112 * @return {@code false} if the wait is interrupted or timeout limit is 113 * reached. 114 */ 115 public boolean waitToAvoidStates(final int states) { 116 return waitForCondition(new ConditionChecker() { 117 @Override 118 public boolean success() { 119 return (states & getState()) == 0; 120 } 121 }, CameraAgent.CAMERA_OPERATION_TIMEOUT_MS); 122 } 123} 124