Merge "[GH] Fixes for GitHub playground" into androidx-main
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index 5f78595..05bd8ba 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -68,6 +68,7 @@
 import org.gradle.api.Task
 import org.gradle.api.component.SoftwareComponentFactory
 import org.gradle.api.file.DuplicatesStrategy
+import org.gradle.api.logging.LogLevel
 import org.gradle.api.plugins.JavaPlugin
 import org.gradle.api.plugins.JavaPluginExtension
 import org.gradle.api.tasks.Copy
@@ -758,6 +759,20 @@
             if (androidXExtension.shouldRelease()) {
                 project.extra.set("publish", true)
             }
+            if (project.hasBenchmarkPlugin()) {
+                // Inject AOT compilation - see b/287358254 for context, b/288167775 for AGP support
+
+                // NOTE: we assume here that all benchmarks have package name $namespace.test
+                val aotCompile = "cmd package compile -m speed -f $namespace.test"
+
+                // only run aotCompile on N+, where it's supported
+                val inject = "if [ `getprop ro.build.version.sdk` -ge 24 ]; then $aotCompile; fi"
+                val options =
+                    "/data/local/tmp/${project.name}-$testBuildType-androidTest.apk && $inject #"
+
+                project.logger.log(LogLevel.WARN, "Injecting benchmark compilation: $options")
+                adbOptions.setInstallOptions(*options.split(" ").toTypedArray())
+            }
         }
     }
 
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt
index 37239d7..4196f2f 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt
@@ -15,11 +15,15 @@
  */
 package androidx.camera.camera2.pipe.integration
 
+import android.content.Context
 import androidx.annotation.RequiresApi
-import androidx.camera.camera2.pipe.integration.adapter.CameraFactoryAdapter
+import androidx.annotation.RestrictTo
+import androidx.camera.camera2.pipe.CameraPipe
+import androidx.camera.camera2.pipe.integration.adapter.CameraFactoryProvider
 import androidx.camera.camera2.pipe.integration.adapter.CameraSurfaceAdapter
 import androidx.camera.camera2.pipe.integration.adapter.CameraUseCaseAdapter
 import androidx.camera.core.CameraXConfig
+import androidx.camera.core.impl.CameraThreadConfig
 
 /**
  * Convenience class for generating a pre-populated CameraPipe based [CameraXConfig].
@@ -27,14 +31,31 @@
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class CameraPipeConfig private constructor() {
     companion object {
-
         /**
          * Creates a [CameraXConfig] containing a default CameraPipe implementation for CameraX.
          */
         @JvmStatic
         fun defaultConfig(): CameraXConfig {
+            return from()
+        }
+
+        /**
+         * Creates a [CameraXConfig] using a pre-existing [CameraPipe] instance.
+         */
+        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        @JvmStatic
+        fun from(
+            sharedCameraPipe: CameraPipe? = null,
+            sharedAppContext: Context? = null,
+            sharedThreadConfig: CameraThreadConfig? = null
+        ): CameraXConfig {
+            val cameraFactoryProvider = CameraFactoryProvider(
+                sharedCameraPipe,
+                sharedAppContext,
+                sharedThreadConfig
+            )
             return CameraXConfig.Builder()
-                .setCameraFactoryProvider(::CameraFactoryAdapter)
+                .setCameraFactoryProvider(cameraFactoryProvider)
                 .setDeviceSurfaceManagerProvider(::CameraSurfaceAdapter)
                 .setUseCaseConfigFactoryProvider(::CameraUseCaseAdapter)
                 .build()
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
index fab238c..1aaab34 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
@@ -18,6 +18,7 @@
 import android.content.Context
 import androidx.annotation.RequiresApi
 import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraPipe
 import androidx.camera.camera2.pipe.core.Debug
 import androidx.camera.camera2.pipe.core.Log.debug
 import androidx.camera.camera2.pipe.core.SystemTimeSource
@@ -28,6 +29,7 @@
 import androidx.camera.camera2.pipe.integration.config.CameraAppConfig
 import androidx.camera.camera2.pipe.integration.config.CameraConfig
 import androidx.camera.camera2.pipe.integration.config.DaggerCameraAppComponent
+import androidx.camera.camera2.pipe.integration.impl.CameraInteropStateCallbackRepository
 import androidx.camera.camera2.pipe.integration.internal.CameraCompatibilityFilter
 import androidx.camera.camera2.pipe.integration.internal.CameraSelectionOptimizer
 import androidx.camera.core.CameraInfo
@@ -43,24 +45,32 @@
  * to share resources across Camera instances.
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-class CameraFactoryAdapter(
+internal class CameraFactoryAdapter(
+    lazyCameraPipe: Lazy<CameraPipe>,
     context: Context,
     threadConfig: CameraThreadConfig,
-    availableCamerasSelector: CameraSelector?
+    camera2InteropCallbacks: CameraInteropStateCallbackRepository,
+    availableCamerasSelector: CameraSelector?,
 ) : CameraFactory {
     private val appComponent: CameraAppComponent by lazy {
         Debug.traceStart { "CameraFactoryAdapter#appComponent" }
         val timeSource = SystemTimeSource()
         val start = Timestamps.now(timeSource)
         val result = DaggerCameraAppComponent.builder()
-            .config(CameraAppConfig(context, threadConfig))
+            .config(
+                CameraAppConfig(
+                    context,
+                    threadConfig,
+                    lazyCameraPipe.value,
+                    camera2InteropCallbacks
+                )
+            )
             .build()
         debug { "Created CameraFactoryAdapter in ${start.measureNow(timeSource).formatMs()}" }
         debug { "availableCamerasSelector: $availableCamerasSelector " }
         Debug.traceStop()
         result
     }
-
     private var mAvailableCamerasSelector: CameraSelector? = availableCamerasSelector
     private var mAvailableCameraIds: List<String>
 
@@ -124,5 +134,5 @@
         }
     }
 
-    override fun getCameraManager(): Any? = appComponent
+    override fun getCameraManager(): Any = appComponent
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryProvider.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryProvider.kt
new file mode 100644
index 0000000..91cc123
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryProvider.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2023 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 androidx.camera.camera2.pipe.integration.adapter
+
+import android.content.Context
+import androidx.annotation.GuardedBy
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraPipe
+import androidx.camera.camera2.pipe.core.Debug
+import androidx.camera.camera2.pipe.core.Log
+import androidx.camera.camera2.pipe.core.SystemTimeSource
+import androidx.camera.camera2.pipe.core.Timestamps
+import androidx.camera.camera2.pipe.core.Timestamps.formatMs
+import androidx.camera.camera2.pipe.core.Timestamps.measureNow
+import androidx.camera.camera2.pipe.integration.impl.CameraInteropStateCallbackRepository
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.impl.CameraFactory
+import androidx.camera.core.impl.CameraThreadConfig
+
+/**
+ * The [CameraFactoryProvider] is responsible for creating the root dagger component that is used
+ * to share resources across Camera instances.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+class CameraFactoryProvider(
+    private val sharedCameraPipe: CameraPipe? = null,
+    private val sharedAppContext: Context? = null,
+    private val sharedThreadConfig: CameraThreadConfig? = null
+) : CameraFactory.Provider {
+    private val cameraInteropStateCallbackRepository = CameraInteropStateCallbackRepository()
+    private val lock = Any()
+
+    @GuardedBy("lock")
+    private var cachedCameraPipe: Pair<Context, Lazy<CameraPipe>>? = null
+
+    override fun newInstance(
+        context: Context,
+        threadConfig: CameraThreadConfig,
+        availableCamerasLimiter: CameraSelector?
+    ): CameraFactory {
+
+        val lazyCameraPipe = getOrCreateCameraPipe(context)
+
+        return CameraFactoryAdapter(
+            lazyCameraPipe,
+            sharedAppContext ?: context,
+            sharedThreadConfig ?: threadConfig,
+            cameraInteropStateCallbackRepository,
+            availableCamerasLimiter
+        )
+    }
+
+    private fun getOrCreateCameraPipe(context: Context): Lazy<CameraPipe> {
+        if (sharedCameraPipe != null) {
+            return lazyOf(sharedCameraPipe)
+        }
+
+        synchronized(lock) {
+            val existing = cachedCameraPipe
+            if (existing == null) {
+                val sharedCameraPipe = lazy { createCameraPipe(context) }
+                cachedCameraPipe = context to sharedCameraPipe
+                return sharedCameraPipe
+            } else {
+                check(context == existing.first) {
+                    "Mismatched context! Expected ${existing.first} but was $context"
+                }
+                return existing.second
+            }
+        }
+    }
+
+    private fun createCameraPipe(context: Context): CameraPipe {
+        Debug.traceStart { "Create CameraPipe" }
+        val timeSource = SystemTimeSource()
+        val start = Timestamps.now(timeSource)
+
+        val cameraPipe = CameraPipe(
+            CameraPipe.Config(
+                appContext = context.applicationContext,
+                cameraInteropConfig = CameraPipe.CameraInteropConfig(
+                    cameraInteropStateCallbackRepository.deviceStateCallback,
+                    cameraInteropStateCallbackRepository.sessionStateCallback
+                )
+            )
+        )
+        Log.debug { "Created CameraPipe in ${start.measureNow(timeSource).formatMs()}" }
+        Debug.traceStop()
+        return cameraPipe
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt
index 2f41d39..2ba8e67 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt
@@ -36,21 +36,6 @@
 )
 abstract class CameraAppModule {
     companion object {
-        @Singleton
-        @Provides
-        fun provideCameraPipe(
-            context: Context,
-            cameraInteropStateCallbackRepository: CameraInteropStateCallbackRepository
-        ): CameraPipe = CameraPipe(
-            CameraPipe.Config(
-                appContext = context.applicationContext,
-                cameraInteropConfig = CameraPipe.CameraInteropConfig(
-                    cameraInteropStateCallbackRepository.deviceStateCallback,
-                    cameraInteropStateCallbackRepository.sessionStateCallback
-                )
-            )
-        )
-
         @Provides
         fun provideCameraDevices(cameraPipe: CameraPipe): CameraDevices {
             return cameraPipe.cameras()
@@ -63,12 +48,21 @@
 class CameraAppConfig(
     private val context: Context,
     private val cameraThreadConfig: CameraThreadConfig,
+    private val cameraPipe: CameraPipe,
+    private val camera2InteropCallbacks: CameraInteropStateCallbackRepository
 ) {
     @Provides
     fun provideContext(): Context = context
 
     @Provides
     fun provideCameraThreadConfig(): CameraThreadConfig = cameraThreadConfig
+
+    @Provides
+    fun provideCameraPipe(): CameraPipe = cameraPipe
+
+    @Provides
+    fun provideCamera2InteropCallbacks(): CameraInteropStateCallbackRepository =
+        camera2InteropCallbacks
 }
 
 /** Dagger component for Application (Process) scoped dependencies. */
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraInteropStateCallbackRepository.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraInteropStateCallbackRepository.kt
index 179fcb0..02b7507 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraInteropStateCallbackRepository.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraInteropStateCallbackRepository.kt
@@ -24,20 +24,17 @@
 import androidx.annotation.RequiresApi
 import androidx.camera.camera2.pipe.core.Log
 import androidx.camera.core.impl.SessionConfig
-import javax.inject.Inject
-import javax.inject.Singleton
 import kotlinx.atomicfu.AtomicRef
 import kotlinx.atomicfu.atomic
 
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-@Singleton
 /**
  * A application-level single-instance repository for Camera Interop callbacks. It supplies
  * camera-pipe with internal callbacks on CameraX initialization. During runtime, before a camera
  * graph is created, CameraX updates these internal callbacks with Camera Interop callbacks so that
  * they may be triggered in camera-pipe.
  */
-class CameraInteropStateCallbackRepository @Inject constructor() {
+class CameraInteropStateCallbackRepository {
 
     private val _deviceStateCallback = CameraInteropDeviceStateCallback()
     private val _sessionStateCallback = CameraInteropSessionStateCallback()
@@ -61,7 +58,7 @@
     val sessionStateCallback
         get() = _sessionStateCallback
 
-    class CameraInteropDeviceStateCallback() : CameraDevice.StateCallback() {
+    class CameraInteropDeviceStateCallback : CameraDevice.StateCallback() {
 
         private var callbacks: AtomicRef<List<CameraDevice.StateCallback>> = atomic(listOf())
         internal fun updateCallbacks(sessionConfig: SessionConfig) {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizer.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizer.kt
index 35bc8dd..5179c88 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizer.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizer.kt
@@ -21,12 +21,12 @@
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.DoNotDisturbException
 import androidx.camera.camera2.pipe.core.Log
-import androidx.camera.camera2.pipe.integration.adapter.CameraFactoryAdapter
 import androidx.camera.camera2.pipe.integration.config.CameraAppComponent
 import androidx.camera.camera2.pipe.integration.config.CameraConfig
 import androidx.camera.core.CameraInfo
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.InitializationException
+import androidx.camera.core.impl.CameraFactory
 import androidx.camera.core.impl.CameraInfoInternal
 
 /**
@@ -34,12 +34,12 @@
  * passed CameraSelector
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-class CameraSelectionOptimizer {
+internal class CameraSelectionOptimizer {
     companion object {
 
         @Throws(InitializationException::class)
         fun getSelectedAvailableCameraIds(
-            cameraFactory: CameraFactoryAdapter,
+            cameraFactory: CameraFactory,
             availableCamerasSelector: CameraSelector?
         ): List<String> {
             try {
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraCompatibilityFilterTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraCompatibilityFilterTest.kt
index 3b7478a..6af4773 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraCompatibilityFilterTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraCompatibilityFilterTest.kt
@@ -23,7 +23,7 @@
 import android.os.Build
 import android.os.Handler
 import android.os.Looper
-import androidx.camera.camera2.pipe.integration.adapter.CameraFactoryAdapter
+import androidx.camera.camera2.pipe.integration.adapter.CameraFactoryProvider
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.impl.CameraThreadConfig
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
@@ -67,8 +67,8 @@
         ReflectionHelpers.setStaticField(Build::class.java, "FINGERPRINT", "fake-fingerprint")
 
         setupCameras()
-        val cameraFactoryAdapter = CameraFactoryAdapter(
-            ApplicationProvider.getApplicationContext<Context>(), CameraThreadConfig.create(
+        val cameraFactoryAdapter = CameraFactoryProvider().newInstance(
+            ApplicationProvider.getApplicationContext(), CameraThreadConfig.create(
                 CameraXExecutors.mainThreadExecutor(), Handler(Looper.getMainLooper())
             ), null
         )
@@ -84,7 +84,7 @@
 
         setupCameras()
 
-        val cameraFactoryAdapter = CameraFactoryAdapter(
+        val cameraFactoryAdapter = CameraFactoryProvider().newInstance(
             ApplicationProvider.getApplicationContext(), CameraThreadConfig.create(
                 CameraXExecutors.mainThreadExecutor(), Handler(Looper.getMainLooper())
             ), CameraSelector.DEFAULT_BACK_CAMERA
@@ -97,7 +97,7 @@
     fun NotFilterOutIncompatibleCameras_whenBuildFingerprintIsRobolectric() {
         setupCameras()
 
-        val cameraFactoryAdapter = CameraFactoryAdapter(
+        val cameraFactoryAdapter = CameraFactoryProvider().newInstance(
             ApplicationProvider.getApplicationContext(), CameraThreadConfig.create(
                 CameraXExecutors.mainThreadExecutor(), Handler(Looper.getMainLooper())
             ), null
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizerTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizerTest.kt
index df10f33..f22f016 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizerTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraSelectionOptimizerTest.kt
@@ -22,17 +22,17 @@
 import android.os.Build
 import android.os.Handler
 import android.os.Looper
-import androidx.camera.camera2.pipe.integration.adapter.CameraFactoryAdapter
+import androidx.camera.camera2.pipe.integration.adapter.CameraFactoryProvider
 import androidx.camera.camera2.pipe.integration.interop.Camera2CameraInfo
 import androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop
 import androidx.camera.core.CameraFilter
 import androidx.camera.core.CameraInfo
 import androidx.camera.core.CameraSelector
+import androidx.camera.core.impl.CameraFactory
 import androidx.camera.core.impl.CameraThreadConfig
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
 import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth
-import java.util.Arrays
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito
@@ -51,24 +51,16 @@
     instrumentedPackages = ["androidx.camera.camera2.pipe.integration.adapter"]
 )
 class CameraSelectionOptimizerTest {
+    private lateinit var cameraFactory: CameraFactory
 
-    private var mCameraFactoryAdapter: CameraFactoryAdapter = CameraFactoryAdapter(
-        ApplicationProvider.getApplicationContext<Context>(),
-        CameraThreadConfig.create(
-            CameraXExecutors.mainThreadExecutor(),
-            Handler(Looper.getMainLooper())
-        ),
-        null
-    )
-
-    fun setupNormalCameras() {
+    private fun setupNormalCameras() {
         initCharacteristics("0", CameraCharacteristics.LENS_FACING_BACK, 3.52f)
         initCharacteristics("1", CameraCharacteristics.LENS_FACING_FRONT, 3.52f)
         initCharacteristics("2", CameraCharacteristics.LENS_FACING_BACK, 2.7f)
         initCharacteristics("3", CameraCharacteristics.LENS_FACING_BACK, 10.0f)
     }
 
-    fun setupAbnormalCameras() {
+    private fun setupAbnormalCameras() {
         // "0" is front
         initCharacteristics("0", CameraCharacteristics.LENS_FACING_FRONT, 3.52f)
         // "1" is back
@@ -96,7 +88,7 @@
         val cameraIds: List<String> = getCameraIdsBasedOnCameraSelector(cameraSelector)
 
         Truth.assertThat(cameraIds).containsExactly("0", "2", "3")
-        Mockito.verify<CameraFactoryAdapter>(mCameraFactoryAdapter, Mockito.never())
+        Mockito.verify(cameraFactory, Mockito.never())
             .getCamera("1")
     }
 
@@ -111,7 +103,7 @@
 
         val cameraIds: List<String> = getCameraIdsBasedOnCameraSelector(cameraSelector)
         Truth.assertThat(cameraIds).containsExactly("1")
-        Mockito.verify<CameraFactoryAdapter>(mCameraFactoryAdapter, Mockito.never())
+        Mockito.verify(cameraFactory, Mockito.never())
             .getCamera("0")
     }
 
@@ -134,7 +126,7 @@
                     minFocalCameraInfo = cameraInfo
                 }
             }
-            Arrays.asList(minFocalCameraInfo)
+            listOf(minFocalCameraInfo)
         }
         val cameraSelector = CameraSelector.Builder()
             .requireLensFacing(CameraSelector.LENS_FACING_BACK)
@@ -143,7 +135,7 @@
         val cameraIds: List<String> = getCameraIdsBasedOnCameraSelector(cameraSelector)
         Truth.assertThat(cameraIds).containsExactly("2")
         // only camera "1" 's getCameraCharacteristics can be avoided.
-        Mockito.verify<CameraFactoryAdapter>(mCameraFactoryAdapter, Mockito.never())
+        Mockito.verify(cameraFactory, Mockito.never())
             .getCamera("1")
     }
 
@@ -201,24 +193,19 @@
     }
 
     private fun getCameraIdsBasedOnCameraSelector(cameraSelector: CameraSelector?): List<String> {
-
-        mCameraFactoryAdapter = Mockito.spy(
-            CameraFactoryAdapter(
-                ApplicationProvider.getApplicationContext<Context>(),
-                CameraThreadConfig.create(
-                    CameraXExecutors.mainThreadExecutor(),
-                    Handler(Looper.getMainLooper())
-                ),
-                cameraSelector
-            )
+        val actualCameraFactory = CameraFactoryProvider().newInstance(
+            ApplicationProvider.getApplicationContext(), CameraThreadConfig.create(
+                CameraXExecutors.mainThreadExecutor(), Handler(Looper.getMainLooper())
+            ),
+            cameraSelector
         )
 
-        val cameraIds: List<String> =
-            CameraSelectionOptimizer.getSelectedAvailableCameraIds(
-                mCameraFactoryAdapter,
-                cameraSelector
-            )
-        return cameraIds
+        cameraFactory = Mockito.spy(actualCameraFactory)
+
+        return CameraSelectionOptimizer.getSelectedAvailableCameraIds(
+            cameraFactory,
+            cameraSelector
+        )
     }
 
     private fun initCharacteristics(cameraId: String, lensFacing: Int, focalLength: Float) {
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index 1804337..ea85035 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -1007,6 +1007,8 @@
 xcframework successfully .*
 # > Configure project :internal-testutils-ktx
 WARNING:.*The option setting 'android\.r8\.maxWorkers=[0-9]+' is experimental\.
+# Injecting benchmark compilation shell warning
+Injecting benchmark compilation: .*
 # Building XCFrameworks (b/260140834) and iOS benchmark invocation
 Observed package id 'platforms;android-33-ext5' in inconsistent location.*
 .*xcodebuild.*