1  /*
2   * Copyright (C) 2016 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  package com.android.settingslib.utils;
17  
18  import android.os.Handler;
19  import android.os.Looper;
20  
21  import java.util.concurrent.Callable;
22  import java.util.concurrent.ExecutorService;
23  import java.util.concurrent.Executors;
24  import java.util.concurrent.Future;
25  
26  public class ThreadUtils {
27  
28      private static volatile Thread sMainThread;
29      private static volatile Handler sMainThreadHandler;
30      private static volatile ExecutorService sThreadExecutor;
31  
32      /**
33       * Returns true if the current thread is the UI thread.
34       */
isMainThread()35      public static boolean isMainThread() {
36          if (sMainThread == null) {
37              sMainThread = Looper.getMainLooper().getThread();
38          }
39          return Thread.currentThread() == sMainThread;
40      }
41  
42      /**
43       * Returns a shared UI thread handler.
44       */
getUiThreadHandler()45      public static Handler getUiThreadHandler() {
46          if (sMainThreadHandler == null) {
47              sMainThreadHandler = new Handler(Looper.getMainLooper());
48          }
49  
50          return sMainThreadHandler;
51      }
52  
53      /**
54       * Checks that the current thread is the UI thread. Otherwise throws an exception.
55       */
ensureMainThread()56      public static void ensureMainThread() {
57          if (!isMainThread()) {
58              throw new RuntimeException("Must be called on the UI thread");
59          }
60      }
61  
62      /**
63       * Posts runnable in background using shared background thread pool.
64       *
65       * @Return A future of the task that can be monitored for updates or cancelled.
66       */
postOnBackgroundThread(Runnable runnable)67      public static Future postOnBackgroundThread(Runnable runnable) {
68          return getThreadExecutor().submit(runnable);
69      }
70  
71      /**
72       * Posts callable in background using shared background thread pool.
73       *
74       * @Return A future of the task that can be monitored for updates or cancelled.
75       */
postOnBackgroundThread(Callable callable)76      public static Future postOnBackgroundThread(Callable callable) {
77          return getThreadExecutor().submit(callable);
78      }
79  
80      /**
81       * Posts the runnable on the main thread.
82       */
postOnMainThread(Runnable runnable)83      public static void postOnMainThread(Runnable runnable) {
84          getUiThreadHandler().post(runnable);
85      }
86  
87      /**
88       * Posts the runnable on the main thread with a delay.
89       */
postOnMainThreadDelayed(Runnable runnable, long delayMillis)90      public static void postOnMainThreadDelayed(Runnable runnable, long delayMillis) {
91          getUiThreadHandler().postDelayed(runnable, delayMillis);
92      }
93  
getThreadExecutor()94      private static synchronized ExecutorService getThreadExecutor() {
95          if (sThreadExecutor == null) {
96              sThreadExecutor = Executors.newFixedThreadPool(
97                      Runtime.getRuntime().availableProcessors());
98          }
99          return sThreadExecutor;
100      }
101  }
102