Home | History | Annotate | Download | only in legacy
      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 
     17 package android.hardware.camera2.legacy;
     18 
     19 import android.os.ConditionVariable;
     20 import android.os.Handler;
     21 import android.os.HandlerThread;
     22 import android.os.Looper;
     23 import android.os.MessageQueue;
     24 
     25 public class RequestHandlerThread extends HandlerThread {
     26 
     27     /**
     28      * Ensure that the MessageQueue's idle handler gets run by poking the message queue;
     29      * normally if the message queue is already idle, the idle handler won't get invoked.
     30      *
     31      * <p>Users of this handler thread should ignore this message.</p>
     32      */
     33     public final static int MSG_POKE_IDLE_HANDLER = -1;
     34 
     35     private final ConditionVariable mStarted = new ConditionVariable(false);
     36     private final ConditionVariable mIdle = new ConditionVariable(true);
     37     private Handler.Callback mCallback;
     38     private volatile Handler mHandler;
     39 
     40     public RequestHandlerThread(String name, Handler.Callback callback) {
     41         super(name, Thread.MAX_PRIORITY);
     42         mCallback = callback;
     43     }
     44 
     45     @Override
     46     protected void onLooperPrepared() {
     47         mHandler = new Handler(getLooper(), mCallback);
     48         mStarted.open();
     49     }
     50 
     51     // Blocks until thread has started
     52     public void waitUntilStarted() {
     53         mStarted.block();
     54     }
     55 
     56     // May return null if the handler is not set up yet.
     57     public Handler getHandler() {
     58         return mHandler;
     59     }
     60 
     61     // Blocks until thread has started
     62     public Handler waitAndGetHandler() {
     63         waitUntilStarted();
     64         return getHandler();
     65     }
     66 
     67     // Atomic multi-type message existence check
     68     public boolean hasAnyMessages(int[] what) {
     69         synchronized (mHandler.getLooper().getQueue()) {
     70             for (int i : what) {
     71                 if (mHandler.hasMessages(i)) {
     72                     return true;
     73                 }
     74             }
     75         }
     76         return false;
     77     }
     78 
     79     // Atomic multi-type message remove
     80     public void removeMessages(int[] what) {
     81         synchronized (mHandler.getLooper().getQueue()) {
     82             for (int i : what) {
     83                 mHandler.removeMessages(i);
     84             }
     85         }
     86     }
     87 
     88     private final MessageQueue.IdleHandler mIdleHandler = new MessageQueue.IdleHandler() {
     89         @Override
     90         public boolean queueIdle() {
     91             mIdle.open();
     92             return false;
     93         }
     94     };
     95 
     96     // Blocks until thread is idling
     97     public void waitUntilIdle() {
     98         Handler handler = waitAndGetHandler();
     99         MessageQueue queue = handler.getLooper().getQueue();
    100         if (queue.isIdle()) {
    101             return;
    102         }
    103         mIdle.close();
    104         queue.addIdleHandler(mIdleHandler);
    105         // Ensure that the idle handler gets run even if the looper already went idle
    106         handler.sendEmptyMessage(MSG_POKE_IDLE_HANDLER);
    107         if (queue.isIdle()) {
    108             return;
    109         }
    110         mIdle.block();
    111     }
    112 
    113 }
    114