Merge "Remove custom BackgroundThread and HandlerExecutor"
diff --git a/Android.bp b/Android.bp
index aa97b1a..9826476 100644
--- a/Android.bp
+++ b/Android.bp
@@ -21,6 +21,7 @@
     manifest: "AndroidManifest.xml",
 
     static_libs: [
+        "modules-utils-backgroundthread",
         "androidx.appcompat_appcompat",
         "androidx.core_core",
         "guava",
@@ -82,7 +83,6 @@
     srcs: [
         "src/**/*.aidl",
         "src/**/*.java",
-        ":mediaprovider-database-sources",
         ":statslog-mediaprovider-java-gen",
     ],
 }
@@ -90,18 +90,26 @@
 // This is defined to give LegacyMediaProvider the bare minimum it needs
 // to keep the legacy database schema working while also building
 // against "system_current"
-filegroup {
-    name: "mediaprovider-database-sources",
+java_library {
+    name: "mediaprovider-database",
     srcs: [
         "src/com/android/providers/media/DatabaseHelper.java",
-        "src/com/android/providers/media/util/BackgroundThread.java",
         "src/com/android/providers/media/util/DatabaseUtils.java",
         "src/com/android/providers/media/util/FileUtils.java",
         "src/com/android/providers/media/util/ForegroundThread.java",
-        "src/com/android/providers/media/util/HandlerExecutor.java",
         "src/com/android/providers/media/util/Logging.java",
         "src/com/android/providers/media/util/MimeUtils.java",
     ],
+    sdk_version: "module_current",
+    min_sdk_version: "30",
+    static_libs: [
+        "modules-utils-backgroundthread",
+    ],
+    libs: [
+        "androidx.annotation_annotation",
+        "framework-annotations-lib",
+        "framework-mediaprovider",
+    ],
 }
 
 platform_compat_config {
diff --git a/legacy/Android.bp b/legacy/Android.bp
index 0d50eac..18d6af2 100644
--- a/legacy/Android.bp
+++ b/legacy/Android.bp
@@ -13,20 +13,23 @@
     manifest: "AndroidManifest.xml",
 
     static_libs: [
+        "mediaprovider-database",
         "androidx.appcompat_appcompat",
         "androidx.core_core",
         "guava",
     ],
 
-    libs: ["app-compat-annotations"],
+    libs: [
+        "app-compat-annotations",
+        "framework-mediaprovider",
+    ],
 
     srcs: [
         "src/**/*.aidl",
         "src/**/*.java",
-        ":mediaprovider-database-sources",
     ],
 
     certificate: "media",
     privileged: true,
-    sdk_version: "system_current",
+    sdk_version: "module_current",
 }
diff --git a/src/com/android/providers/media/DatabaseHelper.java b/src/com/android/providers/media/DatabaseHelper.java
index d48726b..eb3b923 100644
--- a/src/com/android/providers/media/DatabaseHelper.java
+++ b/src/com/android/providers/media/DatabaseHelper.java
@@ -58,7 +58,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.providers.media.util.BackgroundThread;
+import com.android.modules.utils.BackgroundThread;
 import com.android.providers.media.util.DatabaseUtils;
 import com.android.providers.media.util.FileUtils;
 import com.android.providers.media.util.ForegroundThread;
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 1310d1b..9a38d7e 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -166,6 +166,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.modules.utils.BackgroundThread;
 import com.android.providers.media.DatabaseHelper.OnFilesChangeListener;
 import com.android.providers.media.DatabaseHelper.OnLegacyMigrationListener;
 import com.android.providers.media.fuse.ExternalStorageServiceImpl;
@@ -173,7 +174,6 @@
 import com.android.providers.media.playlist.Playlist;
 import com.android.providers.media.scan.MediaScanner;
 import com.android.providers.media.scan.ModernMediaScanner;
-import com.android.providers.media.util.BackgroundThread;
 import com.android.providers.media.util.CachedSupplier;
 import com.android.providers.media.util.DatabaseUtils;
 import com.android.providers.media.util.FileUtils;
@@ -209,6 +209,8 @@
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
@@ -4517,7 +4519,15 @@
             }
             case MediaStore.WAIT_FOR_IDLE_CALL: {
                 ForegroundThread.waitForIdle();
-                BackgroundThread.waitForIdle();
+                final CountDownLatch latch = new CountDownLatch(1);
+                BackgroundThread.getExecutor().execute(() -> {
+                    latch.countDown();
+                });
+                try {
+                    latch.await(30, TimeUnit.SECONDS);
+                } catch (InterruptedException e) {
+                    throw new IllegalStateException(e);
+                }
                 return null;
             }
             case MediaStore.SCAN_FILE_CALL:
diff --git a/src/com/android/providers/media/util/BackgroundThread.java b/src/com/android/providers/media/util/BackgroundThread.java
deleted file mode 100644
index 90d10a3..0000000
--- a/src/com/android/providers/media/util/BackgroundThread.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.android.providers.media.util;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 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 ForegroundThread
- */
-public final class BackgroundThread extends HandlerThread {
-    private static BackgroundThread sInstance;
-    private static Handler sHandler;
-    private static HandlerExecutor sHandlerExecutor;
-
-    private BackgroundThread() {
-        super("bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
-    }
-
-    private static void ensureThreadLocked() {
-        if (sInstance == null) {
-            sInstance = new BackgroundThread();
-            sInstance.start();
-            sHandler = new Handler(sInstance.getLooper());
-            sHandlerExecutor = new HandlerExecutor(sHandler);
-        }
-    }
-
-    public static BackgroundThread get() {
-        synchronized (BackgroundThread.class) {
-            ensureThreadLocked();
-            return sInstance;
-        }
-    }
-
-    public static Handler getHandler() {
-        synchronized (BackgroundThread.class) {
-            ensureThreadLocked();
-            return sHandler;
-        }
-    }
-
-    public static Executor getExecutor() {
-        synchronized (BackgroundThread.class) {
-            ensureThreadLocked();
-            return sHandlerExecutor;
-        }
-    }
-
-    public static void waitForIdle() {
-        final CountDownLatch latch = new CountDownLatch(1);
-        getExecutor().execute(() -> {
-            latch.countDown();
-        });
-        try {
-            latch.await(30, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-}
diff --git a/src/com/android/providers/media/util/ForegroundThread.java b/src/com/android/providers/media/util/ForegroundThread.java
index 436c1b8..0d65a91 100644
--- a/src/com/android/providers/media/util/ForegroundThread.java
+++ b/src/com/android/providers/media/util/ForegroundThread.java
@@ -19,6 +19,8 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 
+import com.android.modules.utils.HandlerExecutor;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
diff --git a/src/com/android/providers/media/util/HandlerExecutor.java b/src/com/android/providers/media/util/HandlerExecutor.java
deleted file mode 100644
index 4d1b4ac..0000000
--- a/src/com/android/providers/media/util/HandlerExecutor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.providers.media.util;
-
-import android.os.Handler;
-
-import androidx.annotation.NonNull;
-
-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}.
- *
- * @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");
-        }
-    }
-}
diff --git a/tests/Android.bp b/tests/Android.bp
index 4131a16..695793e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -46,6 +46,7 @@
         "guava",
         "mockito-target",
         "truth-prebuilt",
+        "modules-utils-backgroundthread",
     ],
 
     certificate: "media",
diff --git a/tests/src/com/android/providers/media/util/BackgroundThreadTest.java b/tests/src/com/android/providers/media/util/BackgroundThreadTest.java
deleted file mode 100644
index 91514c0..0000000
--- a/tests/src/com/android/providers/media/util/BackgroundThreadTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.providers.media.util;
-
-import static org.junit.Assert.assertNotNull;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class BackgroundThreadTest {
-    @Test
-    public void testSimple() {
-        assertNotNull(BackgroundThread.get());
-        assertNotNull(BackgroundThread.getExecutor());
-        assertNotNull(BackgroundThread.getHandler());
-    }
-}