Merge "Fix call to PackageManager exception" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7875db5f8f
@@ -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 }
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user