summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/bluetooth_device_item.xml4
-rw-r--r--packages/SystemUI/res/layout/bluetooth_tile_dialog.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt43
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt5
6 files changed, 99 insertions, 15 deletions
diff --git a/packages/SystemUI/res/layout/bluetooth_device_item.xml b/packages/SystemUI/res/layout/bluetooth_device_item.xml
index 4336ccc70c33..4535f67fa7f9 100644
--- a/packages/SystemUI/res/layout/bluetooth_device_item.xml
+++ b/packages/SystemUI/res/layout/bluetooth_device_item.xml
@@ -41,7 +41,7 @@
android:textDirection="locale"
android:textAlignment="gravity"
android:paddingStart="20dp"
- android:paddingTop="10dp"
+ android:paddingTop="15dp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintTop_toTopOf="parent"
@@ -56,7 +56,7 @@
android:id="@+id/bluetooth_device_summary"
style="@style/BluetoothTileDialog.DeviceSummary"
android:paddingStart="20dp"
- android:paddingBottom="10dp"
+ android:paddingBottom="15dp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="@+id/bluetooth_device_name"
diff --git a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
index 50241cdca8b5..0534c6ee466f 100644
--- a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
+++ b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
@@ -51,13 +51,14 @@
android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintBottom_toTopOf="@+id/scroll_view"
app:layout_constraintTop_toBottomOf="@id/bluetooth_tile_dialog_title" />
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginTop="21dp"
+ android:fillViewport="true"
app:layout_constrainedHeight="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -84,13 +85,13 @@
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@+id/bluetooth_toggle"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintBottom_toTopOf="@+id/device_list"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/bluetooth_toggle"
android:layout_width="wrap_content"
android:layout_height="48dp"
+ android:paddingTop="10dp"
android:gravity="start|center_vertical"
android:paddingEnd="40dp"
android:contentDescription="@string/turn_on_bluetooth"
@@ -100,14 +101,13 @@
android:track="@drawable/settingslib_track_selector"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bluetooth_toggle_title"
- app:layout_constraintBottom_toTopOf="@+id/device_list"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
+ android:layout_marginTop="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bluetooth_toggle"
@@ -146,6 +146,7 @@
android:background="@drawable/bluetooth_tile_dialog_bg_off"
android:layout_width="0dp"
android:layout_height="64dp"
+ android:layout_marginBottom="9dp"
android:contentDescription="@string/accessibility_bluetooth_device_settings_pair_new_device"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -177,7 +178,6 @@
android:maxLines="1"
android:text="@string/inline_done_button"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@id/pair_new_device_button"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
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/BluetoothTileDialog.kt
index db3cf0f70f69..1805eb182cb1 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/BluetoothTileDialog.kt
@@ -24,6 +24,7 @@ import android.view.View.AccessibilityDelegate
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.accessibility.AccessibilityNodeInfo
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import android.widget.ImageView
@@ -54,6 +55,7 @@ internal class BluetoothTileDialog
constructor(
private val bluetoothToggleInitialValue: Boolean,
private val subtitleResIdInitialValue: Int,
+ private val cachedContentHeight: Int,
private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
@Main private val mainDispatcher: CoroutineDispatcher,
private val systemClock: SystemClock,
@@ -72,6 +74,11 @@ constructor(
internal val deviceItemClick
get() = mutableDeviceItemClick.asSharedFlow()
+ private val mutableContentHeight: MutableSharedFlow<Int> =
+ MutableSharedFlow(extraBufferCapacity = 1)
+ internal val contentHeight
+ get() = mutableContentHeight.asSharedFlow()
+
private val deviceItemAdapter: Adapter = Adapter(bluetoothTileDialogCallback)
private var lastUiUpdateMs: Long = -1
@@ -84,6 +91,7 @@ constructor(
private lateinit var seeAllButton: View
private lateinit var pairNewDeviceButton: View
private lateinit var deviceListView: RecyclerView
+ private lateinit var scrollViewContent: View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -110,12 +118,23 @@ constructor(
pairNewDeviceButton.setOnClickListener {
bluetoothTileDialogCallback.onPairNewDeviceClicked(it)
}
+ requireViewById<View>(R.id.scroll_view).apply {
+ scrollViewContent = this
+ layoutParams.height = cachedContentHeight
+ }
}
override fun start() {
lastUiUpdateMs = systemClock.elapsedRealtime()
}
+ override fun dismiss() {
+ if (::scrollViewContent.isInitialized) {
+ mutableContentHeight.tryEmit(scrollViewContent.measuredHeight)
+ }
+ super.dismiss()
+ }
+
internal suspend fun onDeviceItemUpdated(
deviceItem: List<DeviceItem>,
showSeeAll: Boolean,
@@ -124,14 +143,16 @@ constructor(
withContext(mainDispatcher) {
val start = systemClock.elapsedRealtime()
val itemRow = deviceItem.size + showSeeAll.toInt() + showPairNewDevice.toInt()
- // Add a slight delay for smoother dialog height change
- if (itemRow != lastItemRow) {
+ // If not the first load, add a slight delay for smoother dialog height change
+ if (itemRow != lastItemRow && lastItemRow != -1) {
delay(MIN_HEIGHT_CHANGE_INTERVAL_MS - (start - lastUiUpdateMs))
}
if (isActive) {
deviceItemAdapter.refreshDeviceItemList(deviceItem) {
seeAllButton.visibility = if (showSeeAll) VISIBLE else GONE
pairNewDeviceButton.visibility = if (showPairNewDevice) VISIBLE else GONE
+ // Update the height after data is updated
+ scrollViewContent.layoutParams.height = WRAP_CONTENT
lastUiUpdateMs = systemClock.elapsedRealtime()
lastItemRow = itemRow
logger.logDeviceUiUpdate(lastUiUpdateMs - start)
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 5d5e747ba979..6d08f591690f 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
@@ -18,14 +18,18 @@ package com.android.systemui.qs.tiles.dialog.bluetooth
import android.content.Context
import android.content.Intent
+import android.content.SharedPreferences
import android.os.Bundle
import android.view.View
+import android.view.ViewGroup
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.UiEventLogger
+import com.android.systemui.Prefs
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+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
@@ -45,6 +49,7 @@ import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
/** ViewModel for Bluetooth Dialog after clicking on the Bluetooth QS tile. */
@SysUISingleton
@@ -60,6 +65,8 @@ constructor(
private val logger: BluetoothTileDialogLogger,
@Application private val coroutineScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ @Main private val sharedPreferences: SharedPreferences,
) : BluetoothTileDialogCallback {
private var job: Job? = null
@@ -145,14 +152,31 @@ constructor(
.onEach { deviceItemInteractor.updateDeviceItemOnClick(it) }
.launchIn(this)
+ dialog.contentHeight
+ .onEach {
+ withContext(backgroundDispatcher) {
+ sharedPreferences.edit().putInt(CONTENT_HEIGHT_PREF_KEY, it).apply()
+ }
+ }
+ .launchIn(this)
+
produce<Unit> { awaitClose { dialog.cancel() } }
}
}
- private fun createBluetoothTileDialog(context: Context): BluetoothTileDialog {
+ private suspend fun createBluetoothTileDialog(context: Context): BluetoothTileDialog {
+ val cachedContentHeight =
+ withContext(backgroundDispatcher) {
+ sharedPreferences.getInt(
+ CONTENT_HEIGHT_PREF_KEY,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
return BluetoothTileDialog(
bluetoothStateInteractor.isBluetoothEnabled,
getSubtitleResId(bluetoothStateInteractor.isBluetoothEnabled),
+ cachedContentHeight,
this@BluetoothTileDialogViewModel,
mainDispatcher,
systemClock,
@@ -205,6 +229,7 @@ constructor(
companion object {
private const val INTERACTION_JANK_TAG = "bluetooth_tile_dialog"
+ private const val CONTENT_HEIGHT_PREF_KEY = Prefs.Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT
private fun getSubtitleResId(isBluetoothEnabled: Boolean) =
if (isBluetoothEnabled) R.string.quick_settings_bluetooth_tile_subtitle
else R.string.bt_is_off
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
index 313ccb8a8717..154aa1cabb0c 100644
--- 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
@@ -23,6 +23,8 @@ 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
@@ -54,6 +56,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
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()
@@ -88,6 +91,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
BluetoothTileDialog(
ENABLED,
subtitleResId,
+ CONTENT_HEIGHT,
bluetoothTileDialogCallback,
dispatcher,
fakeSystemClock,
@@ -116,9 +120,9 @@ class BluetoothTileDialogTest : SysuiTestCase() {
assertThat(bluetoothTileDialog.isShowing).isTrue()
assertThat(recyclerView).isNotNull()
- assertThat(recyclerView?.visibility).isEqualTo(VISIBLE)
- assertThat(recyclerView?.adapter).isNotNull()
- assertThat(recyclerView?.layoutManager is LinearLayoutManager).isTrue()
+ assertThat(recyclerView.visibility).isEqualTo(VISIBLE)
+ assertThat(recyclerView.adapter).isNotNull()
+ assertThat(recyclerView.layoutManager is LinearLayoutManager).isTrue()
}
@Test
@@ -128,6 +132,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
BluetoothTileDialog(
ENABLED,
subtitleResId,
+ CONTENT_HEIGHT,
bluetoothTileDialogCallback,
dispatcher,
fakeSystemClock,
@@ -144,7 +149,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
)
val recyclerView = bluetoothTileDialog.requireViewById<RecyclerView>(R.id.device_list)
- val adapter = recyclerView?.adapter as BluetoothTileDialog.Adapter
+ 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)
@@ -162,6 +167,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
BluetoothTileDialog(
ENABLED,
subtitleResId,
+ CONTENT_HEIGHT,
bluetoothTileDialogCallback,
dispatcher,
fakeSystemClock,
@@ -189,6 +195,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
BluetoothTileDialog(
ENABLED,
subtitleResId,
+ CONTENT_HEIGHT,
bluetoothTileDialogCallback,
dispatcher,
fakeSystemClock,
@@ -213,6 +220,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
BluetoothTileDialog(
ENABLED,
subtitleResId,
+ CONTENT_HEIGHT,
bluetoothTileDialogCallback,
dispatcher,
fakeSystemClock,
@@ -232,13 +240,38 @@ class BluetoothTileDialogTest : SysuiTestCase() {
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 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_displayFromCachedHeight() {
+ testScope.runTest {
+ bluetoothTileDialog =
+ BluetoothTileDialog(
+ ENABLED,
+ subtitleResId,
+ MATCH_PARENT,
+ bluetoothTileDialogCallback,
+ dispatcher,
+ fakeSystemClock,
+ uiEventLogger,
+ logger,
+ mContext
+ )
+ bluetoothTileDialog.show()
+ assertThat(
+ bluetoothTileDialog.requireViewById<View>(R.id.scroll_view).layoutParams.height
+ )
+ .isEqualTo(MATCH_PARENT)
}
}
}
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 99993f2b3eff..33066d2092b8 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,6 +16,7 @@
package com.android.systemui.qs.tiles.dialog.bluetooth
+import android.content.SharedPreferences
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
@@ -78,6 +79,8 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() {
@Mock private lateinit var logger: BluetoothTileDialogLogger
+ @Mock private lateinit var sharedPreferences: SharedPreferences
+
private lateinit var scheduler: TestCoroutineScheduler
private lateinit var dispatcher: CoroutineDispatcher
private lateinit var testScope: TestScope
@@ -98,6 +101,8 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() {
logger,
testScope.backgroundScope,
dispatcher,
+ dispatcher,
+ sharedPreferences,
)
`when`(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
`when`(bluetoothStateInteractor.bluetoothStateUpdate)