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