1 /*
2  * Copyright (C) 2017 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 com.android.launcher3.util;
18 
19 import android.os.Looper;
20 import android.os.MessageQueue;
21 
22 /**
23  * Utility class to block execution until the UI looper is idle.
24  */
25 public class LooperIdleLock implements MessageQueue.IdleHandler {
26 
27     private final Object mLock;
28 
29     private boolean mIsLocked;
30     private Looper mLooper;
31 
LooperIdleLock(Object lock, Looper looper)32     public LooperIdleLock(Object lock, Looper looper) {
33         mLock = lock;
34         mLooper = looper;
35         mIsLocked = true;
36         looper.getQueue().addIdleHandler(this);
37     }
38 
39     @Override
queueIdle()40     public boolean queueIdle() {
41         synchronized (mLock) {
42             mIsLocked = false;
43             mLock.notify();
44         }
45         // Manually remove from the list in case we're calling this outside of the idle callbacks
46         // (this is Ok in the normal flow as well because MessageQueue makes a copy of all handlers
47         // before calling back)
48         mLooper.getQueue().removeIdleHandler(this);
49         return false;
50     }
51 
awaitLocked(long ms)52     public boolean awaitLocked(long ms) {
53         if (mIsLocked) {
54             try {
55                 // Just in case mFlushingWorkerThread changes but we aren't woken up,
56                 // wait no longer than 1sec at a time
57                 mLock.wait(ms);
58             } catch (InterruptedException ex) {
59                 // Ignore
60             }
61         }
62         return mIsLocked;
63     }
64 }
65