Fixing deadlock in dagger singletons

Bug: 373557167
Flag: EXEMPT dagger
Test: atest DaggerSingletonDeadlockTest

Change-Id: I2304237bfd818c99b82bbfceea8a81ddb136b5a1
diff --git a/tests/Android.bp b/tests/Android.bp
index 9f62d02..9667277 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -98,6 +98,8 @@
         "com_android_launcher3_flags_lib",
         "com_android_wm_shell_flags_lib",
         "android.appwidget.flags-aconfig-java",
+        "platform-parametric-runner-lib",
+        "kotlin-reflect",
     ],
     manifest: "AndroidManifest-common.xml",
     platform_apis: true,
@@ -111,6 +113,9 @@
     asset_dirs: ["assets"],
     // TODO(b/319712088): re-enable use_resource_processor
     use_resource_processor: false,
+    static_libs: [
+        "kotlin-reflect",
+    ],
 }
 
 android_test {
@@ -193,10 +198,7 @@
     name: "Launcher3RoboTests",
     srcs: [
         ":launcher3-robo-src",
-
-        // Test util classes
         ":launcher-testing-helpers-robo",
-        ":launcher-testing-shared",
     ],
     exclude_srcs: [
         //"src/com/android/launcher3/util/CellContentDimensionsTest.kt", // Failing - b/316553889
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DaggerSingletonDeadlockTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DaggerSingletonDeadlockTest.kt
new file mode 100644
index 0000000..642c628
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/util/DaggerSingletonDeadlockTest.kt
@@ -0,0 +1,77 @@
+/*
+ * 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 com.android.launcher3.util
+
+import androidx.test.filters.SmallTest
+import com.android.launcher3.dagger.LauncherAppComponent
+import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
+import java.util.concurrent.TimeUnit.SECONDS
+import kotlin.reflect.KFunction
+import kotlin.reflect.full.memberFunctions
+import org.junit.After
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
+
+@SmallTest
+@RunWith(ParameterizedAndroidJunit4::class)
+class DaggerSingletonDeadlockTest(val method: KFunction<*>, val methodName: String) {
+
+    private val context = SandboxModelContext()
+
+    @After
+    fun tearDown() {
+        context.onDestroy()
+    }
+
+    /** Test to verify that the object can be created successfully on the main thread. */
+    @Test
+    fun objectCreationOnMainThread() {
+        Executors.MAIN_EXECUTOR.submit {
+                method.call(context.appComponent).also(Assert::assertNotNull)
+            }
+            .get(10, SECONDS)
+    }
+
+    /**
+     * Test to verify that the object can be created successfully on the background thread, when the
+     * main thread is blocked.
+     */
+    @Test
+    fun objectCreationOnBackgroundThread() {
+        TestUtil.runOnExecutorSync(Executors.MAIN_EXECUTOR) {
+            Executors.THREAD_POOL_EXECUTOR.submit {
+                    method.call(context.appComponent).also(Assert::assertNotNull)
+                }
+                .get(10, SECONDS)
+        }
+    }
+
+    companion object {
+        @Parameters(name = "{1}")
+        @JvmStatic
+        fun getTestMethods() =
+            LauncherAppComponent::class
+                .memberFunctions
+                .filter { it.parameters.size == 1 }
+                .map {
+                    arrayOf(it, if (it.name.startsWith("get")) it.name.substring(3) else it.name)
+                }
+    }
+}