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 Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.runBlocking


/**
/**
 * The config used to load the App List.
 * The config used to load the App List.
@@ -47,8 +48,21 @@ internal interface AppListRepository {
        userIdFlow: Flow<Int>,
        userIdFlow: Flow<Int>,
        showSystemFlow: Flow<Boolean>,
        showSystemFlow: Flow<Boolean>,
    ): Flow<(app: ApplicationInfo) -> 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 {
internal class AppListRepositoryImpl(private val context: Context) : AppListRepository {
    private val packageManager = context.packageManager
    private val packageManager = context.packageManager
@@ -83,15 +97,26 @@ internal class AppListRepositoryImpl(private val context: Context) : AppListRepo
    ): Flow<(app: ApplicationInfo) -> Boolean> =
    ): Flow<(app: ApplicationInfo) -> Boolean> =
        userIdFlow.combine(showSystemFlow, ::showSystemPredicate)
        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(
    private suspend fun showSystemPredicate(
        userId: Int,
        userId: Int,
        showSystem: Boolean,
        showSystem: Boolean,
    ): (app: ApplicationInfo) -> Boolean {
    ): (app: ApplicationInfo) -> Boolean {
        if (showSystem) return { true }
        if (showSystem) return { true }
        val homeOrLauncherPackages = loadHomeOrLauncherPackages(userId)
        val homeOrLauncherPackages = loadHomeOrLauncherPackages(userId)
        return { app ->
        return { app -> !isSystemApp(app, homeOrLauncherPackages) }
            app.isUpdatedSystemApp || !app.isSystemApp || app.packageName in homeOrLauncherPackages
        }
    }
    }


    private suspend fun loadHomeOrLauncherPackages(userId: Int): Set<String> {
    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 {
    companion object {
        private fun ApplicationInfo.isInAppList(
        private fun ApplicationInfo.isInAppList(
            showInstantApps: Boolean,
            showInstantApps: Boolean,
+38 −17
Original line number Original line Diff line number Diff line
@@ -180,9 +180,7 @@ class AppListRepositoryTest {


    @Test
    @Test
    fun showSystemPredicate_showSystem() = runTest {
    fun showSystemPredicate_showSystem() = runTest {
        val app = ApplicationInfo().apply {
        val app = SYSTEM_APP
            flags = ApplicationInfo.FLAG_SYSTEM
        }


        val showSystemPredicate = getShowSystemPredicate(showSystem = true)
        val showSystemPredicate = getShowSystemPredicate(showSystem = true)


@@ -191,9 +189,7 @@ class AppListRepositoryTest {


    @Test
    @Test
    fun showSystemPredicate_notShowSystemAndIsSystemApp() = runTest {
    fun showSystemPredicate_notShowSystemAndIsSystemApp() = runTest {
        val app = ApplicationInfo().apply {
        val app = SYSTEM_APP
            flags = ApplicationInfo.FLAG_SYSTEM
        }


        val showSystemPredicate = getShowSystemPredicate(showSystem = false)
        val showSystemPredicate = getShowSystemPredicate(showSystem = false)


@@ -202,9 +198,7 @@ class AppListRepositoryTest {


    @Test
    @Test
    fun showSystemPredicate_isUpdatedSystemApp() = runTest {
    fun showSystemPredicate_isUpdatedSystemApp() = runTest {
        val app = ApplicationInfo().apply {
        val app = UPDATED_SYSTEM_APP
            flags = ApplicationInfo.FLAG_SYSTEM or ApplicationInfo.FLAG_UPDATED_SYSTEM_APP
        }


        val showSystemPredicate = getShowSystemPredicate(showSystem = false)
        val showSystemPredicate = getShowSystemPredicate(showSystem = false)


@@ -213,10 +207,8 @@ class AppListRepositoryTest {


    @Test
    @Test
    fun showSystemPredicate_isHome() = runTest {
    fun showSystemPredicate_isHome() = runTest {
        val app = ApplicationInfo().apply {
        val app = HOME_APP
            flags = ApplicationInfo.FLAG_SYSTEM

            packageName = "home.app"
        }
        whenever(packageManager.getHomeActivities(any())).thenAnswer {
        whenever(packageManager.getHomeActivities(any())).thenAnswer {
            @Suppress("UNCHECKED_CAST")
            @Suppress("UNCHECKED_CAST")
            val resolveInfos = it.arguments[0] as MutableList<ResolveInfo>
            val resolveInfos = it.arguments[0] as MutableList<ResolveInfo>
@@ -231,10 +223,8 @@ class AppListRepositoryTest {


    @Test
    @Test
    fun showSystemPredicate_appInLauncher() = runTest {
    fun showSystemPredicate_appInLauncher() = runTest {
        val app = ApplicationInfo().apply {
        val app = IN_LAUMCHER_APP
            flags = ApplicationInfo.FLAG_SYSTEM

            packageName = "app.in.launcher"
        }
        whenever(
        whenever(
            packageManager.queryIntentActivitiesAsUser(any(), any<ResolveInfoFlags>(), eq(USER_ID))
            packageManager.queryIntentActivitiesAsUser(any(), any<ResolveInfoFlags>(), eq(USER_ID))
        ).thenReturn(listOf(resolveInfoOf(packageName = app.packageName)))
        ).thenReturn(listOf(resolveInfoOf(packageName = app.packageName)))
@@ -244,6 +234,17 @@ class AppListRepositoryTest {
        assertThat(showSystemPredicate(app)).isTrue()
        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) =
    private suspend fun getShowSystemPredicate(showSystem: Boolean) =
        repository.showSystemPredicate(
        repository.showSystemPredicate(
            userIdFlow = flowOf(USER_ID),
            userIdFlow = flowOf(USER_ID),
@@ -264,6 +265,26 @@ class AppListRepositoryTest {
            privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT
            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 {
        fun resolveInfoOf(packageName: String) = ResolveInfo().apply {
            activityInfo = ActivityInfo().apply {
            activityInfo = ActivityInfo().apply {
                this.packageName = packageName
                this.packageName = packageName
+2 −0
Original line number Original line Diff line number Diff line
@@ -90,6 +90,8 @@ class AppListViewModelTest {
            userIdFlow: Flow<Int>,
            userIdFlow: Flow<Int>,
            showSystemFlow: Flow<Boolean>,
            showSystemFlow: Flow<Boolean>,
        ): Flow<(app: ApplicationInfo) -> Boolean> = flowOf { true }
        ): Flow<(app: ApplicationInfo) -> Boolean> = flowOf { true }

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


    private object FakeAppRepository : AppRepository {
    private object FakeAppRepository : AppRepository {