Loading core/java/com/android/internal/os/BackgroundThread.java +34 −28 Original line number Diff line number Diff line Loading @@ -32,9 +32,13 @@ import java.util.concurrent.Executor; public final class BackgroundThread extends HandlerThread { private static final long SLOW_DISPATCH_THRESHOLD_MS = 10_000; private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000; private static BackgroundThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; // Note: These static fields are shadowed in Robolectric, and cannot be easily changed without // breaking downstream tests. This makes refactoring or optimization a bit messier than it could // be, e.g., using common lazy singleton abstractions or the holder init pattern. private static volatile BackgroundThread sInstance; private static volatile Handler sHandler; private static volatile HandlerExecutor sHandlerExecutor; private BackgroundThread() { super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND); Loading @@ -47,9 +51,14 @@ public final class BackgroundThread extends HandlerThread { } } private static void ensureThreadReadyLocked() { private static void ensureThreadReady() { // As the executor is assigned and initialized last, we use it to signal full readiness. if (sHandlerExecutor != null) { return; } synchronized (BackgroundThread.class) { if (sHandlerExecutor == null) { ensureThreadStartedLocked(); if (sHandler == null) { // This will block until the looper is initialized on the background thread. final Looper looper = sInstance.getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); Loading @@ -60,37 +69,34 @@ public final class BackgroundThread extends HandlerThread { sHandlerExecutor = new HandlerExecutor(sHandler); } } } /** * Starts the thread if needed, but doesn't block on thread initialization or readiness. */ public static void startIfNeeded() { if (sInstance == null) { synchronized (BackgroundThread.class) { ensureThreadStartedLocked(); } } } @NonNull public static BackgroundThread get() { synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); ensureThreadReady(); return sInstance; } } @NonNull public static Handler getHandler() { synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); ensureThreadReady(); return sHandler; } } @NonNull public static Executor getExecutor() { synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); ensureThreadReady(); return sHandlerExecutor; } } } core/java/com/android/server/FgThread.java +15 −28 Original line number Diff line number Diff line Loading @@ -38,45 +38,32 @@ public final class FgThread extends ServiceThread { private static final long SLOW_DISPATCH_THRESHOLD_MS = 100; private static final long SLOW_DELIVERY_THRESHOLD_MS = 200; private static FgThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private static final class NoPreloadHolder { private static final FgThread sInstance = new FgThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private FgThread() { super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); } private static void ensureThreadLocked() { if (sInstance == null) { sInstance = new FgThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); start(); final Looper looper = getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = makeSharedHandler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = makeSharedHandler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); } public static FgThread get() { synchronized (FgThread.class) { ensureThreadLocked(); return sInstance; } return NoPreloadHolder.sInstance; } public static Handler getHandler() { synchronized (FgThread.class) { ensureThreadLocked(); return sHandler; } return NoPreloadHolder.sInstance.mHandler; } public static Executor getExecutor() { synchronized (FgThread.class) { ensureThreadLocked(); return sHandlerExecutor; } return NoPreloadHolder.sInstance.mHandlerExecutor; } } services/core/java/com/android/server/IoThread.java +15 −25 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server; import android.os.Handler; import android.os.HandlerExecutor; import android.os.Looper; import android.os.Trace; import java.util.concurrent.Executor; Loading @@ -28,42 +29,31 @@ import java.util.concurrent.Executor; * (not waiting for data itself, but communicating with network daemons). */ public final class IoThread extends ServiceThread { private static IoThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private static final class NoPreloadHolder { private static final IoThread sInstance = new IoThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private IoThread() { super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); } private static void ensureThreadLocked() { if (sInstance == null) { sInstance = new IoThread(); sInstance.start(); sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); sHandler = makeSharedHandler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } start(); final Looper looper = getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); mHandler = new Handler(looper, /*callback=*/ null, /* async=*/ false, /* shared=*/ true); mHandlerExecutor = new HandlerExecutor(mHandler); } public static IoThread get() { synchronized (IoThread.class) { ensureThreadLocked(); return sInstance; } return NoPreloadHolder.sInstance; } public static Handler getHandler() { synchronized (IoThread.class) { ensureThreadLocked(); return sHandler; } return NoPreloadHolder.sInstance.mHandler; } public static Executor getExecutor() { synchronized (IoThread.class) { ensureThreadLocked(); return sHandlerExecutor; } return NoPreloadHolder.sInstance.mHandlerExecutor; } } services/core/java/com/android/server/PermissionThread.java +13 −35 Original line number Diff line number Diff line Loading @@ -21,8 +21,6 @@ import android.os.HandlerExecutor; import android.os.Looper; import android.os.Trace; import com.android.internal.annotations.GuardedBy; import java.util.concurrent.Executor; /** Loading @@ -34,61 +32,41 @@ public final class PermissionThread extends ServiceThread { private static final long SLOW_DISPATCH_THRESHOLD_MS = 100; private static final long SLOW_DELIVERY_THRESHOLD_MS = 200; private static final Object sLock = new Object(); private static final class NoPreloadHolder { private static final PermissionThread sInstance = new PermissionThread(); } @GuardedBy("sLock") private static PermissionThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private PermissionThread() { super("android.perm", android.os.Process.THREAD_PRIORITY_DEFAULT, /* allowIo= */ true); } @GuardedBy("sLock") private static void ensureThreadLocked() { if (sInstance != null) { return; } sInstance = new PermissionThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); start(); final Looper looper = getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = new Handler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = new Handler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); } /** * Obtain a singleton instance of the PermissionThread. */ public static PermissionThread get() { synchronized (sLock) { ensureThreadLocked(); return sInstance; } return NoPreloadHolder.sInstance; } /** * Obtain a singleton instance of a handler executing in the PermissionThread. */ public static Handler getHandler() { synchronized (sLock) { ensureThreadLocked(); return sHandler; } return NoPreloadHolder.sInstance.mHandler; } /** * Obtain a singleton instance of an executor of the PermissionThread. */ public static Executor getExecutor() { synchronized (sLock) { ensureThreadLocked(); return sHandlerExecutor; } return NoPreloadHolder.sInstance.mHandlerExecutor; } } Loading
core/java/com/android/internal/os/BackgroundThread.java +34 −28 Original line number Diff line number Diff line Loading @@ -32,9 +32,13 @@ import java.util.concurrent.Executor; public final class BackgroundThread extends HandlerThread { private static final long SLOW_DISPATCH_THRESHOLD_MS = 10_000; private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000; private static BackgroundThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; // Note: These static fields are shadowed in Robolectric, and cannot be easily changed without // breaking downstream tests. This makes refactoring or optimization a bit messier than it could // be, e.g., using common lazy singleton abstractions or the holder init pattern. private static volatile BackgroundThread sInstance; private static volatile Handler sHandler; private static volatile HandlerExecutor sHandlerExecutor; private BackgroundThread() { super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND); Loading @@ -47,9 +51,14 @@ public final class BackgroundThread extends HandlerThread { } } private static void ensureThreadReadyLocked() { private static void ensureThreadReady() { // As the executor is assigned and initialized last, we use it to signal full readiness. if (sHandlerExecutor != null) { return; } synchronized (BackgroundThread.class) { if (sHandlerExecutor == null) { ensureThreadStartedLocked(); if (sHandler == null) { // This will block until the looper is initialized on the background thread. final Looper looper = sInstance.getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); Loading @@ -60,37 +69,34 @@ public final class BackgroundThread extends HandlerThread { sHandlerExecutor = new HandlerExecutor(sHandler); } } } /** * Starts the thread if needed, but doesn't block on thread initialization or readiness. */ public static void startIfNeeded() { if (sInstance == null) { synchronized (BackgroundThread.class) { ensureThreadStartedLocked(); } } } @NonNull public static BackgroundThread get() { synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); ensureThreadReady(); return sInstance; } } @NonNull public static Handler getHandler() { synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); ensureThreadReady(); return sHandler; } } @NonNull public static Executor getExecutor() { synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); ensureThreadReady(); return sHandlerExecutor; } } }
core/java/com/android/server/FgThread.java +15 −28 Original line number Diff line number Diff line Loading @@ -38,45 +38,32 @@ public final class FgThread extends ServiceThread { private static final long SLOW_DISPATCH_THRESHOLD_MS = 100; private static final long SLOW_DELIVERY_THRESHOLD_MS = 200; private static FgThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private static final class NoPreloadHolder { private static final FgThread sInstance = new FgThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private FgThread() { super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); } private static void ensureThreadLocked() { if (sInstance == null) { sInstance = new FgThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); start(); final Looper looper = getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = makeSharedHandler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = makeSharedHandler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); } public static FgThread get() { synchronized (FgThread.class) { ensureThreadLocked(); return sInstance; } return NoPreloadHolder.sInstance; } public static Handler getHandler() { synchronized (FgThread.class) { ensureThreadLocked(); return sHandler; } return NoPreloadHolder.sInstance.mHandler; } public static Executor getExecutor() { synchronized (FgThread.class) { ensureThreadLocked(); return sHandlerExecutor; } return NoPreloadHolder.sInstance.mHandlerExecutor; } }
services/core/java/com/android/server/IoThread.java +15 −25 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server; import android.os.Handler; import android.os.HandlerExecutor; import android.os.Looper; import android.os.Trace; import java.util.concurrent.Executor; Loading @@ -28,42 +29,31 @@ import java.util.concurrent.Executor; * (not waiting for data itself, but communicating with network daemons). */ public final class IoThread extends ServiceThread { private static IoThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private static final class NoPreloadHolder { private static final IoThread sInstance = new IoThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private IoThread() { super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); } private static void ensureThreadLocked() { if (sInstance == null) { sInstance = new IoThread(); sInstance.start(); sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); sHandler = makeSharedHandler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } start(); final Looper looper = getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); mHandler = new Handler(looper, /*callback=*/ null, /* async=*/ false, /* shared=*/ true); mHandlerExecutor = new HandlerExecutor(mHandler); } public static IoThread get() { synchronized (IoThread.class) { ensureThreadLocked(); return sInstance; } return NoPreloadHolder.sInstance; } public static Handler getHandler() { synchronized (IoThread.class) { ensureThreadLocked(); return sHandler; } return NoPreloadHolder.sInstance.mHandler; } public static Executor getExecutor() { synchronized (IoThread.class) { ensureThreadLocked(); return sHandlerExecutor; } return NoPreloadHolder.sInstance.mHandlerExecutor; } }
services/core/java/com/android/server/PermissionThread.java +13 −35 Original line number Diff line number Diff line Loading @@ -21,8 +21,6 @@ import android.os.HandlerExecutor; import android.os.Looper; import android.os.Trace; import com.android.internal.annotations.GuardedBy; import java.util.concurrent.Executor; /** Loading @@ -34,61 +32,41 @@ public final class PermissionThread extends ServiceThread { private static final long SLOW_DISPATCH_THRESHOLD_MS = 100; private static final long SLOW_DELIVERY_THRESHOLD_MS = 200; private static final Object sLock = new Object(); private static final class NoPreloadHolder { private static final PermissionThread sInstance = new PermissionThread(); } @GuardedBy("sLock") private static PermissionThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private PermissionThread() { super("android.perm", android.os.Process.THREAD_PRIORITY_DEFAULT, /* allowIo= */ true); } @GuardedBy("sLock") private static void ensureThreadLocked() { if (sInstance != null) { return; } sInstance = new PermissionThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); start(); final Looper looper = getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = new Handler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = new Handler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); } /** * Obtain a singleton instance of the PermissionThread. */ public static PermissionThread get() { synchronized (sLock) { ensureThreadLocked(); return sInstance; } return NoPreloadHolder.sInstance; } /** * Obtain a singleton instance of a handler executing in the PermissionThread. */ public static Handler getHandler() { synchronized (sLock) { ensureThreadLocked(); return sHandler; } return NoPreloadHolder.sInstance.mHandler; } /** * Obtain a singleton instance of an executor of the PermissionThread. */ public static Executor getExecutor() { synchronized (sLock) { ensureThreadLocked(); return sHandlerExecutor; } return NoPreloadHolder.sInstance.mHandlerExecutor; } }