Loading core/java/com/android/internal/os/BackgroundThread.java +28 −34 Original line number Diff line number Diff line Loading @@ -32,13 +32,9 @@ 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; // 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 static BackgroundThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private BackgroundThread() { super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND); Loading @@ -51,14 +47,9 @@ public final class BackgroundThread extends HandlerThread { } } 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) { private static void ensureThreadReadyLocked() { 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 @@ -69,34 +60,37 @@ 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() { ensureThreadReady(); synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); return sInstance; } } @NonNull public static Handler getHandler() { ensureThreadReady(); synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); return sHandler; } } @NonNull public static Executor getExecutor() { ensureThreadReady(); synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); return sHandlerExecutor; } } } core/java/com/android/server/FgThread.java +28 −15 Original line number Diff line number Diff line Loading @@ -38,32 +38,45 @@ 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 final class NoPreloadHolder { private static final FgThread sInstance = new FgThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private static FgThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private FgThread() { super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); start(); final Looper looper = getLooper(); } private static void ensureThreadLocked() { if (sInstance == null) { sInstance = new FgThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = makeSharedHandler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = makeSharedHandler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } } public static FgThread get() { return NoPreloadHolder.sInstance; synchronized (FgThread.class) { ensureThreadLocked(); return sInstance; } } public static Handler getHandler() { return NoPreloadHolder.sInstance.mHandler; synchronized (FgThread.class) { ensureThreadLocked(); return sHandler; } } public static Executor getExecutor() { return NoPreloadHolder.sInstance.mHandlerExecutor; synchronized (FgThread.class) { ensureThreadLocked(); return sHandlerExecutor; } } } services/core/java/com/android/server/IoThread.java +25 −15 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ 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 @@ -29,31 +28,42 @@ import java.util.concurrent.Executor; * (not waiting for data itself, but communicating with network daemons). */ public final class IoThread extends ServiceThread { private static final class NoPreloadHolder { private static final IoThread sInstance = new IoThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private static IoThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private IoThread() { super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); 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); } 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); } } public static IoThread get() { return NoPreloadHolder.sInstance; synchronized (IoThread.class) { ensureThreadLocked(); return sInstance; } } public static Handler getHandler() { return NoPreloadHolder.sInstance.mHandler; synchronized (IoThread.class) { ensureThreadLocked(); return sHandler; } } public static Executor getExecutor() { return NoPreloadHolder.sInstance.mHandlerExecutor; synchronized (IoThread.class) { ensureThreadLocked(); return sHandlerExecutor; } } } services/core/java/com/android/server/PermissionThread.java +35 −13 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.os.HandlerExecutor; import android.os.Looper; import android.os.Trace; import com.android.internal.annotations.GuardedBy; import java.util.concurrent.Executor; /** Loading @@ -32,41 +34,61 @@ 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 class NoPreloadHolder { private static final PermissionThread sInstance = new PermissionThread(); } private static final Object sLock = new Object(); private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; @GuardedBy("sLock") private static PermissionThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private PermissionThread() { super("android.perm", android.os.Process.THREAD_PRIORITY_DEFAULT, /* allowIo= */ true); start(); final Looper looper = getLooper(); } @GuardedBy("sLock") private static void ensureThreadLocked() { if (sInstance != null) { return; } sInstance = new PermissionThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = new Handler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = new Handler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } /** * Obtain a singleton instance of the PermissionThread. */ public static PermissionThread get() { return NoPreloadHolder.sInstance; synchronized (sLock) { ensureThreadLocked(); return sInstance; } } /** * Obtain a singleton instance of a handler executing in the PermissionThread. */ public static Handler getHandler() { return NoPreloadHolder.sInstance.mHandler; synchronized (sLock) { ensureThreadLocked(); return sHandler; } } /** * Obtain a singleton instance of an executor of the PermissionThread. */ public static Executor getExecutor() { return NoPreloadHolder.sInstance.mHandlerExecutor; synchronized (sLock) { ensureThreadLocked(); return sHandlerExecutor; } } } Loading
core/java/com/android/internal/os/BackgroundThread.java +28 −34 Original line number Diff line number Diff line Loading @@ -32,13 +32,9 @@ 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; // 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 static BackgroundThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private BackgroundThread() { super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND); Loading @@ -51,14 +47,9 @@ public final class BackgroundThread extends HandlerThread { } } 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) { private static void ensureThreadReadyLocked() { 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 @@ -69,34 +60,37 @@ 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() { ensureThreadReady(); synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); return sInstance; } } @NonNull public static Handler getHandler() { ensureThreadReady(); synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); return sHandler; } } @NonNull public static Executor getExecutor() { ensureThreadReady(); synchronized (BackgroundThread.class) { ensureThreadReadyLocked(); return sHandlerExecutor; } } }
core/java/com/android/server/FgThread.java +28 −15 Original line number Diff line number Diff line Loading @@ -38,32 +38,45 @@ 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 final class NoPreloadHolder { private static final FgThread sInstance = new FgThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private static FgThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private FgThread() { super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); start(); final Looper looper = getLooper(); } private static void ensureThreadLocked() { if (sInstance == null) { sInstance = new FgThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = makeSharedHandler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = makeSharedHandler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } } public static FgThread get() { return NoPreloadHolder.sInstance; synchronized (FgThread.class) { ensureThreadLocked(); return sInstance; } } public static Handler getHandler() { return NoPreloadHolder.sInstance.mHandler; synchronized (FgThread.class) { ensureThreadLocked(); return sHandler; } } public static Executor getExecutor() { return NoPreloadHolder.sInstance.mHandlerExecutor; synchronized (FgThread.class) { ensureThreadLocked(); return sHandlerExecutor; } } }
services/core/java/com/android/server/IoThread.java +25 −15 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ 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 @@ -29,31 +28,42 @@ import java.util.concurrent.Executor; * (not waiting for data itself, but communicating with network daemons). */ public final class IoThread extends ServiceThread { private static final class NoPreloadHolder { private static final IoThread sInstance = new IoThread(); } private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; private static IoThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private IoThread() { super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); 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); } 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); } } public static IoThread get() { return NoPreloadHolder.sInstance; synchronized (IoThread.class) { ensureThreadLocked(); return sInstance; } } public static Handler getHandler() { return NoPreloadHolder.sInstance.mHandler; synchronized (IoThread.class) { ensureThreadLocked(); return sHandler; } } public static Executor getExecutor() { return NoPreloadHolder.sInstance.mHandlerExecutor; synchronized (IoThread.class) { ensureThreadLocked(); return sHandlerExecutor; } } }
services/core/java/com/android/server/PermissionThread.java +35 −13 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.os.HandlerExecutor; import android.os.Looper; import android.os.Trace; import com.android.internal.annotations.GuardedBy; import java.util.concurrent.Executor; /** Loading @@ -32,41 +34,61 @@ 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 class NoPreloadHolder { private static final PermissionThread sInstance = new PermissionThread(); } private static final Object sLock = new Object(); private final Handler mHandler; private final HandlerExecutor mHandlerExecutor; @GuardedBy("sLock") private static PermissionThread sInstance; private static Handler sHandler; private static HandlerExecutor sHandlerExecutor; private PermissionThread() { super("android.perm", android.os.Process.THREAD_PRIORITY_DEFAULT, /* allowIo= */ true); start(); final Looper looper = getLooper(); } @GuardedBy("sLock") private static void ensureThreadLocked() { if (sInstance != null) { return; } sInstance = new PermissionThread(); sInstance.start(); final Looper looper = sInstance.getLooper(); looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER); looper.setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); mHandler = new Handler(looper); mHandlerExecutor = new HandlerExecutor(mHandler); looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = new Handler(sInstance.getLooper()); sHandlerExecutor = new HandlerExecutor(sHandler); } /** * Obtain a singleton instance of the PermissionThread. */ public static PermissionThread get() { return NoPreloadHolder.sInstance; synchronized (sLock) { ensureThreadLocked(); return sInstance; } } /** * Obtain a singleton instance of a handler executing in the PermissionThread. */ public static Handler getHandler() { return NoPreloadHolder.sInstance.mHandler; synchronized (sLock) { ensureThreadLocked(); return sHandler; } } /** * Obtain a singleton instance of an executor of the PermissionThread. */ public static Executor getExecutor() { return NoPreloadHolder.sInstance.mHandlerExecutor; synchronized (sLock) { ensureThreadLocked(); return sHandlerExecutor; } } }