Update the BackgroundThread dependency
Need to use the BackgroundThread from modules-utils-backgroundthread
only after we move to the CrashRecovery module. But till the time we
ramp up the flag, we cannot use it directly.
Copying BackgroundThread to local utils for now.
Added a TODO to move it later.
Bug: b/289203818
Test: atest PackageWatchdogTest:com.android.server.PackageWatchdogTest
Change-Id: I40b919bbe7a410eab48d099e30e5c54095731cac
diff --git a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
index ce8fb65..5d71b7d 100644
--- a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
+++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
@@ -38,13 +38,13 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.BackgroundThread;
import android.util.LongArrayQueue;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
diff --git a/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java b/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java
new file mode 100644
index 0000000..a6ae68f
--- /dev/null
+++ b/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java
@@ -0,0 +1,103 @@
+/*
+ * * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Thread for asynchronous event processing. This thread is configured as
+ * {@link android.os.Process#THREAD_PRIORITY_BACKGROUND}, which means fewer CPU
+ * resources will be dedicated to it, and it will "have less chance of impacting
+ * the responsiveness of the user interface."
+ * <p>
+ * This thread is best suited for tasks that the user is not actively waiting
+ * for, or for tasks that the user expects to be executed eventually.
+ *
+ * @see com.android.internal.os.BackgroundThread
+ *
+ * TODO: b/326916057 depend on modules-utils-backgroundthread instead
+ * @hide
+ */
+public final class BackgroundThread extends HandlerThread {
+ private static final Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static BackgroundThread sInstance;
+ @GuardedBy("sLock")
+ private static Handler sHandler;
+ @GuardedBy("sLock")
+ private static HandlerExecutor sHandlerExecutor;
+
+ private BackgroundThread() {
+ super(BackgroundThread.class.getName(), android.os.Process.THREAD_PRIORITY_BACKGROUND);
+ }
+
+ @GuardedBy("sLock")
+ private static void ensureThreadLocked() {
+ if (sInstance == null) {
+ sInstance = new BackgroundThread();
+ sInstance.start();
+ sHandler = new Handler(sInstance.getLooper());
+ sHandlerExecutor = new HandlerExecutor(sHandler);
+ }
+ }
+
+ /**
+ * Get the singleton instance of this class.
+ *
+ * @return the singleton instance of this class
+ */
+ @NonNull
+ public static BackgroundThread get() {
+ synchronized (sLock) {
+ ensureThreadLocked();
+ return sInstance;
+ }
+ }
+
+ /**
+ * Get the singleton {@link Handler} for this class.
+ *
+ * @return the singleton {@link Handler} for this class.
+ */
+ @NonNull
+ public static Handler getHandler() {
+ synchronized (sLock) {
+ ensureThreadLocked();
+ return sHandler;
+ }
+ }
+
+ /**
+ * Get the singleton {@link Executor} for this class.
+ *
+ * @return the singleton {@link Executor} for this class.
+ */
+ @NonNull
+ public static Executor getExecutor() {
+ synchronized (sLock) {
+ ensureThreadLocked();
+ return sHandlerExecutor;
+ }
+ }
+}
diff --git a/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java b/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java
new file mode 100644
index 0000000..948ebcca
--- /dev/null
+++ b/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * An adapter {@link Executor} that posts all executed tasks onto the given
+ * {@link Handler}.
+ *
+ * TODO: b/326916057 depend on modules-utils-backgroundthread instead
+ * @hide
+ */
+public class HandlerExecutor implements Executor {
+ private final Handler mHandler;
+
+ public HandlerExecutor(@NonNull Handler handler) {
+ mHandler = Objects.requireNonNull(handler);
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ if (!mHandler.post(command)) {
+ throw new RejectedExecutionException(mHandler + " is shutting down");
+ }
+ }
+}