Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3da365b1 authored by Chelsea Hao's avatar Chelsea Hao Committed by Android (Google) Code Review
Browse files

Merge "Apply a min duration limit for smoother animation." into main

parents 718e4628 5562f8ae
Loading
Loading
Loading
Loading
+36 −6
Original line number Original line Diff line number Diff line
@@ -32,13 +32,18 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView
import com.android.internal.logging.UiEventLogger
import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.util.time.SystemClock
import com.android.systemui.util.time.SystemClock
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext


/** Dialog for showing active, connected and saved bluetooth devices. */
/** Dialog for showing active, connected and saved bluetooth devices. */
@SysUISingleton
@SysUISingleton
@@ -47,6 +52,7 @@ constructor(
    private val bluetoothToggleInitialValue: Boolean,
    private val bluetoothToggleInitialValue: Boolean,
    private val subtitleResIdInitialValue: Int,
    private val subtitleResIdInitialValue: Int,
    private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
    private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
    @Main private val mainDispatcher: CoroutineDispatcher,
    private val systemClock: SystemClock,
    private val systemClock: SystemClock,
    private val uiEventLogger: UiEventLogger,
    private val uiEventLogger: UiEventLogger,
    private val logger: BluetoothTileDialogLogger,
    private val logger: BluetoothTileDialogLogger,
@@ -65,6 +71,10 @@ constructor(


    private val deviceItemAdapter: Adapter = Adapter(bluetoothTileDialogCallback)
    private val deviceItemAdapter: Adapter = Adapter(bluetoothTileDialogCallback)


    private var lastUiUpdateMs: Long = -1

    private var lastItemRow: Int = -1

    private lateinit var toggleView: Switch
    private lateinit var toggleView: Switch
    private lateinit var subtitleTextView: TextView
    private lateinit var subtitleTextView: TextView
    private lateinit var doneButton: View
    private lateinit var doneButton: View
@@ -103,16 +113,31 @@ constructor(
        }
        }
    }
    }


    internal fun onDeviceItemUpdated(
    override fun start() {
        lastUiUpdateMs = systemClock.elapsedRealtime()
    }

    internal suspend fun onDeviceItemUpdated(
        deviceItem: List<DeviceItem>,
        deviceItem: List<DeviceItem>,
        showSeeAll: Boolean,
        showSeeAll: Boolean,
        showPairNewDevice: Boolean
        showPairNewDevice: Boolean
    ) {
    ) {
        withContext(mainDispatcher) {
            val start = systemClock.elapsedRealtime()
            val start = systemClock.elapsedRealtime()
            val itemRow = deviceItem.size + showSeeAll.toInt() + showPairNewDevice.toInt()
            // Add a slight delay for smoother dialog height change
            if (itemRow != lastItemRow) {
                delay(MIN_HEIGHT_CHANGE_INTERVAL_MS - (start - lastUiUpdateMs))
            }
            if (isActive) {
                deviceItemAdapter.refreshDeviceItemList(deviceItem) {
                deviceItemAdapter.refreshDeviceItemList(deviceItem) {
                    seeAllViewGroup.visibility = if (showSeeAll) VISIBLE else GONE
                    seeAllViewGroup.visibility = if (showSeeAll) VISIBLE else GONE
                    pairNewDeviceViewGroup.visibility = if (showPairNewDevice) VISIBLE else GONE
                    pairNewDeviceViewGroup.visibility = if (showPairNewDevice) VISIBLE else GONE
            logger.logDeviceUiUpdate(systemClock.elapsedRealtime() - start)
                    lastUiUpdateMs = systemClock.elapsedRealtime()
                    lastItemRow = itemRow
                    logger.logDeviceUiUpdate(lastUiUpdateMs - start)
                }
            }
        }
        }
    }
    }


@@ -230,6 +255,7 @@ constructor(
    }
    }


    internal companion object {
    internal companion object {
        const val MIN_HEIGHT_CHANGE_INTERVAL_MS = 800L
        const val MAX_DEVICE_ITEM_ENTRY = 3
        const val MAX_DEVICE_ITEM_ENTRY = 3
        const val ACTION_BLUETOOTH_DEVICE_DETAILS =
        const val ACTION_BLUETOOTH_DEVICE_DETAILS =
            "com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS"
            "com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS"
@@ -238,5 +264,9 @@ constructor(
        const val ACTION_PAIR_NEW_DEVICE = "android.settings.BLUETOOTH_PAIRING_SETTINGS"
        const val ACTION_PAIR_NEW_DEVICE = "android.settings.BLUETOOTH_PAIRING_SETTINGS"
        const val DISABLED_ALPHA = 0.3f
        const val DISABLED_ALPHA = 0.3f
        const val ENABLED_ALPHA = 1f
        const val ENABLED_ALPHA = 1f

        private fun Boolean.toInt(): Int {
            return if (this) 1 else 0
        }
    }
    }
}
}
+11 −9
Original line number Original line Diff line number Diff line
@@ -40,7 +40,6 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onEach
@@ -76,6 +75,7 @@ constructor(
        dismissDialog()
        dismissDialog()


        var updateDeviceItemJob: Job? = null
        var updateDeviceItemJob: Job? = null
        var updateDialogUiJob: Job? = null


        job =
        job =
            coroutineScope.launch(mainDispatcher) {
            coroutineScope.launch(mainDispatcher) {
@@ -93,10 +93,9 @@ constructor(
                    )
                    )
                }
                }
                    ?: dialog!!.show()
                    ?: dialog!!.show()

                updateDeviceItemJob?.cancel()
                updateDeviceItemJob?.cancel()
                updateDeviceItemJob = launch {
                updateDeviceItemJob = launch {
                    // Add a slight delay for smoother dialog bounds change
                    delay(FIRST_LOAD_DELAY_MS)
                    deviceItemInteractor.updateDeviceItems(context, DeviceFetchTrigger.FIRST_LOAD)
                    deviceItemInteractor.updateDeviceItems(context, DeviceFetchTrigger.FIRST_LOAD)
                }
                }


@@ -128,12 +127,15 @@ constructor(


                deviceItemInteractor.deviceItemUpdate
                deviceItemInteractor.deviceItemUpdate
                    .onEach {
                    .onEach {
                        dialog!!.onDeviceItemUpdated(
                        updateDialogUiJob?.cancel()
                        updateDialogUiJob = launch {
                            dialog?.onDeviceItemUpdated(
                                it.take(MAX_DEVICE_ITEM_ENTRY),
                                it.take(MAX_DEVICE_ITEM_ENTRY),
                                showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY,
                                showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY,
                                showPairNewDevice = bluetoothStateInteractor.isBluetoothEnabled
                                showPairNewDevice = bluetoothStateInteractor.isBluetoothEnabled
                            )
                            )
                        }
                        }
                    }
                    .launchIn(this)
                    .launchIn(this)


                dialog!!
                dialog!!
@@ -153,6 +155,7 @@ constructor(
                bluetoothStateInteractor.isBluetoothEnabled,
                bluetoothStateInteractor.isBluetoothEnabled,
                getSubtitleResId(bluetoothStateInteractor.isBluetoothEnabled),
                getSubtitleResId(bluetoothStateInteractor.isBluetoothEnabled),
                this@BluetoothTileDialogViewModel,
                this@BluetoothTileDialogViewModel,
                mainDispatcher,
                systemClock,
                systemClock,
                uiEventLogger,
                uiEventLogger,
                logger,
                logger,
@@ -205,7 +208,6 @@ constructor(


    companion object {
    companion object {
        private const val INTERACTION_JANK_TAG = "bluetooth_tile_dialog"
        private const val INTERACTION_JANK_TAG = "bluetooth_tile_dialog"
        private const val FIRST_LOAD_DELAY_MS = 500L
        private fun getSubtitleResId(isBluetoothEnabled: Boolean) =
        private fun getSubtitleResId(isBluetoothEnabled: Boolean) =
            if (isBluetoothEnabled) R.string.quick_settings_bluetooth_tile_subtitle
            if (isBluetoothEnabled) R.string.quick_settings_bluetooth_tile_subtitle
            else R.string.bt_is_off
            else R.string.bt_is_off
+69 −47
Original line number Original line Diff line number Diff line
@@ -32,6 +32,11 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.res.R
import com.android.systemui.res.R
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
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.Before
import org.junit.Rule
import org.junit.Rule
import org.junit.Test
import org.junit.Test
@@ -67,17 +72,24 @@ class BluetoothTileDialogTest : SysuiTestCase() {


    private val fakeSystemClock = FakeSystemClock()
    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 icon: Pair<Drawable, String>
    private lateinit var bluetoothTileDialog: BluetoothTileDialog
    private lateinit var bluetoothTileDialog: BluetoothTileDialog
    private lateinit var deviceItem: DeviceItem
    private lateinit var deviceItem: DeviceItem


    @Before
    @Before
    fun setUp() {
    fun setUp() {
        scheduler = TestCoroutineScheduler()
        dispatcher = UnconfinedTestDispatcher(scheduler)
        testScope = TestScope(dispatcher)
        bluetoothTileDialog =
        bluetoothTileDialog =
            BluetoothTileDialog(
            BluetoothTileDialog(
                ENABLED,
                ENABLED,
                subtitleResId,
                subtitleResId,
                bluetoothTileDialogCallback,
                bluetoothTileDialogCallback,
                dispatcher,
                fakeSystemClock,
                fakeSystemClock,
                uiEventLogger,
                uiEventLogger,
                logger,
                logger,
@@ -111,17 +123,20 @@ class BluetoothTileDialogTest : SysuiTestCase() {


    @Test
    @Test
    fun testShowDialog_displayBluetoothDevice() {
    fun testShowDialog_displayBluetoothDevice() {
        testScope.runTest {
            bluetoothTileDialog =
            bluetoothTileDialog =
                BluetoothTileDialog(
                BluetoothTileDialog(
                    ENABLED,
                    ENABLED,
                    subtitleResId,
                    subtitleResId,
                    bluetoothTileDialogCallback,
                    bluetoothTileDialogCallback,
                    dispatcher,
                    fakeSystemClock,
                    fakeSystemClock,
                    uiEventLogger,
                    uiEventLogger,
                    logger,
                    logger,
                    mContext
                    mContext
                )
                )
            bluetoothTileDialog.show()
            bluetoothTileDialog.show()
            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
            bluetoothTileDialog.onDeviceItemUpdated(
            bluetoothTileDialog.onDeviceItemUpdated(
                listOf(deviceItem),
                listOf(deviceItem),
                showSeeAll = false,
                showSeeAll = false,
@@ -135,6 +150,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
            assertThat(adapter.getItem(0).connectionSummary).isEqualTo(DEVICE_CONNECTION_SUMMARY)
            assertThat(adapter.getItem(0).connectionSummary).isEqualTo(DEVICE_CONNECTION_SUMMARY)
            assertThat(adapter.getItem(0).iconWithDescription).isEqualTo(icon)
            assertThat(adapter.getItem(0).iconWithDescription).isEqualTo(icon)
        }
        }
    }


    @Test
    @Test
    fun testDeviceItemViewHolder_cachedDeviceNotBusy() {
    fun testDeviceItemViewHolder_cachedDeviceNotBusy() {
@@ -147,6 +163,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
                    ENABLED,
                    ENABLED,
                    subtitleResId,
                    subtitleResId,
                    bluetoothTileDialogCallback,
                    bluetoothTileDialogCallback,
                    dispatcher,
                    fakeSystemClock,
                    fakeSystemClock,
                    uiEventLogger,
                    uiEventLogger,
                    logger,
                    logger,
@@ -173,6 +190,7 @@ class BluetoothTileDialogTest : SysuiTestCase() {
                    ENABLED,
                    ENABLED,
                    subtitleResId,
                    subtitleResId,
                    bluetoothTileDialogCallback,
                    bluetoothTileDialogCallback,
                    dispatcher,
                    fakeSystemClock,
                    fakeSystemClock,
                    uiEventLogger,
                    uiEventLogger,
                    logger,
                    logger,
@@ -190,17 +208,20 @@ class BluetoothTileDialogTest : SysuiTestCase() {


    @Test
    @Test
    fun testOnDeviceUpdated_hideSeeAll_showPairNew() {
    fun testOnDeviceUpdated_hideSeeAll_showPairNew() {
        testScope.runTest {
            bluetoothTileDialog =
            bluetoothTileDialog =
                BluetoothTileDialog(
                BluetoothTileDialog(
                    ENABLED,
                    ENABLED,
                    subtitleResId,
                    subtitleResId,
                    bluetoothTileDialogCallback,
                    bluetoothTileDialogCallback,
                    dispatcher,
                    fakeSystemClock,
                    fakeSystemClock,
                    uiEventLogger,
                    uiEventLogger,
                    logger,
                    logger,
                    mContext
                    mContext
                )
                )
            bluetoothTileDialog.show()
            bluetoothTileDialog.show()
            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
            bluetoothTileDialog.onDeviceItemUpdated(
            bluetoothTileDialog.onDeviceItemUpdated(
                listOf(deviceItem),
                listOf(deviceItem),
                showSeeAll = false,
                showSeeAll = false,
@@ -220,3 +241,4 @@ class BluetoothTileDialogTest : SysuiTestCase() {
            assertThat(adapter.itemCount).isEqualTo(1)
            assertThat(adapter.itemCount).isEqualTo(1)
        }
        }
    }
    }
}