From 91f7ae3dc0fd224830210cab2a730899da2fbe5d Mon Sep 17 00:00:00 2001 From: Zaiyue Xue Date: Mon, 16 Jan 2023 16:49:21 +0800 Subject: [PATCH] Fix b/265632782: Battery usage app list changed when entering the app details page and back This only happens on the first time the Settings package is installed. Discussed with Chaohui, the old showSystemApp() logic in Settings->Apps has some issues. This cl updates the logic to the new logic Chaohui provided. Bug: 265632782 Fix: 265632782 Test: manual Change-Id: Iff5838f0299aed1b0ba2164b97e7fbdeefcadbee --- .../model/app/AppListRepository.kt | 36 +++++++++++- .../model/app/AppListRepositoryTest.kt | 55 +++++++++++++------ .../model/app/AppListViewModelTest.kt | 2 + 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt index cbb4fbe32713b..ce0c5511c3d0e 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt @@ -26,6 +26,7 @@ import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.runBlocking /** * The config used to load the App List. @@ -47,8 +48,21 @@ internal interface AppListRepository { userIdFlow: Flow, showSystemFlow: Flow, ): Flow<(app: ApplicationInfo) -> Boolean> + + /** Gets the system app package names. */ + fun getSystemPackageNamesBlocking(config: AppListConfig): Set } +/** + * Util for app list repository. + */ +object AppListRepositoryUtil { + /** Gets the system app package names. */ + @JvmStatic + fun getSystemPackageNames(context: Context, config: AppListConfig): Set { + return AppListRepositoryImpl(context).getSystemPackageNamesBlocking(config) + } +} internal class AppListRepositoryImpl(private val context: Context) : AppListRepository { private val packageManager = context.packageManager @@ -83,15 +97,26 @@ internal class AppListRepositoryImpl(private val context: Context) : AppListRepo ): Flow<(app: ApplicationInfo) -> Boolean> = userIdFlow.combine(showSystemFlow, ::showSystemPredicate) + override fun getSystemPackageNamesBlocking(config: AppListConfig) = runBlocking { + getSystemPackageNames(config) + } + + private suspend fun getSystemPackageNames(config: AppListConfig): Set = + coroutineScope { + val loadAppsDeferred = async { loadApps(config) } + val homeOrLauncherPackages = loadHomeOrLauncherPackages(config.userId) + val showSystemPredicate = + { app: ApplicationInfo -> isSystemApp(app, homeOrLauncherPackages) } + loadAppsDeferred.await().filter(showSystemPredicate).map { it.packageName }.toSet() + } + private suspend fun showSystemPredicate( userId: Int, showSystem: Boolean, ): (app: ApplicationInfo) -> Boolean { if (showSystem) return { true } val homeOrLauncherPackages = loadHomeOrLauncherPackages(userId) - return { app -> - app.isUpdatedSystemApp || !app.isSystemApp || app.packageName in homeOrLauncherPackages - } + return { app -> !isSystemApp(app, homeOrLauncherPackages) } } private suspend fun loadHomeOrLauncherPackages(userId: Int): Set { @@ -117,6 +142,11 @@ internal class AppListRepositoryImpl(private val context: Context) : AppListRepo } } + private fun isSystemApp(app: ApplicationInfo, homeOrLauncherPackages: Set): Boolean { + return !app.isUpdatedSystemApp && app.isSystemApp && + !(app.packageName in homeOrLauncherPackages) + } + companion object { private fun ApplicationInfo.isInAppList( showInstantApps: Boolean, diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt index 2d8f0098480cf..b0ea40a49a0ee 100644 --- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt @@ -180,9 +180,7 @@ class AppListRepositoryTest { @Test fun showSystemPredicate_showSystem() = runTest { - val app = ApplicationInfo().apply { - flags = ApplicationInfo.FLAG_SYSTEM - } + val app = SYSTEM_APP val showSystemPredicate = getShowSystemPredicate(showSystem = true) @@ -191,9 +189,7 @@ class AppListRepositoryTest { @Test fun showSystemPredicate_notShowSystemAndIsSystemApp() = runTest { - val app = ApplicationInfo().apply { - flags = ApplicationInfo.FLAG_SYSTEM - } + val app = SYSTEM_APP val showSystemPredicate = getShowSystemPredicate(showSystem = false) @@ -202,9 +198,7 @@ class AppListRepositoryTest { @Test fun showSystemPredicate_isUpdatedSystemApp() = runTest { - val app = ApplicationInfo().apply { - flags = ApplicationInfo.FLAG_SYSTEM or ApplicationInfo.FLAG_UPDATED_SYSTEM_APP - } + val app = UPDATED_SYSTEM_APP val showSystemPredicate = getShowSystemPredicate(showSystem = false) @@ -213,10 +207,8 @@ class AppListRepositoryTest { @Test fun showSystemPredicate_isHome() = runTest { - val app = ApplicationInfo().apply { - flags = ApplicationInfo.FLAG_SYSTEM - packageName = "home.app" - } + val app = HOME_APP + whenever(packageManager.getHomeActivities(any())).thenAnswer { @Suppress("UNCHECKED_CAST") val resolveInfos = it.arguments[0] as MutableList @@ -231,10 +223,8 @@ class AppListRepositoryTest { @Test fun showSystemPredicate_appInLauncher() = runTest { - val app = ApplicationInfo().apply { - flags = ApplicationInfo.FLAG_SYSTEM - packageName = "app.in.launcher" - } + val app = IN_LAUMCHER_APP + whenever( packageManager.queryIntentActivitiesAsUser(any(), any(), eq(USER_ID)) ).thenReturn(listOf(resolveInfoOf(packageName = app.packageName))) @@ -244,6 +234,17 @@ class AppListRepositoryTest { assertThat(showSystemPredicate(app)).isTrue() } + @Test + fun getSystemPackageNames_returnExpectedValues() = runTest { + mockInstalledApplications(listOf( + NORMAL_APP, INSTANT_APP, SYSTEM_APP, UPDATED_SYSTEM_APP, HOME_APP, IN_LAUMCHER_APP)) + val appListConfig = AppListConfig(userId = USER_ID, showInstantApps = false) + + val systemPackageNames = AppListRepositoryUtil.getSystemPackageNames(context, appListConfig) + + assertThat(systemPackageNames).containsExactly("system.app", "home.app", "app.in.launcher") + } + private suspend fun getShowSystemPredicate(showSystem: Boolean) = repository.showSystemPredicate( userIdFlow = flowOf(USER_ID), @@ -264,6 +265,26 @@ class AppListRepositoryTest { privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT } + val SYSTEM_APP = ApplicationInfo().apply { + packageName = "system.app" + flags = ApplicationInfo.FLAG_SYSTEM + } + + val UPDATED_SYSTEM_APP = ApplicationInfo().apply { + packageName = "updated.system.app" + flags = ApplicationInfo.FLAG_SYSTEM or ApplicationInfo.FLAG_UPDATED_SYSTEM_APP + } + + val HOME_APP = ApplicationInfo().apply { + packageName = "home.app" + flags = ApplicationInfo.FLAG_SYSTEM + } + + val IN_LAUMCHER_APP = ApplicationInfo().apply { + packageName = "app.in.launcher" + flags = ApplicationInfo.FLAG_SYSTEM + } + fun resolveInfoOf(packageName: String) = ResolveInfo().apply { activityInfo = ActivityInfo().apply { this.packageName = packageName diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt index f51448744c56a..7151439c2a2ff 100644 --- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt @@ -90,6 +90,8 @@ class AppListViewModelTest { userIdFlow: Flow, showSystemFlow: Flow, ): Flow<(app: ApplicationInfo) -> Boolean> = flowOf { true } + + override fun getSystemPackageNamesBlocking(config: AppListConfig): Set = setOf() } private object FakeAppRepository : AppRepository {