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

This commit is contained in:
TreeHugger Robot
2023-06-28 21:22:39 +00:00
committed by Android (Google) Code Review
3 changed files with 77 additions and 6 deletions

View File

@@ -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 }

View File

@@ -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)) {

View File

@@ -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(