Refactor BluetoothTileDialog into BluetoothTileDialogDelegate

Removes the SystemUIDialog from BluetoothTileDialog

Flag: NA
Test: atest SystemUITests:com.android.systemui.qs.tiles.dialog.bluetooth
Bug: 219008720
Change-Id: Ieea93e483fd3a33ae193791f7e92d472e53ce5ea
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
similarity index 67%
rename from packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt
rename to packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
index 6b53c7a..7ece6e0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
@@ -37,11 +37,13 @@
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.android.internal.logging.UiEventLogger
-import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.util.time.SystemClock
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.MutableSharedFlow
@@ -52,19 +54,24 @@
 import kotlinx.coroutines.withContext
 
 /** Dialog for showing active, connected and saved bluetooth devices. */
-@SysUISingleton
-internal class BluetoothTileDialog
-constructor(
-    private val bluetoothToggleInitialValue: Boolean,
-    private val initialUiProperties: BluetoothTileDialogViewModel.UiProperties,
-    private val cachedContentHeight: Int,
-    private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
+class BluetoothTileDialogDelegate
+@AssistedInject
+internal constructor(
+    @Assisted private val context: Context,
+    @Assisted private val initialUiProperties: BluetoothTileDialogViewModel.UiProperties,
+    @Assisted private val cachedContentHeight: Int,
+    @Assisted private val bluetoothToggleInitialValue: Boolean,
+    @Assisted private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
+    @Assisted private val dismissListener: Runnable,
     @Main private val mainDispatcher: CoroutineDispatcher,
     private val systemClock: SystemClock,
     private val uiEventLogger: UiEventLogger,
     private val logger: BluetoothTileDialogLogger,
-    context: Context,
-) : SystemUIDialog(context, DEFAULT_THEME, DEFAULT_DISMISS_ON_DEVICE_LOCK) {
+    private val systemuiDialogFactory: SystemUIDialog.Factory,
+    mainLayoutInflater: LayoutInflater,
+) : SystemUIDialog.Delegate {
+
+    private val layoutInflater = mainLayoutInflater.cloneInContext(context)
 
     private val mutableBluetoothStateToggle: MutableStateFlow<Boolean> =
         MutableStateFlow(bluetoothToggleInitialValue)
@@ -91,78 +98,72 @@
 
     private var lastItemRow: Int = -1
 
-    private lateinit var toggleView: Switch
-    private lateinit var subtitleTextView: TextView
-    private lateinit var autoOnToggle: Switch
-    private lateinit var autoOnToggleView: View
-    private lateinit var doneButton: View
-    private lateinit var seeAllButton: View
-    private lateinit var pairNewDeviceButton: View
-    private lateinit var deviceListView: RecyclerView
-    private lateinit var scrollViewContent: View
-    private lateinit var progressBarAnimation: ProgressBar
-    private lateinit var progressBarBackground: View
+    @AssistedFactory
+    internal interface Factory {
+        fun create(
+            context: Context,
+            initialUiProperties: BluetoothTileDialogViewModel.UiProperties,
+            cachedContentHeight: Int,
+            bluetoothEnabled: Boolean,
+            dialogCallback: BluetoothTileDialogCallback,
+            dimissListener: Runnable
+        ): BluetoothTileDialogDelegate
+    }
 
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
+    override fun createDialog(): SystemUIDialog {
+        val dialog = systemuiDialogFactory.create(this, context)
+
+        return dialog
+    }
+
+    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+        SystemUIDialog.registerDismissListener(dialog, dismissListener)
         uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_TILE_DIALOG_SHOWN)
 
-        LayoutInflater.from(context).inflate(R.layout.bluetooth_tile_dialog, null).apply {
+        layoutInflater.inflate(R.layout.bluetooth_tile_dialog, null).apply {
             accessibilityPaneTitle = context.getText(R.string.accessibility_desc_quick_settings)
-            setContentView(this)
+            dialog.setContentView(this)
         }
 
-        toggleView = requireViewById(R.id.bluetooth_toggle)
-        subtitleTextView = requireViewById(R.id.bluetooth_tile_dialog_subtitle) as TextView
-        autoOnToggle = requireViewById(R.id.bluetooth_auto_on_toggle)
-        autoOnToggleView = requireViewById(R.id.bluetooth_auto_on_toggle_layout)
-        doneButton = requireViewById(R.id.done_button)
-        seeAllButton = requireViewById(R.id.see_all_button)
-        pairNewDeviceButton = requireViewById(R.id.pair_new_device_button)
-        deviceListView = requireViewById<RecyclerView>(R.id.device_list)
+        setupToggle(dialog)
+        setupRecyclerView(dialog)
 
-        setupToggle()
-        setupRecyclerView()
-
-        subtitleTextView.text = context.getString(initialUiProperties.subTitleResId)
-        doneButton.setOnClickListener { dismiss() }
-        seeAllButton.setOnClickListener { bluetoothTileDialogCallback.onSeeAllClicked(it) }
-        pairNewDeviceButton.setOnClickListener {
+        getSubtitleTextView(dialog).text = context.getString(initialUiProperties.subTitleResId)
+        dialog.requireViewById<View>(R.id.done_button).setOnClickListener { dialog.dismiss() }
+        getSeeAllButton(dialog).setOnClickListener {
+            bluetoothTileDialogCallback.onSeeAllClicked(it)
+        }
+        getPairNewDeviceButton(dialog).setOnClickListener {
             bluetoothTileDialogCallback.onPairNewDeviceClicked(it)
         }
-        requireViewById<View>(R.id.scroll_view).apply {
-            scrollViewContent = this
+        getScrollViewContent(dialog).apply {
             minimumHeight =
                 resources.getDimensionPixelSize(initialUiProperties.scrollViewMinHeightResId)
             layoutParams.height = maxOf(cachedContentHeight, minimumHeight)
         }
-        progressBarAnimation = requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
-        progressBarBackground = requireViewById(R.id.bluetooth_tile_dialog_progress_background)
     }
 
-    override fun start() {
+    override fun onStart(dialog: SystemUIDialog) {
         lastUiUpdateMs = systemClock.elapsedRealtime()
     }
 
-    override fun dismiss() {
-        if (::scrollViewContent.isInitialized) {
-            mutableContentHeight.tryEmit(scrollViewContent.measuredHeight)
-        }
-        super.dismiss()
+    override fun onStop(dialog: SystemUIDialog) {
+        mutableContentHeight.tryEmit(getScrollViewContent(dialog).measuredHeight)
     }
 
-    internal suspend fun animateProgressBar(animate: Boolean) {
+    internal suspend fun animateProgressBar(dialog: SystemUIDialog, animate: Boolean) {
         withContext(mainDispatcher) {
             if (animate) {
-                showProgressBar()
+                showProgressBar(dialog)
             } else {
                 delay(PROGRESS_BAR_ANIMATION_DURATION_MS)
-                hideProgressBar()
+                hideProgressBar(dialog)
             }
         }
     }
 
     internal suspend fun onDeviceItemUpdated(
+        dialog: SystemUIDialog,
         deviceItem: List<DeviceItem>,
         showSeeAll: Boolean,
         showPairNewDevice: Boolean
@@ -176,10 +177,11 @@
             }
             if (isActive) {
                 deviceItemAdapter.refreshDeviceItemList(deviceItem) {
-                    seeAllButton.visibility = if (showSeeAll) VISIBLE else GONE
-                    pairNewDeviceButton.visibility = if (showPairNewDevice) VISIBLE else GONE
+                    getSeeAllButton(dialog).visibility = if (showSeeAll) VISIBLE else GONE
+                    getPairNewDeviceButton(dialog).visibility =
+                        if (showPairNewDevice) VISIBLE else GONE
                     // Update the height after data is updated
-                    scrollViewContent.layoutParams.height = WRAP_CONTENT
+                    getScrollViewContent(dialog).layoutParams.height = WRAP_CONTENT
                     lastUiUpdateMs = systemClock.elapsedRealtime()
                     lastItemRow = itemRow
                     logger.logDeviceUiUpdate(lastUiUpdateMs - start)
@@ -189,29 +191,29 @@
     }
 
     internal fun onBluetoothStateUpdated(
+        dialog: SystemUIDialog,
         isEnabled: Boolean,
         uiProperties: BluetoothTileDialogViewModel.UiProperties
     ) {
-        toggleView.apply {
+        getToggleView(dialog).apply {
             isChecked = isEnabled
             setEnabled(true)
             alpha = ENABLED_ALPHA
         }
-        subtitleTextView.text = context.getString(uiProperties.subTitleResId)
-        autoOnToggleView.visibility = uiProperties.autoOnToggleVisibility
+        getSubtitleTextView(dialog).text = context.getString(uiProperties.subTitleResId)
+        getAutoOnToggleView(dialog).visibility = uiProperties.autoOnToggleVisibility
     }
 
-    internal fun onBluetoothAutoOnUpdated(isEnabled: Boolean) {
-        if (::autoOnToggle.isInitialized) {
-            autoOnToggle.apply {
-                isChecked = isEnabled
-                setEnabled(true)
-                alpha = ENABLED_ALPHA
-            }
+    internal fun onBluetoothAutoOnUpdated(dialog: SystemUIDialog, isEnabled: Boolean) {
+        getAutoOnToggle(dialog).apply {
+            isChecked = isEnabled
+            setEnabled(true)
+            alpha = ENABLED_ALPHA
         }
     }
 
-    private fun setupToggle() {
+    private fun setupToggle(dialog: SystemUIDialog) {
+        val toggleView = getToggleView(dialog)
         toggleView.isChecked = bluetoothToggleInitialValue
         toggleView.setOnCheckedChangeListener { view, isChecked ->
             mutableBluetoothStateToggle.value = isChecked
@@ -223,8 +225,8 @@
             uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_TOGGLE_CLICKED)
         }
 
-        autoOnToggleView.visibility = initialUiProperties.autoOnToggleVisibility
-        autoOnToggle.setOnCheckedChangeListener { view, isChecked ->
+        getAutoOnToggleView(dialog).visibility = initialUiProperties.autoOnToggleVisibility
+        getAutoOnToggle(dialog).setOnCheckedChangeListener { view, isChecked ->
             mutableBluetoothAutoOnToggle.value = isChecked
             view.apply {
                 isEnabled = false
@@ -234,30 +236,66 @@
         }
     }
 
-    private fun setupRecyclerView() {
-        deviceListView.apply {
+    private fun getToggleView(dialog: SystemUIDialog): Switch {
+        return dialog.requireViewById(R.id.bluetooth_toggle)
+    }
+
+    private fun getSubtitleTextView(dialog: SystemUIDialog): TextView {
+        return dialog.requireViewById(R.id.bluetooth_tile_dialog_subtitle)
+    }
+
+    private fun getSeeAllButton(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.see_all_button)
+    }
+
+    private fun getPairNewDeviceButton(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.pair_new_device_button)
+    }
+
+    private fun getDeviceListView(dialog: SystemUIDialog): RecyclerView {
+        return dialog.requireViewById(R.id.device_list)
+    }
+
+    private fun getAutoOnToggle(dialog: SystemUIDialog): Switch {
+        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle)
+    }
+
+    private fun getAutoOnToggleView(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_layout)
+    }
+
+    private fun getProgressBarAnimation(dialog: SystemUIDialog): ProgressBar {
+        return dialog.requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
+    }
+
+    private fun getProgressBarBackground(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
+    }
+
+    private fun getScrollViewContent(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.scroll_view)
+    }
+
+    private fun setupRecyclerView(dialog: SystemUIDialog) {
+        getDeviceListView(dialog).apply {
             layoutManager = LinearLayoutManager(context)
             adapter = deviceItemAdapter
         }
     }
 
-    private fun showProgressBar() {
-        if (
-            ::progressBarAnimation.isInitialized &&
-                ::progressBarBackground.isInitialized &&
-                progressBarAnimation.visibility != VISIBLE
-        ) {
+    private fun showProgressBar(dialog: SystemUIDialog) {
+        val progressBarAnimation = getProgressBarAnimation(dialog)
+        val progressBarBackground = getProgressBarBackground(dialog)
+        if (progressBarAnimation.visibility != VISIBLE) {
             progressBarAnimation.visibility = VISIBLE
             progressBarBackground.visibility = INVISIBLE
         }
     }
 
-    private fun hideProgressBar() {
-        if (
-            ::progressBarAnimation.isInitialized &&
-                ::progressBarBackground.isInitialized &&
-                progressBarAnimation.visibility != INVISIBLE
-        ) {
+    private fun hideProgressBar(dialog: SystemUIDialog) {
+        val progressBarAnimation = getProgressBarAnimation(dialog)
+        val progressBarBackground = getProgressBarBackground(dialog)
+        if (progressBarAnimation.visibility != INVISIBLE) {
             progressBarAnimation.visibility = INVISIBLE
             progressBarBackground.visibility = VISIBLE
         }
@@ -295,9 +333,7 @@
         private val asyncListDiffer = AsyncListDiffer(this, diffUtilCallback)
 
         override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DeviceItemViewHolder {
-            val view =
-                LayoutInflater.from(parent.context)
-                    .inflate(R.layout.bluetooth_device_item, parent, false)
+            val view = layoutInflater.inflate(R.layout.bluetooth_device_item, parent, false)
             return DeviceItemViewHolder(view)
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
index 5a14e5f..0486207 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
@@ -38,13 +38,11 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialog.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialog.Companion.ACTION_PAIR_NEW_DEVICE
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialog.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialog.Companion.MAX_DEVICE_ITEM_ENTRY
+import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
+import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE
+import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE
+import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.MAX_DEVICE_ITEM_ENTRY
 import com.android.systemui.res.R
-import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -67,13 +65,12 @@
     private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor,
     private val dialogTransitionAnimator: DialogTransitionAnimator,
     private val activityStarter: ActivityStarter,
-    private val systemClock: SystemClock,
     private val uiEventLogger: UiEventLogger,
-    private val logger: BluetoothTileDialogLogger,
     @Application private val coroutineScope: CoroutineScope,
     @Main private val mainDispatcher: CoroutineDispatcher,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     @Main private val sharedPreferences: SharedPreferences,
+    private val bluetoothDialogDelegateFactory: BluetoothTileDialogDelegate.Factory,
 ) : BluetoothTileDialogCallback {
 
     private var job: Job? = null
@@ -92,7 +89,8 @@
             coroutineScope.launch(mainDispatcher) {
                 var updateDeviceItemJob: Job?
                 var updateDialogUiJob: Job? = null
-                val dialog = createBluetoothTileDialog(context)
+                val dialogDelegate = createBluetoothTileDialog(context)
+                val dialog = dialogDelegate.createDialog()
 
                 view?.let {
                     dialogTransitionAnimator.showFromView(
@@ -118,13 +116,14 @@
                     .onEach {
                         updateDialogUiJob?.cancel()
                         updateDialogUiJob = launch {
-                            dialog.apply {
+                            dialogDelegate.apply {
                                 onDeviceItemUpdated(
+                                    dialog,
                                     it.take(MAX_DEVICE_ITEM_ENTRY),
                                     showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY,
                                     showPairNewDevice = bluetoothStateInteractor.isBluetoothEnabled
                                 )
-                                animateProgressBar(false)
+                                animateProgressBar(dialog, false)
                             }
                         }
                     }
@@ -134,7 +133,7 @@
                 // the device item list and animiate the progress bar.
                 deviceItemInteractor.deviceItemUpdateRequest
                     .onEach {
-                        dialog.animateProgressBar(true)
+                        dialogDelegate.animateProgressBar(dialog, true)
                         updateDeviceItemJob?.cancel()
                         updateDeviceItemJob = launch {
                             deviceItemInteractor.updateDeviceItems(
@@ -150,7 +149,8 @@
                 bluetoothStateInteractor.bluetoothStateUpdate
                     .filterNotNull()
                     .onEach {
-                        dialog.onBluetoothStateUpdated(
+                        dialogDelegate.onBluetoothStateUpdated(
+                            dialog,
                             it,
                             UiProperties.build(it, isAutoOnToggleFeatureAvailable())
                         )
@@ -166,20 +166,20 @@
 
                 // bluetoothStateToggle is emitted when user toggles the bluetooth state switch,
                 // send the new value to the bluetoothStateInteractor and animate the progress bar.
-                dialog.bluetoothStateToggle
+                dialogDelegate.bluetoothStateToggle
                     .onEach {
-                        dialog.animateProgressBar(true)
+                        dialogDelegate.animateProgressBar(dialog, true)
                         bluetoothStateInteractor.isBluetoothEnabled = it
                     }
                     .launchIn(this)
 
                 // deviceItemClick is emitted when user clicked on a device item.
-                dialog.deviceItemClick
+                dialogDelegate.deviceItemClick
                     .onEach { deviceItemInteractor.updateDeviceItemOnClick(it) }
                     .launchIn(this)
 
                 // contentHeight is emitted when the dialog is dismissed.
-                dialog.contentHeight
+                dialogDelegate.contentHeight
                     .onEach {
                         withContext(backgroundDispatcher) {
                             sharedPreferences.edit().putInt(CONTENT_HEIGHT_PREF_KEY, it).apply()
@@ -191,12 +191,12 @@
                     // bluetoothAutoOnUpdate is emitted when bluetooth auto on on/off state is
                     // changed.
                     bluetoothAutoOnInteractor.isEnabled
-                        .onEach { dialog.onBluetoothAutoOnUpdated(it) }
+                        .onEach { dialogDelegate.onBluetoothAutoOnUpdated(dialog, it) }
                         .launchIn(this)
 
                     // bluetoothAutoOnToggle is emitted when user toggles the bluetooth auto on
                     // switch, send the new value to the bluetoothAutoOnInteractor.
-                    dialog.bluetoothAutoOnToggle
+                    dialogDelegate.bluetoothAutoOnToggle
                         .filterNotNull()
                         .onEach { bluetoothAutoOnInteractor.setEnabled(it) }
                         .launchIn(this)
@@ -206,7 +206,7 @@
             }
     }
 
-    private suspend fun createBluetoothTileDialog(context: Context): BluetoothTileDialog {
+    private suspend fun createBluetoothTileDialog(context: Context): BluetoothTileDialogDelegate {
         val cachedContentHeight =
             withContext(backgroundDispatcher) {
                 sharedPreferences.getInt(
@@ -215,21 +215,17 @@
                 )
             }
 
-        return BluetoothTileDialog(
+        return bluetoothDialogDelegateFactory.create(
+            context,
+            UiProperties.build(
                 bluetoothStateInteractor.isBluetoothEnabled,
-                UiProperties.build(
-                    bluetoothStateInteractor.isBluetoothEnabled,
-                    isAutoOnToggleFeatureAvailable()
-                ),
-                cachedContentHeight,
-                this@BluetoothTileDialogViewModel,
-                mainDispatcher,
-                systemClock,
-                uiEventLogger,
-                logger,
-                context
-            )
-            .apply { SystemUIDialog.registerDismissListener(this) { cancelJob() } }
+                isAutoOnToggleFeatureAvailable()
+            ),
+            cachedContentHeight,
+            bluetoothStateInteractor.isBluetoothEnabled,
+            this@BluetoothTileDialogViewModel,
+            { cancelJob() }
+        )
     }
 
     override fun onDeviceItemGearClicked(deviceItem: DeviceItem, view: View) {
@@ -308,7 +304,7 @@
     }
 }
 
-internal interface BluetoothTileDialogCallback {
+interface BluetoothTileDialogCallback {
     fun onDeviceItemGearClicked(deviceItem: DeviceItem, view: View)
     fun onSeeAllClicked(view: View)
     fun onPairNewDeviceClicked(view: View)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegateTest.kt
new file mode 100644
index 0000000..8ecb953
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegateTest.kt
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 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 com.android.systemui.qs.tiles.dialog.bluetooth
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.model.SysUiState
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.phone.SystemUIDialogManager
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.test.TestCoroutineScheduler
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class BluetoothTileDialogDelegateTest : SysuiTestCase() {
+    companion object {
+        const val DEVICE_NAME = "device"
+        const val DEVICE_CONNECTION_SUMMARY = "active"
+        const val ENABLED = true
+        const val CONTENT_HEIGHT = WRAP_CONTENT
+    }
+
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice
+
+    @Mock private lateinit var bluetoothTileDialogCallback: BluetoothTileDialogCallback
+
+    @Mock private lateinit var drawable: Drawable
+
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+
+    @Mock private lateinit var logger: BluetoothTileDialogLogger
+
+    private val uiProperties =
+        BluetoothTileDialogViewModel.UiProperties.build(
+            isBluetoothEnabled = ENABLED,
+            isAutoOnToggleFeatureAvailable = ENABLED
+        )
+    @Mock private lateinit var sysuiDialogFactory: SystemUIDialog.Factory
+    @Mock private lateinit var dialogManager: SystemUIDialogManager
+    @Mock private lateinit var sysuiState: SysUiState
+    @Mock private lateinit var dialogTransitionAnimator: DialogTransitionAnimator
+
+    private val fakeSystemClock = FakeSystemClock()
+
+    private lateinit var scheduler: TestCoroutineScheduler
+    private lateinit var dispatcher: CoroutineDispatcher
+    private lateinit var testScope: TestScope
+    private lateinit var icon: Pair<Drawable, String>
+    private lateinit var mBluetoothTileDialogDelegate: BluetoothTileDialogDelegate
+    private lateinit var deviceItem: DeviceItem
+
+    @Before
+    fun setUp() {
+        scheduler = TestCoroutineScheduler()
+        dispatcher = UnconfinedTestDispatcher(scheduler)
+        testScope = TestScope(dispatcher)
+
+        whenever(sysuiState.setFlag(anyInt(), anyBoolean())).thenReturn(sysuiState)
+
+        mBluetoothTileDialogDelegate =
+            BluetoothTileDialogDelegate(
+                mContext,
+                uiProperties,
+                CONTENT_HEIGHT,
+                ENABLED,
+                bluetoothTileDialogCallback,
+                {},
+                dispatcher,
+                fakeSystemClock,
+                uiEventLogger,
+                logger,
+                sysuiDialogFactory,
+                LayoutInflater.from(mContext)
+            )
+
+        whenever(
+                sysuiDialogFactory.create(
+                    any(SystemUIDialog.Delegate::class.java),
+                    any(Context::class.java)
+                )
+            )
+            .thenAnswer {
+                SystemUIDialog(
+                    mContext,
+                    0,
+                    SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK,
+                    dialogManager,
+                    sysuiState,
+                    fakeBroadcastDispatcher,
+                    dialogTransitionAnimator,
+                    it.getArgument(0)
+                )
+            }
+
+        icon = Pair(drawable, DEVICE_NAME)
+        deviceItem =
+            DeviceItem(
+                type = DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
+                cachedBluetoothDevice = cachedBluetoothDevice,
+                deviceName = DEVICE_NAME,
+                connectionSummary = DEVICE_CONNECTION_SUMMARY,
+                iconWithDescription = icon,
+                background = null
+            )
+        `when`(cachedBluetoothDevice.isBusy).thenReturn(false)
+    }
+
+    @Test
+    fun testShowDialog_createRecyclerViewWithAdapter() {
+        val dialog = mBluetoothTileDialogDelegate.createDialog()
+        dialog.show()
+
+        val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
+
+        assertThat(recyclerView).isNotNull()
+        assertThat(recyclerView.visibility).isEqualTo(VISIBLE)
+        assertThat(recyclerView.adapter).isNotNull()
+        assertThat(recyclerView.layoutManager is LinearLayoutManager).isTrue()
+    }
+
+    @Test
+    fun testShowDialog_displayBluetoothDevice() {
+        testScope.runTest {
+            val dialog = mBluetoothTileDialogDelegate.createDialog()
+            dialog.show()
+            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
+            mBluetoothTileDialogDelegate.onDeviceItemUpdated(
+                dialog,
+                listOf(deviceItem),
+                showSeeAll = false,
+                showPairNewDevice = false
+            )
+
+            val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
+            val adapter = recyclerView?.adapter as BluetoothTileDialogDelegate.Adapter
+            assertThat(adapter.itemCount).isEqualTo(1)
+            assertThat(adapter.getItem(0).deviceName).isEqualTo(DEVICE_NAME)
+            assertThat(adapter.getItem(0).connectionSummary).isEqualTo(DEVICE_CONNECTION_SUMMARY)
+            assertThat(adapter.getItem(0).iconWithDescription).isEqualTo(icon)
+        }
+    }
+
+    @Test
+    fun testDeviceItemViewHolder_cachedDeviceNotBusy() {
+        deviceItem.isEnabled = true
+
+        val view =
+            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
+        val viewHolder =
+            mBluetoothTileDialogDelegate
+                .Adapter(bluetoothTileDialogCallback)
+                .DeviceItemViewHolder(view)
+        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
+        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
+
+        assertThat(container).isNotNull()
+        assertThat(container.isEnabled).isTrue()
+        assertThat(container.hasOnClickListeners()).isTrue()
+    }
+
+    @Test
+    fun testDeviceItemViewHolder_cachedDeviceBusy() {
+        deviceItem.isEnabled = false
+
+        val view =
+            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
+        val viewHolder =
+            BluetoothTileDialogDelegate(
+                    mContext,
+                    uiProperties,
+                    CONTENT_HEIGHT,
+                    ENABLED,
+                    bluetoothTileDialogCallback,
+                    {},
+                    dispatcher,
+                    fakeSystemClock,
+                    uiEventLogger,
+                    logger,
+                    sysuiDialogFactory,
+                    LayoutInflater.from(mContext)
+                )
+                .Adapter(bluetoothTileDialogCallback)
+                .DeviceItemViewHolder(view)
+        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
+        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
+
+        assertThat(container).isNotNull()
+        assertThat(container.isEnabled).isFalse()
+        assertThat(container.hasOnClickListeners()).isTrue()
+    }
+
+    @Test
+    fun testOnDeviceUpdated_hideSeeAll_showPairNew() {
+        testScope.runTest {
+            val dialog = mBluetoothTileDialogDelegate.createDialog()
+            dialog.show()
+            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
+            mBluetoothTileDialogDelegate.onDeviceItemUpdated(
+                dialog,
+                listOf(deviceItem),
+                showSeeAll = false,
+                showPairNewDevice = true
+            )
+
+            val seeAllButton = dialog.requireViewById<View>(R.id.see_all_button)
+            val pairNewButton = dialog.requireViewById<View>(R.id.pair_new_device_button)
+            val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
+            val adapter = recyclerView?.adapter as BluetoothTileDialogDelegate.Adapter
+            val scrollViewContent = dialog.requireViewById<View>(R.id.scroll_view)
+
+            assertThat(seeAllButton).isNotNull()
+            assertThat(seeAllButton.visibility).isEqualTo(GONE)
+            assertThat(pairNewButton).isNotNull()
+            assertThat(pairNewButton.visibility).isEqualTo(VISIBLE)
+            assertThat(adapter.itemCount).isEqualTo(1)
+            assertThat(scrollViewContent.layoutParams.height).isEqualTo(WRAP_CONTENT)
+        }
+    }
+
+    @Test
+    fun testShowDialog_cachedHeightLargerThanMinHeight_displayFromCachedHeight() {
+        testScope.runTest {
+            val cachedHeight = Int.MAX_VALUE
+            val dialog =
+                BluetoothTileDialogDelegate(
+                        mContext,
+                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
+                        cachedHeight,
+                        ENABLED,
+                        bluetoothTileDialogCallback,
+                        {},
+                        dispatcher,
+                        fakeSystemClock,
+                        uiEventLogger,
+                        logger,
+                        sysuiDialogFactory,
+                        LayoutInflater.from(mContext)
+                    )
+                    .createDialog()
+            dialog.show()
+            assertThat(dialog.requireViewById<View>(R.id.scroll_view).layoutParams.height)
+                .isEqualTo(cachedHeight)
+        }
+    }
+
+    @Test
+    fun testShowDialog_cachedHeightLessThanMinHeight_displayFromUiProperties() {
+        testScope.runTest {
+            val dialog =
+                BluetoothTileDialogDelegate(
+                        mContext,
+                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
+                        MATCH_PARENT,
+                        ENABLED,
+                        bluetoothTileDialogCallback,
+                        {},
+                        dispatcher,
+                        fakeSystemClock,
+                        uiEventLogger,
+                        logger,
+                        sysuiDialogFactory,
+                        LayoutInflater.from(mContext)
+                    )
+                    .createDialog()
+            dialog.show()
+            assertThat(dialog.requireViewById<View>(R.id.scroll_view).layoutParams.height)
+                .isGreaterThan(MATCH_PARENT)
+        }
+    }
+
+    @Test
+    fun testShowDialog_bluetoothEnabled_autoOnToggleGone() {
+        testScope.runTest {
+            val dialog =
+                BluetoothTileDialogDelegate(
+                        mContext,
+                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
+                        MATCH_PARENT,
+                        ENABLED,
+                        bluetoothTileDialogCallback,
+                        {},
+                        dispatcher,
+                        fakeSystemClock,
+                        uiEventLogger,
+                        logger,
+                        sysuiDialogFactory,
+                        LayoutInflater.from(mContext)
+                    )
+                    .createDialog()
+            dialog.show()
+            assertThat(
+                    dialog.requireViewById<View>(R.id.bluetooth_auto_on_toggle_layout).visibility
+                )
+                .isEqualTo(GONE)
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt
deleted file mode 100644
index 70b0417..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (C) 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 com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.graphics.drawable.Drawable
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.LayoutInflater
-import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
-import android.view.ViewGroup.LayoutParams.MATCH_PARENT
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.UiEventLogger
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.res.R
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.test.TestCoroutineScheduler
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-class BluetoothTileDialogTest : SysuiTestCase() {
-    companion object {
-        const val DEVICE_NAME = "device"
-        const val DEVICE_CONNECTION_SUMMARY = "active"
-        const val ENABLED = true
-        const val CONTENT_HEIGHT = WRAP_CONTENT
-    }
-
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-
-    @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice
-
-    @Mock private lateinit var bluetoothTileDialogCallback: BluetoothTileDialogCallback
-
-    @Mock private lateinit var drawable: Drawable
-
-    @Mock private lateinit var uiEventLogger: UiEventLogger
-
-    @Mock private lateinit var logger: BluetoothTileDialogLogger
-
-    private val uiProperties =
-        BluetoothTileDialogViewModel.UiProperties.build(
-            isBluetoothEnabled = ENABLED,
-            isAutoOnToggleFeatureAvailable = ENABLED
-        )
-
-    private val fakeSystemClock = FakeSystemClock()
-
-    private lateinit var scheduler: TestCoroutineScheduler
-    private lateinit var dispatcher: CoroutineDispatcher
-    private lateinit var testScope: TestScope
-    private lateinit var icon: Pair<Drawable, String>
-    private lateinit var bluetoothTileDialog: BluetoothTileDialog
-    private lateinit var deviceItem: DeviceItem
-
-    @Before
-    fun setUp() {
-        scheduler = TestCoroutineScheduler()
-        dispatcher = UnconfinedTestDispatcher(scheduler)
-        testScope = TestScope(dispatcher)
-        bluetoothTileDialog =
-            BluetoothTileDialog(
-                ENABLED,
-                uiProperties,
-                CONTENT_HEIGHT,
-                bluetoothTileDialogCallback,
-                dispatcher,
-                fakeSystemClock,
-                uiEventLogger,
-                logger,
-                mContext
-            )
-        icon = Pair(drawable, DEVICE_NAME)
-        deviceItem =
-            DeviceItem(
-                type = DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
-                cachedBluetoothDevice = cachedBluetoothDevice,
-                deviceName = DEVICE_NAME,
-                connectionSummary = DEVICE_CONNECTION_SUMMARY,
-                iconWithDescription = icon,
-                background = null
-            )
-        `when`(cachedBluetoothDevice.isBusy).thenReturn(false)
-    }
-
-    @Test
-    fun testShowDialog_createRecyclerViewWithAdapter() {
-        bluetoothTileDialog.show()
-
-        val recyclerView = bluetoothTileDialog.requireViewById<RecyclerView>(R.id.device_list)
-
-        assertThat(bluetoothTileDialog.isShowing).isTrue()
-        assertThat(recyclerView).isNotNull()
-        assertThat(recyclerView.visibility).isEqualTo(VISIBLE)
-        assertThat(recyclerView.adapter).isNotNull()
-        assertThat(recyclerView.layoutManager is LinearLayoutManager).isTrue()
-    }
-
-    @Test
-    fun testShowDialog_displayBluetoothDevice() {
-        testScope.runTest {
-            bluetoothTileDialog =
-                BluetoothTileDialog(
-                    ENABLED,
-                    uiProperties,
-                    CONTENT_HEIGHT,
-                    bluetoothTileDialogCallback,
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    mContext
-                )
-            bluetoothTileDialog.show()
-            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
-            bluetoothTileDialog.onDeviceItemUpdated(
-                listOf(deviceItem),
-                showSeeAll = false,
-                showPairNewDevice = false
-            )
-
-            val recyclerView = bluetoothTileDialog.requireViewById<RecyclerView>(R.id.device_list)
-            val adapter = recyclerView.adapter as BluetoothTileDialog.Adapter
-            assertThat(adapter.itemCount).isEqualTo(1)
-            assertThat(adapter.getItem(0).deviceName).isEqualTo(DEVICE_NAME)
-            assertThat(adapter.getItem(0).connectionSummary).isEqualTo(DEVICE_CONNECTION_SUMMARY)
-            assertThat(adapter.getItem(0).iconWithDescription).isEqualTo(icon)
-        }
-    }
-
-    @Test
-    fun testDeviceItemViewHolder_cachedDeviceNotBusy() {
-        deviceItem.isEnabled = true
-
-        val view =
-            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
-        val viewHolder =
-            BluetoothTileDialog(
-                    ENABLED,
-                    uiProperties,
-                    CONTENT_HEIGHT,
-                    bluetoothTileDialogCallback,
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    mContext
-                )
-                .Adapter(bluetoothTileDialogCallback)
-                .DeviceItemViewHolder(view)
-        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
-        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
-
-        assertThat(container).isNotNull()
-        assertThat(container.isEnabled).isTrue()
-        assertThat(container.hasOnClickListeners()).isTrue()
-    }
-
-    @Test
-    fun testDeviceItemViewHolder_cachedDeviceBusy() {
-        deviceItem.isEnabled = false
-
-        val view =
-            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
-        val viewHolder =
-            BluetoothTileDialog(
-                    ENABLED,
-                    uiProperties,
-                    CONTENT_HEIGHT,
-                    bluetoothTileDialogCallback,
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    mContext
-                )
-                .Adapter(bluetoothTileDialogCallback)
-                .DeviceItemViewHolder(view)
-        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
-        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
-
-        assertThat(container).isNotNull()
-        assertThat(container.isEnabled).isFalse()
-        assertThat(container.hasOnClickListeners()).isTrue()
-    }
-
-    @Test
-    fun testOnDeviceUpdated_hideSeeAll_showPairNew() {
-        testScope.runTest {
-            bluetoothTileDialog =
-                BluetoothTileDialog(
-                    ENABLED,
-                    uiProperties,
-                    CONTENT_HEIGHT,
-                    bluetoothTileDialogCallback,
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    mContext
-                )
-            bluetoothTileDialog.show()
-            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
-            bluetoothTileDialog.onDeviceItemUpdated(
-                listOf(deviceItem),
-                showSeeAll = false,
-                showPairNewDevice = true
-            )
-
-            val seeAllButton = bluetoothTileDialog.requireViewById<View>(R.id.see_all_button)
-            val pairNewButton =
-                bluetoothTileDialog.requireViewById<View>(R.id.pair_new_device_button)
-            val recyclerView = bluetoothTileDialog.requireViewById<RecyclerView>(R.id.device_list)
-            val adapter = recyclerView.adapter as BluetoothTileDialog.Adapter
-            val scrollViewContent = bluetoothTileDialog.requireViewById<View>(R.id.scroll_view)
-
-            assertThat(seeAllButton).isNotNull()
-            assertThat(seeAllButton.visibility).isEqualTo(GONE)
-            assertThat(pairNewButton).isNotNull()
-            assertThat(pairNewButton.visibility).isEqualTo(VISIBLE)
-            assertThat(adapter.itemCount).isEqualTo(1)
-            assertThat(scrollViewContent.layoutParams.height).isEqualTo(WRAP_CONTENT)
-        }
-    }
-
-    @Test
-    fun testShowDialog_cachedHeightLargerThanMinHeight_displayFromCachedHeight() {
-        testScope.runTest {
-            val cachedHeight = Int.MAX_VALUE
-            bluetoothTileDialog =
-                BluetoothTileDialog(
-                    ENABLED,
-                    uiProperties,
-                    cachedHeight,
-                    bluetoothTileDialogCallback,
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    mContext
-                )
-            bluetoothTileDialog.show()
-            assertThat(
-                    bluetoothTileDialog.requireViewById<View>(R.id.scroll_view).layoutParams.height
-                )
-                .isEqualTo(cachedHeight)
-        }
-    }
-
-    @Test
-    fun testShowDialog_cachedHeightLessThanMinHeight_displayFromUiProperties() {
-        testScope.runTest {
-            bluetoothTileDialog =
-                BluetoothTileDialog(
-                    ENABLED,
-                    uiProperties,
-                    MATCH_PARENT,
-                    bluetoothTileDialogCallback,
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    mContext
-                )
-            bluetoothTileDialog.show()
-            assertThat(
-                    bluetoothTileDialog.requireViewById<View>(R.id.scroll_view).layoutParams.height
-                )
-                .isGreaterThan(MATCH_PARENT)
-        }
-    }
-
-    @Test
-    fun testShowDialog_bluetoothEnabled_autoOnToggleGone() {
-        testScope.runTest {
-            bluetoothTileDialog =
-                BluetoothTileDialog(
-                    ENABLED,
-                    BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
-                    MATCH_PARENT,
-                    bluetoothTileDialogCallback,
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    mContext
-                )
-            bluetoothTileDialog.show()
-            assertThat(
-                    bluetoothTileDialog
-                        .requireViewById<View>(R.id.bluetooth_auto_on_toggle_layout)
-                        .visibility
-                )
-                .isEqualTo(GONE)
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
index cb9f4b4..39e2413 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.qs.tiles.dialog.bluetooth
 
-import android.content.SharedPreferences
 import android.content.pm.UserInfo
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
@@ -31,10 +30,14 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.kotlin.getMutableStateFlow
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.settings.FakeSettings
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -50,12 +53,12 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.anyBoolean
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
 import org.mockito.junit.MockitoJUnit
 import org.mockito.junit.MockitoRule
 
@@ -84,9 +87,15 @@
 
     @Mock private lateinit var uiEventLogger: UiEventLogger
 
-    @Mock private lateinit var logger: BluetoothTileDialogLogger
+    @Mock
+    private lateinit var mBluetoothTileDialogDelegateDelegateFactory:
+        BluetoothTileDialogDelegate.Factory
 
-    @Mock private lateinit var sharedPreferences: SharedPreferences
+    @Mock private lateinit var bluetoothTileDialogDelegate: BluetoothTileDialogDelegate
+
+    @Mock private lateinit var sysuiDialog: SystemUIDialog
+
+    private val sharedPreferences = FakeSharedPreferences()
 
     private lateinit var scheduler: TestCoroutineScheduler
     private lateinit var dispatcher: CoroutineDispatcher
@@ -123,20 +132,38 @@
                 ),
                 mDialogTransitionAnimator,
                 activityStarter,
-                fakeSystemClock,
                 uiEventLogger,
-                logger,
                 testScope.backgroundScope,
                 dispatcher,
                 dispatcher,
                 sharedPreferences,
+                mBluetoothTileDialogDelegateDelegateFactory
             )
-        `when`(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
-        `when`(bluetoothStateInteractor.bluetoothStateUpdate)
+        whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
+        whenever(bluetoothStateInteractor.bluetoothStateUpdate)
             .thenReturn(MutableStateFlow(null).asStateFlow())
-        `when`(deviceItemInteractor.deviceItemUpdateRequest)
+        whenever(deviceItemInteractor.deviceItemUpdateRequest)
             .thenReturn(MutableStateFlow(Unit).asStateFlow())
-        `when`(bluetoothStateInteractor.isBluetoothEnabled).thenReturn(true)
+        whenever(bluetoothStateInteractor.isBluetoothEnabled).thenReturn(true)
+        whenever(
+                mBluetoothTileDialogDelegateDelegateFactory.create(
+                    any(),
+                    any(),
+                    anyInt(),
+                    ArgumentMatchers.anyBoolean(),
+                    any(),
+                    any()
+                )
+            )
+            .thenReturn(bluetoothTileDialogDelegate)
+        whenever(bluetoothTileDialogDelegate.createDialog()).thenReturn(sysuiDialog)
+        whenever(bluetoothTileDialogDelegate.bluetoothStateToggle)
+            .thenReturn(getMutableStateFlow(false))
+        whenever(bluetoothTileDialogDelegate.deviceItemClick)
+            .thenReturn(getMutableStateFlow(deviceItem))
+        whenever(bluetoothTileDialogDelegate.contentHeight).thenReturn(getMutableStateFlow(0))
+        whenever(bluetoothTileDialogDelegate.bluetoothAutoOnToggle)
+            .thenReturn(getMutableStateFlow(false))
     }
 
     @Test
@@ -145,7 +172,6 @@
             bluetoothTileDialogViewModel.showDialog(context, null)
 
             verify(mDialogTransitionAnimator, never()).showFromView(any(), any(), any(), any())
-            verify(uiEventLogger).log(BluetoothTileDialogUiEvent.BLUETOOTH_TILE_DIALOG_SHOWN)
         }
     }
 
@@ -191,7 +217,7 @@
     @Test
     fun testStartSettingsActivity_activityLaunched_dialogDismissed() {
         testScope.runTest {
-            `when`(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice)
+            whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice)
             bluetoothTileDialogViewModel.showDialog(context, null)
 
             val clickedView = View(context)