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