1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/*
2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project
3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License.
6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at
7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and
14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License.
15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpackage android.hardware.camera2.legacy;
18feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
19feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable;
20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler;
21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread;
22feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Looper;
23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.MessageQueue;
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class RequestHandlerThread extends HandlerThread {
2651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
2751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin    /**
2851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin     * Ensure that the MessageQueue's idle handler gets run by poking the message queue;
2951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin     * normally if the message queue is already idle, the idle handler won't get invoked.
3051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin     *
3151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin     * <p>Users of this handler thread should ignore this message.</p>
3251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin     */
3351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin    public final static int MSG_POKE_IDLE_HANDLER = -1;
3451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final ConditionVariable mStarted = new ConditionVariable(false);
36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final ConditionVariable mIdle = new ConditionVariable(true);
37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private Handler.Callback mCallback;
38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private volatile Handler mHandler;
39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public RequestHandlerThread(String name, Handler.Callback callback) {
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        super(name, Thread.MAX_PRIORITY);
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCallback = callback;
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    protected void onLooperPrepared() {
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mHandler = new Handler(getLooper(), mCallback);
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mStarted.open();
49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Blocks until thread has started
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void waitUntilStarted() {
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mStarted.block();
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // May return null if the handler is not set up yet.
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public Handler getHandler() {
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mHandler;
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Blocks until thread has started
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public Handler waitAndGetHandler() {
63feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        waitUntilStarted();
64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return getHandler();
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Atomic multi-type message existence check
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public boolean hasAnyMessages(int[] what) {
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized (mHandler.getLooper().getQueue()) {
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            for (int i : what) {
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mHandler.hasMessages(i)) {
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    return true;
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return false;
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Atomic multi-type message remove
80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void removeMessages(int[] what) {
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized (mHandler.getLooper().getQueue()) {
82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            for (int i : what) {
83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                mHandler.removeMessages(i);
84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
86feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final MessageQueue.IdleHandler mIdleHandler = new MessageQueue.IdleHandler() {
89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        @Override
90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        public boolean queueIdle() {
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mIdle.open();
92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return false;
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    };
95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
96feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Blocks until thread is idling
97feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void waitUntilIdle() {
9851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        Handler handler = waitAndGetHandler();
996c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown        MessageQueue queue = handler.getLooper().getQueue();
1006c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown        if (queue.isIdle()) {
101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return;
102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mIdle.close();
1046c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown        queue.addIdleHandler(mIdleHandler);
10551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        // Ensure that the idle handler gets run even if the looper already went idle
10651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        handler.sendEmptyMessage(MSG_POKE_IDLE_HANDLER);
1076c7b41adf9e937a66880b8906389760f3fc82a08Jeff Brown        if (queue.isIdle()) {
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return;
109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mIdle.block();
111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
114