CameraStateHolder.java revision 6a9babad6eb8ac3e79a5e036d878ed7408e79f26
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    private int mState;
27
28    public CameraStateHolder(int state) {
29        setState(state);
30    }
31
32    public synchronized void setState(int state) {
33        if (mState != state) {
34            Log.v(TAG, "setState - state = " + Integer.toBinaryString(state));
35        }
36        mState = state;
37        this.notifyAll();
38    }
39
40    public synchronized int getState() {
41        return mState;
42    }
43
44    private static interface ConditionChecker {
45        /**
46         * @return Whether the condition holds.
47         */
48        boolean success();
49    }
50
51    /**
52     * A helper method used by {@link #waitToAvoidStates(int)} and
53     * {@link #waitForStates(int)}. This method will wait until the
54     * condition is successful.
55     *
56     * @param stateChecker The state checker to be used.
57     * @param timeoutMs The timeout limit in milliseconds.
58     * @return {@code false} if the wait is interrupted or timeout limit is
59     *         reached.
60     */
61    private boolean waitForCondition(ConditionChecker stateChecker,
62            long timeoutMs) {
63        long timeBound = SystemClock.uptimeMillis() + timeoutMs;
64        synchronized (this) {
65            while (!stateChecker.success()) {
66                try {
67                    this.wait(timeoutMs);
68                } catch (InterruptedException ex) {
69                    if (SystemClock.uptimeMillis() > timeBound) {
70                        // Timeout.
71                        Log.w(TAG, "Timeout waiting.");
72                    }
73                    return false;
74                }
75            }
76        }
77        return true;
78    }
79
80    /**
81     * Block the current thread until the state becomes one of the
82     * specified.
83     *
84     * @param states Expected states.
85     * @return {@code false} if the wait is interrupted or timeout limit is
86     *         reached.
87     */
88    public boolean waitForStates(final int states) {
89        Log.v(TAG, "waitForStates - states = " + Integer.toBinaryString(states));
90        return waitForCondition(new ConditionChecker() {
91            @Override
92            public boolean success() {
93                return (states | getState()) == states;
94            }
95        }, CameraAgent.CAMERA_OPERATION_TIMEOUT_MS);
96    }
97
98    /**
99     * Block the current thread until the state becomes NOT one of the
100     * specified.
101     *
102     * @param states States to avoid.
103     * @return {@code false} if the wait is interrupted or timeout limit is
104     *         reached.
105     */
106    public boolean waitToAvoidStates(final int states) {
107        Log.v(TAG, "waitToAvoidStates - states = " + Integer.toBinaryString(states));
108        return waitForCondition(new ConditionChecker() {
109            @Override
110            public boolean success() {
111                return (states & getState()) == 0;
112            }
113        }, CameraAgent.CAMERA_OPERATION_TIMEOUT_MS);
114    }
115}
116