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

Commit 7875db5f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix call to PackageManager exception" into udc-qpr-dev

parents b3ed3c63 00fe868a
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -51,12 +51,26 @@ class InstalledTilesComponentRepositoryImpl
@Inject
constructor(
    @Application private val applicationContext: Context,
    private val packageManager: PackageManager,
    @Background private val backgroundDispatcher: CoroutineDispatcher,
) : InstalledTilesComponentRepository {

    override fun getInstalledTilesComponents(userId: Int): Flow<Set<ComponentName>> =
        conflatedCallbackFlow {
    override fun getInstalledTilesComponents(userId: Int): Flow<Set<ComponentName>> {
        /*
         * In order to query [PackageManager] for different users, this implementation will call
         * [Context.createContextAsUser] and retrieve the [PackageManager] from that context.
         */
        val packageManager =
            if (applicationContext.userId == userId) {
                applicationContext.packageManager
            } else {
                applicationContext
                    .createContextAsUser(
                        UserHandle.of(userId),
                        /* flags */ 0,
                    )
                    .packageManager
            }
        return conflatedCallbackFlow {
                val receiver =
                    object : BroadcastReceiver() {
                        override fun onReceive(context: Context?, intent: Intent?) {
@@ -74,12 +88,13 @@ constructor(
                awaitClose { applicationContext.unregisterReceiver(receiver) }
            }
            .onStart { emit(Unit) }
            .map { reloadComponents(userId) }
            .map { reloadComponents(userId, packageManager) }
            .distinctUntilChanged()
            .flowOn(backgroundDispatcher)
    }

    @WorkerThread
    private fun reloadComponents(userId: Int): Set<ComponentName> {
    private fun reloadComponents(userId: Int, packageManager: PackageManager): Set<ComponentName> {
        return packageManager
            .queryIntentServicesAsUser(INTENT, FLAGS, userId)
            .mapNotNull { it.serviceInfo }
+7 −0
Original line number Diff line number Diff line
@@ -16,12 +16,19 @@

package com.android.systemui.util.kotlin

import android.annotation.UserHandleAware
import android.annotation.WorkerThread
import android.content.pm.ComponentInfo
import android.content.pm.PackageManager
import com.android.systemui.util.Assert

/**
 * Determines whether a component is actually enabled (not just its default value).
 *
 * @throws IllegalArgumentException if the component is not found
 */
@WorkerThread
@UserHandleAware
fun PackageManager.isComponentActuallyEnabled(componentInfo: ComponentInfo): Boolean {
    Assert.isNotMainThread()
    return when (getComponentEnabledSetting(componentInfo.componentName)) {
+50 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import com.android.systemui.util.mockito.argThat
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
@@ -75,6 +76,9 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
    fun setUp() {
        MockitoAnnotations.initMocks(this)

        whenever(context.createContextAsUser(any(), anyInt())).thenReturn(context)
        whenever(context.packageManager).thenReturn(packageManager)

        // Use the default value set in the ServiceInfo
        whenever(packageManager.getComponentEnabledSetting(any()))
            .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
@@ -86,7 +90,6 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
        underTest =
            InstalledTilesComponentRepositoryImpl(
                context,
                packageManager,
                testDispatcher,
            )
    }
@@ -224,6 +227,52 @@ class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
            assertThat(componentNames).isEmpty()
        }

    @Test
    fun packageOnlyInSecondaryUser_noException() =
        testScope.runTest {
            val userId = 10
            val secondaryUserContext: Context = mock()
            whenever(context.userId).thenReturn(0) // System context
            whenever(context.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
                .thenReturn(secondaryUserContext)

            val secondaryUserPackageManager: PackageManager = mock()
            whenever(secondaryUserContext.packageManager).thenReturn(secondaryUserPackageManager)

            // Use the default value set in the ServiceInfo
            whenever(secondaryUserPackageManager.getComponentEnabledSetting(any()))
                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
            // System User package manager throws exception if the component doesn't exist for that
            // user
            whenever(packageManager.getComponentEnabledSetting(TEST_COMPONENT))
                .thenThrow(IllegalArgumentException()) // The package is not in the system user

            val resolveInfo =
                ResolveInfo(TEST_COMPONENT, hasPermission = true, defaultEnabled = true)
            // Both package manager should return the same (because the query is for the secondary
            // user)
            whenever(
                    secondaryUserPackageManager.queryIntentServicesAsUser(
                        matchIntent(),
                        matchFlags(),
                        eq(userId)
                    )
                )
                .thenReturn(listOf(resolveInfo))
            whenever(
                    packageManager.queryIntentServicesAsUser(
                        matchIntent(),
                        matchFlags(),
                        eq(userId)
                    )
                )
                .thenReturn(listOf(resolveInfo))

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

            assertThat(componentNames).containsExactly(TEST_COMPONENT)
        }

    private fun getRegisteredReceiver(): BroadcastReceiver {
        verify(context)
            .registerReceiverAsUser(