Refresh the App Info Settings

When apk upgraded or downgraded.

And only close the page when the package is fully removed.

Bug: 314562958
Test: manual - on App Info Settings
Test: unit test
Change-Id: Ifdff714da99e31f9c5f237a0c3342de7a0797ec4
This commit is contained in:
Chaohui Wang
2023-12-03 18:00:51 +08:00
parent 0a32ca2bbc
commit de3fe3744f
5 changed files with 93 additions and 138 deletions

View File

@@ -23,7 +23,9 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Report import androidx.compose.material.icons.outlined.Report
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R import com.android.settings.R
import com.android.settingslib.RestrictedLockUtils import com.android.settingslib.RestrictedLockUtils
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
@@ -35,6 +37,9 @@ import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
import com.android.settingslib.spaprivileged.model.app.hasFlag import com.android.settingslib.spaprivileged.model.app.hasFlag
import com.android.settingslib.spaprivileged.model.app.isActiveAdmin import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
import com.android.settingslib.spaprivileged.model.app.userId import com.android.settingslib.spaprivileged.model.app.userId
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
class AppForceStopButton( class AppForceStopButton(
private val packageInfoPresenter: PackageInfoPresenter, private val packageInfoPresenter: PackageInfoPresenter,
@@ -47,9 +52,13 @@ class AppForceStopButton(
fun getActionButton(app: ApplicationInfo): ActionButton { fun getActionButton(app: ApplicationInfo): ActionButton {
val dialogPresenter = confirmDialogPresenter() val dialogPresenter = confirmDialogPresenter()
return ActionButton( return ActionButton(
text = context.getString(R.string.force_stop), text = stringResource(R.string.force_stop),
imageVector = Icons.Outlined.Report, imageVector = Icons.Outlined.Report,
enabled = isForceStopButtonEnable(app), enabled = remember(app) {
flow {
emit(isForceStopButtonEnable(app))
}.flowOn(Dispatchers.Default)
}.collectAsStateWithLifecycle(false).value,
) { onForceStopButtonClicked(app, dialogPresenter) } ) { onForceStopButtonClicked(app, dialogPresenter) }
} }

View File

@@ -32,10 +32,10 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavType import androidx.navigation.NavType
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.android.settings.flags.Flags
import com.android.settings.R import com.android.settings.R
import com.android.settings.applications.AppInfoBase import com.android.settings.applications.AppInfoBase
import com.android.settings.applications.appinfo.AppInfoDashboardFragment import com.android.settings.applications.appinfo.AppInfoDashboardFragment
import com.android.settings.flags.Flags
import com.android.settings.spa.SpaActivity.Companion.startSpaActivity import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
import com.android.settings.spa.app.appcompat.UserAspectRatioAppPreference import com.android.settings.spa.app.appcompat.UserAspectRatioAppPreference
import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
@@ -45,7 +45,6 @@ import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListPro
import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
import com.android.settings.spa.app.specialaccess.VoiceActivationAppsListProvider import com.android.settings.spa.app.specialaccess.VoiceActivationAppsListProvider
import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.LifecycleEffect
import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spa.widget.ui.Category
@@ -75,7 +74,7 @@ object AppInfoSettingsProvider : SettingsPageProvider {
PackageInfoPresenter(context, packageName, userId, coroutineScope) PackageInfoPresenter(context, packageName, userId, coroutineScope)
} }
AppInfoSettings(packageInfoPresenter) AppInfoSettings(packageInfoPresenter)
packageInfoPresenter.PackageRemoveDetector() packageInfoPresenter.PackageFullyRemovedEffect()
} }
@Composable @Composable
@@ -120,8 +119,7 @@ object AppInfoSettingsProvider : SettingsPageProvider {
@Composable @Composable
private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
LifecycleEffect(onStart = { packageInfoPresenter.reloadPackageInfo() }) val packageInfo = packageInfoPresenter.flow.collectAsStateWithLifecycle().value ?:return
val packageInfo = packageInfoPresenter.flow.collectAsStateWithLifecycle().value ?: return
val app = checkNotNull(packageInfo.applicationInfo) val app = checkNotNull(packageInfo.applicationInfo)
val featureFlags: FeatureFlags = FeatureFlagsImpl() val featureFlags: FeatureFlags = FeatureFlagsImpl()
RegularScaffold( RegularScaffold(
@@ -131,7 +129,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
AppInfoSettingsMoreOptions(packageInfoPresenter, app) AppInfoSettingsMoreOptions(packageInfoPresenter, app)
} }
) { ) {
val appInfoProvider = remember { AppInfoProvider(packageInfo) } val appInfoProvider = remember(packageInfo) { AppInfoProvider(packageInfo) }
appInfoProvider.AppInfo() appInfoProvider.AppInfo()

View File

@@ -28,7 +28,6 @@ import androidx.navigation.NavType
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.android.settings.R import com.android.settings.R
import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.LifecycleEffect
import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spaprivileged.model.app.toRoute import com.android.settingslib.spaprivileged.model.app.toRoute
import com.android.settingslib.spaprivileged.template.app.AppInfoProvider import com.android.settingslib.spaprivileged.template.app.AppInfoProvider
@@ -54,7 +53,7 @@ object CloneAppInfoSettingsProvider : SettingsPageProvider {
PackageInfoPresenter(context, packageName, userId, coroutineScope) PackageInfoPresenter(context, packageName, userId, coroutineScope)
} }
CloneAppInfoSettings(packageInfoPresenter) CloneAppInfoSettings(packageInfoPresenter)
packageInfoPresenter.PackageRemoveDetector() packageInfoPresenter.PackageFullyRemovedEffect()
} }
@Composable @Composable
@@ -70,7 +69,6 @@ object CloneAppInfoSettingsProvider : SettingsPageProvider {
@Composable @Composable
private fun CloneAppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { private fun CloneAppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
LifecycleEffect(onStart = { packageInfoPresenter.reloadPackageInfo() })
val packageInfo = packageInfoPresenter.flow.collectAsStateWithLifecycle().value ?: return val packageInfo = packageInfoPresenter.flow.collectAsStateWithLifecycle().value ?: return
RegularScaffold( RegularScaffold(
title = stringResource(R.string.application_info_label), title = stringResource(R.string.application_info_label),

View File

@@ -32,14 +32,20 @@ import com.android.settings.spa.app.startUninstallActivity
import com.android.settingslib.spa.framework.compose.LocalNavController import com.android.settingslib.spa.framework.compose.LocalNavController
import com.android.settingslib.spaprivileged.framework.common.activityManager import com.android.settingslib.spaprivileged.framework.common.activityManager
import com.android.settingslib.spaprivileged.framework.common.asUser import com.android.settingslib.spaprivileged.framework.common.asUser
import com.android.settingslib.spaprivileged.framework.common.broadcastReceiverAsUserFlow
import com.android.settingslib.spaprivileged.framework.compose.DisposableBroadcastReceiverAsUser import com.android.settingslib.spaprivileged.framework.compose.DisposableBroadcastReceiverAsUser
import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.model.app.PackageManagers import com.android.settingslib.spaprivileged.model.app.PackageManagers
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
private const val TAG = "PackageInfoPresenter" private const val TAG = "PackageInfoPresenter"
@@ -58,34 +64,33 @@ class PackageInfoPresenter(
private val userHandle = UserHandle.of(userId) private val userHandle = UserHandle.of(userId)
val userContext by lazy { context.asUser(userHandle) } val userContext by lazy { context.asUser(userHandle) }
val userPackageManager: PackageManager by lazy { userContext.packageManager } val userPackageManager: PackageManager by lazy { userContext.packageManager }
private val _flow: MutableStateFlow<PackageInfo?> = MutableStateFlow(null)
val flow: StateFlow<PackageInfo?> = _flow val flow: StateFlow<PackageInfo?> = merge(
flowOf(null), // kick an initial value
fun reloadPackageInfo() { context.broadcastReceiverAsUserFlow(
coroutineScope.launch(Dispatchers.IO) { intentFilter = IntentFilter().apply {
_flow.value = getPackageInfo() addAction(Intent.ACTION_PACKAGE_CHANGED)
} addAction(Intent.ACTION_PACKAGE_REPLACED)
} addAction(Intent.ACTION_PACKAGE_RESTARTED)
addDataScheme("package")
},
userHandle = userHandle,
),
).map { getPackageInfo() }
.stateIn(coroutineScope + Dispatchers.Default, SharingStarted.WhileSubscribed(), null)
/** /**
* Detects the package removed event. * Detects the package fully removed event, and close the current page.
*/ */
@Composable @Composable
fun PackageRemoveDetector() { fun PackageFullyRemovedEffect() {
val intentFilter = IntentFilter(Intent.ACTION_PACKAGE_REMOVED).apply { val intentFilter = IntentFilter(Intent.ACTION_PACKAGE_FULLY_REMOVED).apply {
addDataScheme("package") addDataScheme("package")
} }
val navController = LocalNavController.current val navController = LocalNavController.current
DisposableBroadcastReceiverAsUser(intentFilter, userHandle) { intent -> DisposableBroadcastReceiverAsUser(intentFilter, userHandle) { intent ->
if (packageName == intent.data?.schemeSpecificPart) { if (packageName == intent.data?.schemeSpecificPart) {
val packageInfo = flow.value navController.navigateBack()
if (packageInfo != null && packageInfo.applicationInfo?.isSystemApp == true) {
// System app still exists after uninstalling the updates, refresh the page.
reloadPackageInfo()
} else {
navController.navigateBack()
}
} }
} }
} }
@@ -97,7 +102,6 @@ class PackageInfoPresenter(
userPackageManager.setApplicationEnabledSetting( userPackageManager.setApplicationEnabledSetting(
packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0
) )
reloadPackageInfo()
} }
} }
@@ -108,7 +112,6 @@ class PackageInfoPresenter(
userPackageManager.setApplicationEnabledSetting( userPackageManager.setApplicationEnabledSetting(
packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0 packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0
) )
reloadPackageInfo()
} }
} }
@@ -123,7 +126,6 @@ class PackageInfoPresenter(
logAction(SettingsEnums.ACTION_SETTINGS_CLEAR_INSTANT_APP) logAction(SettingsEnums.ACTION_SETTINGS_CLEAR_INSTANT_APP)
coroutineScope.launch(Dispatchers.IO) { coroutineScope.launch(Dispatchers.IO) {
userPackageManager.deletePackageAsUser(packageName, null, 0, userId) userPackageManager.deletePackageAsUser(packageName, null, 0, userId)
reloadPackageInfo()
} }
} }
@@ -133,7 +135,6 @@ class PackageInfoPresenter(
coroutineScope.launch(Dispatchers.Default) { coroutineScope.launch(Dispatchers.Default) {
Log.d(TAG, "Stopping package $packageName") Log.d(TAG, "Stopping package $packageName")
context.activityManager.forceStopPackageAsUser(packageName, userId) context.activityManager.forceStopPackageAsUser(packageName, userId)
reloadPackageInfo()
} }
} }
@@ -141,7 +142,7 @@ class PackageInfoPresenter(
metricsFeatureProvider.action(context, category, packageName) metricsFeatureProvider.action(context, category, packageName)
} }
private fun getPackageInfo() = private fun getPackageInfo(): PackageInfo? =
packageManagers.getPackageInfoAsUser( packageManagers.getPackageInfoAsUser(
packageName = packageName, packageName = packageName,
flags = PackageManager.MATCH_ANY_USER.toLong() or flags = PackageManager.MATCH_ANY_USER.toLong() or

View File

@@ -20,8 +20,6 @@ import android.app.ActivityManager
import android.app.settings.SettingsEnums import android.app.settings.SettingsEnums
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.FakeFeatureFlagsImpl
import android.content.pm.Flags
import android.content.pm.PackageManager import android.content.pm.PackageManager
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -30,91 +28,79 @@ import com.android.settings.testutils.mockAsUser
import com.android.settingslib.spaprivileged.framework.common.activityManager import com.android.settingslib.spaprivileged.framework.common.activityManager
import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.runBlocking
import org.junit.Before import kotlinx.coroutines.test.TestScope
import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.kotlin.any
import org.mockito.Mock import org.mockito.kotlin.argumentCaptor
import org.mockito.Mockito.any import org.mockito.kotlin.doNothing
import org.mockito.Mockito.doNothing import org.mockito.kotlin.doReturn
import org.mockito.Mockito.verify import org.mockito.kotlin.mock
import org.mockito.Spy import org.mockito.kotlin.spy
import org.mockito.junit.MockitoJUnit import org.mockito.kotlin.verify
import org.mockito.junit.MockitoRule import org.mockito.kotlin.whenever
import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class PackageInfoPresenterTest { class PackageInfoPresenterTest {
@get:Rule
val mockito: MockitoRule = MockitoJUnit.rule()
@Spy private val mockPackageManager = mock<PackageManager>()
private val context: Context = ApplicationProvider.getApplicationContext()
@Mock private val mockActivityManager = mock<ActivityManager>()
private lateinit var packageManager: PackageManager
@Mock private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
private lateinit var activityManager: ActivityManager on { packageManager } doReturn mockPackageManager
on { activityManager } doReturn mockActivityManager
doNothing().whenever(mock).startActivityAsUser(any(), any())
mock.mockAsUser()
}
@Mock private val packageManagers = mock<IPackageManagers>()
private lateinit var packageManagers: IPackageManagers
private val fakeFeatureFactory = FakeFeatureFactory() private val fakeFeatureFactory = FakeFeatureFactory()
private val metricsFeatureProvider = fakeFeatureFactory.metricsFeatureProvider private val metricsFeatureProvider = fakeFeatureFactory.metricsFeatureProvider
@Before
fun setUp() {
context.mockAsUser()
whenever(context.packageManager).thenReturn(packageManager)
whenever(context.activityManager).thenReturn(activityManager)
}
@Test @Test
fun enable() = runTest { fun enable() = runBlocking {
coroutineScope { val packageInfoPresenter =
val packageInfoPresenter = PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, TestScope(), packageManagers)
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers)
packageInfoPresenter.enable() packageInfoPresenter.enable()
} delay(100)
verifyAction(SettingsEnums.ACTION_SETTINGS_ENABLE_APP) verifyAction(SettingsEnums.ACTION_SETTINGS_ENABLE_APP)
verify(packageManager).setApplicationEnabledSetting( verify(mockPackageManager).setApplicationEnabledSetting(
PACKAGE_NAME, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 PACKAGE_NAME, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0
) )
} }
@Test @Test
fun disable() = runTest { fun disable() = runBlocking {
coroutineScope { val packageInfoPresenter =
val packageInfoPresenter = PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, TestScope(), packageManagers)
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers)
packageInfoPresenter.disable() packageInfoPresenter.disable()
} delay(100)
verifyAction(SettingsEnums.ACTION_SETTINGS_DISABLE_APP) verifyAction(SettingsEnums.ACTION_SETTINGS_DISABLE_APP)
verify(packageManager).setApplicationEnabledSetting( verify(mockPackageManager).setApplicationEnabledSetting(
PACKAGE_NAME, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0 PACKAGE_NAME, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0
) )
} }
@Test @Test
fun startUninstallActivity() = runTest { fun startUninstallActivity() = runBlocking {
doNothing().`when`(context).startActivityAsUser(any(), any())
val packageInfoPresenter = val packageInfoPresenter =
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, TestScope(), packageManagers)
packageInfoPresenter.startUninstallActivity() packageInfoPresenter.startUninstallActivity()
verifyAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP) verifyAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP)
val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) val intent = argumentCaptor<Intent> {
verify(context).startActivityAsUser(intentCaptor.capture(), any()) verify(context).startActivityAsUser(capture(), any())
with(intentCaptor.value) { }.firstValue
with(intent) {
assertThat(action).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE) assertThat(action).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE)
assertThat(data?.schemeSpecificPart).isEqualTo(PACKAGE_NAME) assertThat(data?.schemeSpecificPart).isEqualTo(PACKAGE_NAME)
assertThat(getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, true)).isEqualTo(false) assertThat(getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, true)).isEqualTo(false)
@@ -122,76 +108,39 @@ class PackageInfoPresenterTest {
} }
@Test @Test
fun clearInstantApp() = runTest { fun clearInstantApp() = runBlocking {
coroutineScope { val packageInfoPresenter =
val packageInfoPresenter = PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, TestScope(), packageManagers)
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers)
packageInfoPresenter.clearInstantApp() packageInfoPresenter.clearInstantApp()
} delay(100)
verifyAction(SettingsEnums.ACTION_SETTINGS_CLEAR_INSTANT_APP) verifyAction(SettingsEnums.ACTION_SETTINGS_CLEAR_INSTANT_APP)
verify(packageManager).deletePackageAsUser(PACKAGE_NAME, null, 0, USER_ID) verify(mockPackageManager).deletePackageAsUser(PACKAGE_NAME, null, 0, USER_ID)
} }
@Test @Test
fun forceStop() = runTest { fun forceStop() = runBlocking {
coroutineScope { val packageInfoPresenter =
val packageInfoPresenter = PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, TestScope(), packageManagers)
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers)
packageInfoPresenter.forceStop() packageInfoPresenter.forceStop()
} delay(100)
verifyAction(SettingsEnums.ACTION_APP_FORCE_STOP) verifyAction(SettingsEnums.ACTION_APP_FORCE_STOP)
verify(activityManager).forceStopPackageAsUser(PACKAGE_NAME, USER_ID) verify(mockActivityManager).forceStopPackageAsUser(PACKAGE_NAME, USER_ID)
} }
@Test @Test
fun logAction() = runTest { fun logAction() = runBlocking {
val packageInfoPresenter = val packageInfoPresenter =
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, TestScope(), packageManagers)
packageInfoPresenter.logAction(123) packageInfoPresenter.logAction(123)
verifyAction(123) verifyAction(123)
} }
@Test
fun reloadPackageInfo_archivingDisabled() = runTest {
coroutineScope {
val fakeFeatureFlags = FakeFeatureFlagsImpl()
fakeFeatureFlags.setFlag(Flags.FLAG_ARCHIVING, false)
val packageInfoPresenter =
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers, fakeFeatureFlags)
packageInfoPresenter.reloadPackageInfo()
}
val flags = PackageManager.MATCH_ANY_USER.toLong() or
PackageManager.MATCH_DISABLED_COMPONENTS.toLong() or
PackageManager.GET_PERMISSIONS.toLong()
verify(packageManagers).getPackageInfoAsUser(PACKAGE_NAME, flags, USER_ID)
}
@Test
fun reloadPackageInfo_archivingEnabled() = runTest {
coroutineScope {
val fakeFeatureFlags = FakeFeatureFlagsImpl()
fakeFeatureFlags.setFlag(Flags.FLAG_ARCHIVING, true)
val packageInfoPresenter =
PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers, fakeFeatureFlags)
packageInfoPresenter.reloadPackageInfo()
}
val flags = PackageManager.MATCH_ANY_USER.toLong() or
PackageManager.MATCH_DISABLED_COMPONENTS.toLong() or
PackageManager.GET_PERMISSIONS.toLong() or
PackageManager.MATCH_ARCHIVED_PACKAGES
verify(packageManagers).getPackageInfoAsUser(PACKAGE_NAME, flags, USER_ID)
}
private fun verifyAction(category: Int) { private fun verifyAction(category: Int) {
verify(metricsFeatureProvider).action(context, category, PACKAGE_NAME) verify(metricsFeatureProvider).action(context, category, PACKAGE_NAME)
} }