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

Commit 91f7ae3d authored by Zaiyue Xue's avatar Zaiyue Xue
Browse files

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
parent c5fa04ec
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -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<Int>,
        showSystemFlow: Flow<Boolean>,
    ): Flow<(app: ApplicationInfo) -> Boolean>

    /** Gets the system app package names. */
    fun getSystemPackageNamesBlocking(config: AppListConfig): Set<String>
}

/**
 * Util for app list repository.
 */
object AppListRepositoryUtil {
    /** Gets the system app package names. */
    @JvmStatic
    fun getSystemPackageNames(context: Context, config: AppListConfig): Set<String> {
        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<String> =
            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<String> {
@@ -117,6 +142,11 @@ internal class AppListRepositoryImpl(private val context: Context) : AppListRepo
        }
    }

    private fun isSystemApp(app: ApplicationInfo, homeOrLauncherPackages: Set<String>): Boolean {
        return !app.isUpdatedSystemApp && app.isSystemApp &&
            !(app.packageName in homeOrLauncherPackages)
    }

    companion object {
        private fun ApplicationInfo.isInAppList(
            showInstantApps: Boolean,
+38 −17
Original line number Diff line number Diff line
@@ -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<ResolveInfo>
@@ -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<ResolveInfoFlags>(), 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
+2 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ class AppListViewModelTest {
            userIdFlow: Flow<Int>,
            showSystemFlow: Flow<Boolean>,
        ): Flow<(app: ApplicationInfo) -> Boolean> = flowOf { true }

        override fun getSystemPackageNamesBlocking(config: AppListConfig): Set<String> = setOf()
    }

    private object FakeAppRepository : AppRepository {