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

Commit e6b3a7f1 authored by Behnam Heydarshahi's avatar Behnam Heydarshahi Committed by Android (Google) Code Review
Browse files

Merge "Cache installed tile component flow per user" into main

parents 9c539c7b bf020d37
Loading
Loading
Loading
Loading
+33 −2
Original line number Original line Diff line number Diff line
@@ -35,7 +35,6 @@ import com.android.systemui.common.data.repository.fakePackageChangeRepository
import com.android.systemui.common.data.repository.packageChangeRepository
import com.android.systemui.common.data.repository.packageChangeRepository
import com.android.systemui.common.data.shared.model.PackageChangeModel
import com.android.systemui.common.data.shared.model.PackageChangeModel
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.any
@@ -44,6 +43,8 @@ import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
@@ -52,6 +53,7 @@ import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.MockitoAnnotations


@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@TestableLooper.RunWithLooper
@@ -82,7 +84,7 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
        underTest =
        underTest =
            InstalledTilesComponentRepositoryImpl(
            InstalledTilesComponentRepositoryImpl(
                context,
                context,
                kosmos.testDispatcher,
                testScope.backgroundScope,
                kosmos.packageChangeRepository
                kosmos.packageChangeRepository
            )
            )
    }
    }
@@ -103,6 +105,7 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
                .thenReturn(listOf(resolveInfo))
                .thenReturn(listOf(resolveInfo))


            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            runCurrent()


            assertThat(componentNames).containsExactly(TEST_COMPONENT)
            assertThat(componentNames).containsExactly(TEST_COMPONENT)
        }
        }
@@ -115,6 +118,8 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
                ResolveInfo(TEST_COMPONENT, hasPermission = true, defaultEnabled = true)
                ResolveInfo(TEST_COMPONENT, hasPermission = true, defaultEnabled = true)


            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            runCurrent()

            assertThat(componentNames).isEmpty()
            assertThat(componentNames).isEmpty()


            whenever(
            whenever(
@@ -126,6 +131,7 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
                )
                )
                .thenReturn(listOf(resolveInfo))
                .thenReturn(listOf(resolveInfo))
            kosmos.fakePackageChangeRepository.notifyChange(PackageChangeModel.Empty)
            kosmos.fakePackageChangeRepository.notifyChange(PackageChangeModel.Empty)
            runCurrent()


            assertThat(componentNames).containsExactly(TEST_COMPONENT)
            assertThat(componentNames).containsExactly(TEST_COMPONENT)
        }
        }
@@ -146,6 +152,8 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
                .thenReturn(listOf(resolveInfo))
                .thenReturn(listOf(resolveInfo))


            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            runCurrent()

            assertThat(componentNames).isEmpty()
            assertThat(componentNames).isEmpty()
        }
        }


@@ -165,6 +173,8 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
                .thenReturn(listOf(resolveInfo))
                .thenReturn(listOf(resolveInfo))


            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            runCurrent()

            assertThat(componentNames).isEmpty()
            assertThat(componentNames).isEmpty()
        }
        }


@@ -210,10 +220,31 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
                .thenReturn(listOf(resolveInfo))
                .thenReturn(listOf(resolveInfo))


            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
            runCurrent()


            assertThat(componentNames).containsExactly(TEST_COMPONENT)
            assertThat(componentNames).containsExactly(TEST_COMPONENT)
        }
        }


    @Test
    fun loadComponentsForSameUserTwice_returnsSameFlow() =
        testScope.runTest {
            val flowForUser1 = underTest.getInstalledTilesComponents(1)
            val flowForUser1TheSecondTime = underTest.getInstalledTilesComponents(1)
            runCurrent()

            assertThat(flowForUser1TheSecondTime).isEqualTo(flowForUser1)
        }

    @Test
    fun loadComponentsForDifferentUsers_returnsDifferentFlow() =
        testScope.runTest {
            val flowForUser1 = underTest.getInstalledTilesComponents(1)
            val flowForUser2 = underTest.getInstalledTilesComponents(2)
            runCurrent()

            assertThat(flowForUser2).isNotEqualTo(flowForUser1)
        }

    companion object {
    companion object {
        private val INTENT = Intent(TileService.ACTION_QS_TILE)
        private val INTENT = Intent(TileService.ACTION_QS_TILE)
        private val FLAGS =
        private val FLAGS =
+33 −25
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.pm.PackageManager
import android.content.pm.PackageManager.ResolveInfoFlags
import android.content.pm.PackageManager.ResolveInfoFlags
import android.os.UserHandle
import android.os.UserHandle
import android.service.quicksettings.TileService
import android.service.quicksettings.TileService
import androidx.annotation.GuardedBy
import com.android.systemui.common.data.repository.PackageChangeRepository
import com.android.systemui.common.data.repository.PackageChangeRepository
import com.android.systemui.common.data.shared.model.PackageChangeModel
import com.android.systemui.common.data.shared.model.PackageChangeModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
@@ -32,12 +33,13 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.util.kotlin.isComponentActuallyEnabled
import com.android.systemui.util.kotlin.isComponentActuallyEnabled
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn


interface InstalledTilesComponentRepository {
interface InstalledTilesComponentRepository {


@@ -49,14 +51,19 @@ class InstalledTilesComponentRepositoryImpl
@Inject
@Inject
constructor(
constructor(
    @Application private val applicationContext: Context,
    @Application private val applicationContext: Context,
    @Background private val backgroundDispatcher: CoroutineDispatcher,
    @Background private val backgroundScope: CoroutineScope,
    private val packageChangeRepository: PackageChangeRepository
    private val packageChangeRepository: PackageChangeRepository
) : InstalledTilesComponentRepository {
) : InstalledTilesComponentRepository {


    override fun getInstalledTilesComponents(userId: Int): Flow<Set<ComponentName>> {
    @GuardedBy("userMap") private val userMap = mutableMapOf<Int, Flow<Set<ComponentName>>>()

    override fun getInstalledTilesComponents(userId: Int): Flow<Set<ComponentName>> =
        synchronized(userMap) {
            userMap.getOrPut(userId) {
                /*
                /*
         * In order to query [PackageManager] for different users, this implementation will call
                 * In order to query [PackageManager] for different users, this implementation will
         * [Context.createContextAsUser] and retrieve the [PackageManager] from that context.
                 * call [Context.createContextAsUser] and retrieve the [PackageManager] from that
                 * context.
                 */
                 */
                val packageManager =
                val packageManager =
                    if (applicationContext.userId == userId) {
                    if (applicationContext.userId == userId) {
@@ -69,12 +76,13 @@ constructor(
                            )
                            )
                            .packageManager
                            .packageManager
                    }
                    }
        return packageChangeRepository
                packageChangeRepository
                    .packageChanged(UserHandle.of(userId))
                    .packageChanged(UserHandle.of(userId))
                    .onStart { emit(PackageChangeModel.Empty) }
                    .onStart { emit(PackageChangeModel.Empty) }
                    .map { reloadComponents(userId, packageManager) }
                    .map { reloadComponents(userId, packageManager) }
                    .distinctUntilChanged()
                    .distinctUntilChanged()
            .flowOn(backgroundDispatcher)
                    .shareIn(backgroundScope, SharingStarted.WhileSubscribed(), replay = 1)
            }
        }
        }


    @WorkerThread
    @WorkerThread