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