Loading packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt +13 −9 Original line number Diff line number Diff line Loading @@ -17,10 +17,11 @@ package com.android.settingslib.spaprivileged.model.app import android.content.Context import android.content.pm.FeatureFlags import android.content.pm.FeatureFlagsImpl import android.content.Intent import android.content.pm.ApplicationInfo import android.content.pm.FeatureFlags import android.content.pm.FeatureFlagsImpl import android.content.pm.Flags import android.content.pm.PackageManager import android.content.pm.PackageManager.ApplicationInfoFlags import android.content.pm.ResolveInfo Loading Loading @@ -85,13 +86,7 @@ class AppListRepositoryImpl( loadInstantApps: Boolean, matchAnyUserForAdmin: Boolean, ): List<ApplicationInfo> = coroutineScope { val hiddenSystemModulesDeferred = async { packageManager.getInstalledModules(0) .filter { it.isHidden } .map { it.packageName } .filterNotNull() .toSet() } val hiddenSystemModulesDeferred = async { packageManager.getHiddenSystemModules() } val hideWhenDisabledPackagesDeferred = async { context.resources.getStringArray(R.array.config_hideWhenDisabled_packageNames) } Loading Loading @@ -205,6 +200,15 @@ class AppListRepositoryImpl( private fun isSystemApp(app: ApplicationInfo, homeOrLauncherPackages: Set<String>): Boolean = app.isSystemApp && !app.isUpdatedSystemApp && app.packageName !in homeOrLauncherPackages private fun PackageManager.getHiddenSystemModules(): Set<String> { val moduleInfos = getInstalledModules(0).filter { it.isHidden } val hiddenApps = moduleInfos.mapNotNull { it.packageName }.toMutableSet() if (Flags.provideInfoOfApkInApex()) { hiddenApps += moduleInfos.flatMap { it.apkInApexPackageNames } } return hiddenApps } companion object { private fun ApplicationInfo.isInAppList( showInstantApps: Boolean, Loading packages/SettingsLib/SpaPrivileged/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -35,5 +35,6 @@ android_test { "androidx.test.ext.junit", "androidx.test.runner", "mockito-target-minus-junit4", "flag-junit", ], } packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt +52 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.FakeFeatureFlagsImpl import android.content.pm.Flags import android.content.pm.ModuleInfo import android.content.pm.PackageManager import android.content.pm.PackageManager.ApplicationInfoFlags import android.content.pm.PackageManager.ResolveInfoFlags Loading @@ -28,6 +29,7 @@ import android.content.pm.ResolveInfo import android.content.pm.UserInfo import android.content.res.Resources import android.os.UserManager import android.platform.test.flag.junit.SetFlagsRule import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.internal.R Loading @@ -35,6 +37,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any Loading @@ -50,6 +53,9 @@ import org.mockito.kotlin.whenever @RunWith(AndroidJUnit4::class) class AppListRepositoryTest { @get:Rule val mSetFlagsRule = SetFlagsRule() private val resources = mock<Resources> { on { getStringArray(R.array.config_hideWhenDisabled_packageNames) } doReturn emptyArray() } Loading Loading @@ -272,6 +278,38 @@ class AppListRepositoryTest { ) } @Test fun loadApps_hasApkInApexInfo_shouldNotIncludeAllHiddenApps() = runTest { mSetFlagsRule.enableFlags(Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) packageManager.stub { on { getInstalledModules(any()) } doReturn listOf(HIDDEN_MODULE) } mockInstalledApplications( listOf(NORMAL_APP, HIDDEN_APEX_APP, HIDDEN_MODULE_APP), ADMIN_USER_ID ) val appList = repository.loadApps(userId = ADMIN_USER_ID) assertThat(appList).containsExactly(NORMAL_APP) } @Test fun loadApps_noApkInApexInfo_shouldNotIncludeHiddenSystemModule() = runTest { mSetFlagsRule.disableFlags(Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) packageManager.stub { on { getInstalledModules(any()) } doReturn listOf(HIDDEN_MODULE) } mockInstalledApplications( listOf(NORMAL_APP, HIDDEN_APEX_APP, HIDDEN_MODULE_APP), ADMIN_USER_ID ) val appList = repository.loadApps(userId = ADMIN_USER_ID) assertThat(appList).containsExactly(NORMAL_APP, HIDDEN_APEX_APP) } @Test fun showSystemPredicate_showSystem() = runTest { val app = SYSTEM_APP Loading Loading @@ -402,6 +440,20 @@ class AppListRepositoryTest { isArchived = true } val HIDDEN_APEX_APP = ApplicationInfo().apply { packageName = "hidden.apex.package" } val HIDDEN_MODULE_APP = ApplicationInfo().apply { packageName = "hidden.module.package" } val HIDDEN_MODULE = ModuleInfo().apply { packageName = "hidden.module.package" apkInApexPackageNames = listOf("hidden.apex.package") isHidden = true } fun resolveInfoOf(packageName: String) = ResolveInfo().apply { activityInfo = ActivityInfo().apply { this.packageName = packageName Loading packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java +11 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.Flags; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; Loading Loading @@ -164,12 +165,16 @@ public class AppUtils { try { final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */); if (Flags.provideInfoOfApkInApex()) { return pkg.getApexPackageName() != null; } else { // Check if the package is contained in an APEX. There is no public API to properly // check whether a given APK package comes from an APEX registered as module. // Therefore we conservatively assume that any package scanned from an /apex path is // a system package. return pkg.applicationInfo.sourceDir.startsWith( Environment.getApexDirectory().getAbsolutePath()); } } catch (PackageManager.NameNotFoundException e) { return false; } Loading packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +6 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.Flags; import android.content.pm.IPackageManager; import android.content.pm.IPackageStatsObserver; import android.content.pm.ModuleInfo; Loading Loading @@ -226,6 +227,11 @@ public class ApplicationsState { final List<ModuleInfo> moduleInfos = mPm.getInstalledModules(0 /* flags */); for (ModuleInfo info : moduleInfos) { mSystemModules.put(info.getPackageName(), info.isHidden()); if (Flags.provideInfoOfApkInApex()) { for (String apkInApexPackageName : info.getApkInApexPackageNames()) { mSystemModules.put(apkInApexPackageName, info.isHidden()); } } } /** Loading Loading
packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt +13 −9 Original line number Diff line number Diff line Loading @@ -17,10 +17,11 @@ package com.android.settingslib.spaprivileged.model.app import android.content.Context import android.content.pm.FeatureFlags import android.content.pm.FeatureFlagsImpl import android.content.Intent import android.content.pm.ApplicationInfo import android.content.pm.FeatureFlags import android.content.pm.FeatureFlagsImpl import android.content.pm.Flags import android.content.pm.PackageManager import android.content.pm.PackageManager.ApplicationInfoFlags import android.content.pm.ResolveInfo Loading Loading @@ -85,13 +86,7 @@ class AppListRepositoryImpl( loadInstantApps: Boolean, matchAnyUserForAdmin: Boolean, ): List<ApplicationInfo> = coroutineScope { val hiddenSystemModulesDeferred = async { packageManager.getInstalledModules(0) .filter { it.isHidden } .map { it.packageName } .filterNotNull() .toSet() } val hiddenSystemModulesDeferred = async { packageManager.getHiddenSystemModules() } val hideWhenDisabledPackagesDeferred = async { context.resources.getStringArray(R.array.config_hideWhenDisabled_packageNames) } Loading Loading @@ -205,6 +200,15 @@ class AppListRepositoryImpl( private fun isSystemApp(app: ApplicationInfo, homeOrLauncherPackages: Set<String>): Boolean = app.isSystemApp && !app.isUpdatedSystemApp && app.packageName !in homeOrLauncherPackages private fun PackageManager.getHiddenSystemModules(): Set<String> { val moduleInfos = getInstalledModules(0).filter { it.isHidden } val hiddenApps = moduleInfos.mapNotNull { it.packageName }.toMutableSet() if (Flags.provideInfoOfApkInApex()) { hiddenApps += moduleInfos.flatMap { it.apkInApexPackageNames } } return hiddenApps } companion object { private fun ApplicationInfo.isInAppList( showInstantApps: Boolean, Loading
packages/SettingsLib/SpaPrivileged/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -35,5 +35,6 @@ android_test { "androidx.test.ext.junit", "androidx.test.runner", "mockito-target-minus-junit4", "flag-junit", ], }
packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt +52 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.FakeFeatureFlagsImpl import android.content.pm.Flags import android.content.pm.ModuleInfo import android.content.pm.PackageManager import android.content.pm.PackageManager.ApplicationInfoFlags import android.content.pm.PackageManager.ResolveInfoFlags Loading @@ -28,6 +29,7 @@ import android.content.pm.ResolveInfo import android.content.pm.UserInfo import android.content.res.Resources import android.os.UserManager import android.platform.test.flag.junit.SetFlagsRule import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.internal.R Loading @@ -35,6 +37,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any Loading @@ -50,6 +53,9 @@ import org.mockito.kotlin.whenever @RunWith(AndroidJUnit4::class) class AppListRepositoryTest { @get:Rule val mSetFlagsRule = SetFlagsRule() private val resources = mock<Resources> { on { getStringArray(R.array.config_hideWhenDisabled_packageNames) } doReturn emptyArray() } Loading Loading @@ -272,6 +278,38 @@ class AppListRepositoryTest { ) } @Test fun loadApps_hasApkInApexInfo_shouldNotIncludeAllHiddenApps() = runTest { mSetFlagsRule.enableFlags(Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) packageManager.stub { on { getInstalledModules(any()) } doReturn listOf(HIDDEN_MODULE) } mockInstalledApplications( listOf(NORMAL_APP, HIDDEN_APEX_APP, HIDDEN_MODULE_APP), ADMIN_USER_ID ) val appList = repository.loadApps(userId = ADMIN_USER_ID) assertThat(appList).containsExactly(NORMAL_APP) } @Test fun loadApps_noApkInApexInfo_shouldNotIncludeHiddenSystemModule() = runTest { mSetFlagsRule.disableFlags(Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) packageManager.stub { on { getInstalledModules(any()) } doReturn listOf(HIDDEN_MODULE) } mockInstalledApplications( listOf(NORMAL_APP, HIDDEN_APEX_APP, HIDDEN_MODULE_APP), ADMIN_USER_ID ) val appList = repository.loadApps(userId = ADMIN_USER_ID) assertThat(appList).containsExactly(NORMAL_APP, HIDDEN_APEX_APP) } @Test fun showSystemPredicate_showSystem() = runTest { val app = SYSTEM_APP Loading Loading @@ -402,6 +440,20 @@ class AppListRepositoryTest { isArchived = true } val HIDDEN_APEX_APP = ApplicationInfo().apply { packageName = "hidden.apex.package" } val HIDDEN_MODULE_APP = ApplicationInfo().apply { packageName = "hidden.module.package" } val HIDDEN_MODULE = ModuleInfo().apply { packageName = "hidden.module.package" apkInApexPackageNames = listOf("hidden.apex.package") isHidden = true } fun resolveInfoOf(packageName: String) = ResolveInfo().apply { activityInfo = ActivityInfo().apply { this.packageName = packageName Loading
packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java +11 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.Flags; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; Loading Loading @@ -164,12 +165,16 @@ public class AppUtils { try { final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */); if (Flags.provideInfoOfApkInApex()) { return pkg.getApexPackageName() != null; } else { // Check if the package is contained in an APEX. There is no public API to properly // check whether a given APK package comes from an APEX registered as module. // Therefore we conservatively assume that any package scanned from an /apex path is // a system package. return pkg.applicationInfo.sourceDir.startsWith( Environment.getApexDirectory().getAbsolutePath()); } } catch (PackageManager.NameNotFoundException e) { return false; } Loading
packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +6 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.Flags; import android.content.pm.IPackageManager; import android.content.pm.IPackageStatsObserver; import android.content.pm.ModuleInfo; Loading Loading @@ -226,6 +227,11 @@ public class ApplicationsState { final List<ModuleInfo> moduleInfos = mPm.getInstalledModules(0 /* flags */); for (ModuleInfo info : moduleInfos) { mSystemModules.put(info.getPackageName(), info.isHidden()); if (Flags.provideInfoOfApkInApex()) { for (String apkInApexPackageName : info.getApkInApexPackageNames()) { mSystemModules.put(apkInApexPackageName, info.isHidden()); } } } /** Loading