1 /* 2 * Copyright (C) 2019 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.settings.dashboard; 18 19 import android.util.Log; 20 21 import androidx.annotation.NonNull; 22 23 import com.android.settings.core.BasePreferenceController; 24 import com.android.settingslib.utils.ThreadUtils; 25 26 import java.util.HashSet; 27 import java.util.List; 28 import java.util.Set; 29 import java.util.concurrent.CountDownLatch; 30 import java.util.concurrent.TimeUnit; 31 32 /** 33 * Control ui blocker data and check whether it is finished 34 * 35 * @see BasePreferenceController.UiBlocker 36 * @see BasePreferenceController.UiBlockListener 37 */ 38 public class UiBlockerController { 39 private static final String TAG = "UiBlockerController"; 40 private static final int TIMEOUT_MILLIS = 500; 41 42 private CountDownLatch mCountDownLatch; 43 private boolean mBlockerFinished; 44 private Set<String> mKeys; 45 private long mTimeoutMillis; 46 UiBlockerController(@onNull List<String> keys)47 public UiBlockerController(@NonNull List<String> keys) { 48 this(keys, TIMEOUT_MILLIS); 49 } 50 UiBlockerController(@onNull List<String> keys, long timeout)51 public UiBlockerController(@NonNull List<String> keys, long timeout) { 52 mCountDownLatch = new CountDownLatch(keys.size()); 53 mBlockerFinished = keys.isEmpty(); 54 mKeys = new HashSet<>(keys); 55 mTimeoutMillis = timeout; 56 } 57 58 /** 59 * Start background thread, it will invoke {@code finishRunnable} if any condition is met 60 * 61 * 1. Waiting time exceeds {@link #mTimeoutMillis} 62 * 2. All background work that associated with {@link #mCountDownLatch} is finished 63 */ start(Runnable finishRunnable)64 public boolean start(Runnable finishRunnable) { 65 if (mKeys.isEmpty()) { 66 // Don't need to run finishRunnable because it doesn't start 67 return false; 68 } 69 ThreadUtils.postOnBackgroundThread(() -> { 70 try { 71 mCountDownLatch.await(mTimeoutMillis, TimeUnit.MILLISECONDS); 72 } catch (InterruptedException e) { 73 Log.w(TAG, "interrupted"); 74 } 75 mBlockerFinished = true; 76 ThreadUtils.postOnMainThread(finishRunnable); 77 }); 78 79 return true; 80 } 81 82 /** 83 * Return {@code true} if all work finished 84 */ isBlockerFinished()85 public boolean isBlockerFinished() { 86 return mBlockerFinished; 87 } 88 89 /** 90 * Count down latch by {@code key}. It only count down 1 time if same key count down multiple 91 * times. 92 */ countDown(String key)93 public boolean countDown(String key) { 94 if (mKeys.remove(key)) { 95 mCountDownLatch.countDown(); 96 return true; 97 } 98 99 return false; 100 } 101 } 102