From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../java/org/mozilla/gecko/util/ThreadUtils.java | 145 +++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ThreadUtils.java (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ThreadUtils.java') diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ThreadUtils.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ThreadUtils.java new file mode 100644 index 0000000000..00625800c9 --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ThreadUtils.java @@ -0,0 +1,145 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.util; + +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import org.mozilla.gecko.annotation.RobocopTarget; + +public final class ThreadUtils { + private static final String LOGTAG = "ThreadUtils"; + + /** + * Controls the action taken when a method like {@link + * ThreadUtils#assertOnUiThread(AssertBehavior)} detects a problem. + */ + public enum AssertBehavior { + NONE, + THROW, + } + + private static final Thread sUiThread = Looper.getMainLooper().getThread(); + private static final Handler sUiHandler = new Handler(Looper.getMainLooper()); + + // Referenced directly from GeckoAppShell in highly performance-sensitive code (The extra + // function call of the getter was harming performance. (Bug 897123)) + // Once Bug 709230 is resolved we should reconsider this as ProGuard should be able to optimise + // this out at compile time. + public static Handler sGeckoHandler; + public static volatile Thread sGeckoThread; + + public static Thread getUiThread() { + return sUiThread; + } + + public static Handler getUiHandler() { + return sUiHandler; + } + + /** + * Runs the provided runnable on the UI thread. If this method is called on the UI thread the + * runnable will be executed synchronously. + * + * @param runnable the runnable to be executed. + */ + public static void runOnUiThread(final Runnable runnable) { + // We're on the UI thread already, let's just run this + if (isOnUiThread()) { + runnable.run(); + return; + } + + postToUiThread(runnable); + } + + public static void postToUiThread(final Runnable runnable) { + sUiHandler.post(runnable); + } + + public static void postToUiThreadDelayed(final Runnable runnable, final long delayMillis) { + sUiHandler.postDelayed(runnable, delayMillis); + } + + public static void removeUiThreadCallbacks(final Runnable runnable) { + sUiHandler.removeCallbacks(runnable); + } + + public static Handler getBackgroundHandler() { + return GeckoBackgroundThread.getHandler(); + } + + public static void postToBackgroundThread(final Runnable runnable) { + GeckoBackgroundThread.post(runnable); + } + + public static void assertOnUiThread(final AssertBehavior assertBehavior) { + assertOnThread(getUiThread(), assertBehavior); + } + + public static void assertOnUiThread() { + assertOnThread(getUiThread(), AssertBehavior.THROW); + } + + @RobocopTarget + public static void assertOnGeckoThread() { + assertOnThread(sGeckoThread, AssertBehavior.THROW); + } + + public static void assertOnThread(final Thread expectedThread, final AssertBehavior behavior) { + assertOnThreadComparison(expectedThread, behavior, true); + } + + private static void assertOnThreadComparison( + final Thread expectedThread, final AssertBehavior behavior, final boolean expected) { + final Thread currentThread = Thread.currentThread(); + final long currentThreadId = currentThread.getId(); + final long expectedThreadId = expectedThread.getId(); + + if ((currentThreadId == expectedThreadId) == expected) { + return; + } + + final String message; + if (expected) { + message = + "Expected thread " + + expectedThreadId + + " (\"" + + expectedThread.getName() + + "\"), but running on thread " + + currentThreadId + + " (\"" + + currentThread.getName() + + "\")"; + } else { + message = + "Expected anything but " + + expectedThreadId + + " (\"" + + expectedThread.getName() + + "\"), but running there."; + } + + final IllegalThreadStateException e = new IllegalThreadStateException(message); + + switch (behavior) { + case THROW: + throw e; + default: + Log.e(LOGTAG, "Method called on wrong thread!", e); + } + } + + public static boolean isOnUiThread() { + return isOnThread(getUiThread()); + } + + @RobocopTarget + public static boolean isOnThread(final Thread thread) { + return (Thread.currentThread().getId() == thread.getId()); + } +} -- cgit v1.2.3