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

Commit d97ff4ed authored by Alyssa Ketpreechasawat's avatar Alyssa Ketpreechasawat
Browse files

Remove ModuleInfo#isHidden Usage from the source code.

ModuleInfo#isHidden is used for getting hidden module status from
ModuleMetadata package (Mainline). It was set to hide Mainline modules'
Apk to show in the Settings UI and this has caused the issue as it
disallowed the user to toggle permissions where it was needed. Thus, we
decided to deprecate the usage of ModuleInfo#isHidden (see
go/aml-hidden-modules-permissions).

Bug: 379056868
Test: unittest
Test: check behavior before/after enable flags
Flag: android.content.pm.remove_hidden_module_usage
Change-Id: Ib7710551559552ecf337493e6dbc2aab566105c9
parent a8eeebd5
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ class AppListRepositoryImpl(
        matchAnyUserForAdmin: Boolean,
    ): List<ApplicationInfo> = try {
        coroutineScope {
            // TODO(b/382016780): to be removed after flag cleanup.
            val hiddenSystemModulesDeferred = async { packageManager.getHiddenSystemModules() }
            val hideWhenDisabledPackagesDeferred = async {
                context.resources.getStringArray(R.array.config_hideWhenDisabled_packageNames)
@@ -95,6 +96,7 @@ class AppListRepositoryImpl(
            val installedApplicationsAsUser =
                getInstalledApplications(userId, matchAnyUserForAdmin)

            // TODO(b/382016780): to be removed after flag cleanup.
            val hiddenSystemModules = hiddenSystemModulesDeferred.await()
            val hideWhenDisabledPackages = hideWhenDisabledPackagesDeferred.await()
            installedApplicationsAsUser.filter { app ->
@@ -206,6 +208,7 @@ class AppListRepositoryImpl(
    private fun isSystemApp(app: ApplicationInfo, homeOrLauncherPackages: Set<String>): Boolean =
        app.isSystemApp && !app.isUpdatedSystemApp && app.packageName !in homeOrLauncherPackages

    // TODO(b/382016780): to be removed after flag cleanup.
    private fun PackageManager.getHiddenSystemModules(): Set<String> {
        val moduleInfos = getInstalledModules(0).filter { it.isHidden }
        val hiddenApps = moduleInfos.mapNotNull { it.packageName }.toMutableSet()
@@ -218,13 +221,14 @@ class AppListRepositoryImpl(
    companion object {
        private const val TAG = "AppListRepository"

        // TODO(b/382016780): to be removed after flag cleanup.
        private fun ApplicationInfo.isInAppList(
            showInstantApps: Boolean,
            hiddenSystemModules: Set<String>,
            hideWhenDisabledPackages: Array<String>,
        ) = when {
            !showInstantApps && isInstantApp -> false
            packageName in hiddenSystemModules -> false
            !Flags.removeHiddenModuleUsage() && (packageName in hiddenSystemModules) -> false
            packageName in hideWhenDisabledPackages -> enabled && !isDisabledUntilUsed
            enabled -> true
            else -> enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
+19 −1
Original line number Diff line number Diff line
@@ -281,6 +281,23 @@ class AppListRepositoryTest {
        )
    }

    @EnableFlags(Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE)
    @Test
    fun loadApps_shouldIncludeAllSystemModuleApps() = runTest {
        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, HIDDEN_MODULE_APP)
    }

    @DisableFlags(Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE)
    @EnableFlags(Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX)
    @Test
    fun loadApps_hasApkInApexInfo_shouldNotIncludeAllHiddenApps() = runTest {
@@ -297,7 +314,7 @@ class AppListRepositoryTest {
        assertThat(appList).containsExactly(NORMAL_APP)
    }

    @DisableFlags(Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX)
    @DisableFlags(Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX, Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE)
    @Test
    fun loadApps_noApkInApexInfo_shouldNotIncludeHiddenSystemModule() = runTest {
        packageManager.stub {
@@ -456,6 +473,7 @@ class AppListRepositoryTest {
            isArchived = true
        }

        // TODO(b/382016780): to be removed after flag cleanup.
        val HIDDEN_APEX_APP = ApplicationInfo().apply {
            packageName = "hidden.apex.package"
        }
+1 −0
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ public class AppUtils {

    /**
     * Returns a boolean indicating whether the given package is a hidden system module
     * TODO(b/382016780): to be removed after flag cleanup.
     */
    public static boolean isHiddenSystemModule(Context context, String packageName) {
        return ApplicationsState.getInstance((Application) context.getApplicationContext())
+13 −8
Original line number Diff line number Diff line
@@ -157,6 +157,7 @@ public class ApplicationsState {
    int mCurComputingSizeUserId;
    boolean mSessionsChanged;
    // Maps all installed modules on the system to whether they're hidden or not.
    // TODO(b/382016780): to be removed after flag cleanup.
    final HashMap<String, Boolean> mSystemModules = new HashMap<>();

    // Temporary for dispatching session callbacks.  Only touched by main thread.
@@ -226,6 +227,7 @@ public class ApplicationsState {
        mRetrieveFlags = PackageManager.MATCH_DISABLED_COMPONENTS |
                PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;

        if (!Flags.removeHiddenModuleUsage()) {
            final List<ModuleInfo> moduleInfos = mPm.getInstalledModules(0 /* flags */);
            for (ModuleInfo info : moduleInfos) {
                mSystemModules.put(info.getPackageName(), info.isHidden());
@@ -235,6 +237,7 @@ public class ApplicationsState {
                    }
                }
            }
        }

        /**
         * This is a trick to prevent the foreground thread from being delayed.
@@ -336,7 +339,7 @@ public class ApplicationsState {
                }
                mHaveDisabledApps = true;
            }
            if (isHiddenModule(info.packageName)) {
            if (!Flags.removeHiddenModuleUsage() && isHiddenModule(info.packageName)) {
                mApplications.remove(i--);
                continue;
            }
@@ -453,6 +456,7 @@ public class ApplicationsState {
        return mHaveInstantApps;
    }

    // TODO(b/382016780): to be removed after flag cleanup.
    boolean isHiddenModule(String packageName) {
        Boolean isHidden = mSystemModules.get(packageName);
        if (isHidden == null) {
@@ -462,6 +466,7 @@ public class ApplicationsState {
        return isHidden;
    }

    // TODO(b/382016780): to be removed after flag cleanup.
    boolean isSystemModule(String packageName) {
        return mSystemModules.containsKey(packageName);
    }
@@ -755,7 +760,7 @@ public class ApplicationsState {
            Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
        }
        if (entry == null) {
            if (isHiddenModule(info.packageName)) {
            if (!Flags.removeHiddenModuleUsage() && isHiddenModule(info.packageName)) {
                if (DEBUG) {
                    Log.i(TAG, "No AppEntry for " + info.packageName + " (hidden module)");
                }
+20 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.settingslib.applications;

import static android.content.pm.Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE;
import static android.content.pm.Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX;
import static android.os.UserHandle.MU_ENABLED;
import static android.os.UserHandle.USER_SYSTEM;
@@ -59,6 +60,8 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
@@ -204,6 +207,7 @@ public class ApplicationsStateRoboTest {
            info.setPackageName(packageName);
            info.setApkInApexPackageNames(Collections.singletonList(apexPackageName));
            // will treat any app with package name that contains "hidden" as hidden module
            // TODO(b/382016780): to be removed after flag cleanup.
            info.setHidden(!TextUtils.isEmpty(packageName) && packageName.contains("hidden"));
            return info;
        }
@@ -414,6 +418,7 @@ public class ApplicationsStateRoboTest {
    }

    @Test
    @DisableFlags({FLAG_REMOVE_HIDDEN_MODULE_USAGE})
    public void onResume_shouldNotIncludeSystemHiddenModule() {
        mSession.onResume();

@@ -423,6 +428,18 @@ public class ApplicationsStateRoboTest {
        assertThat(mApplications.get(1).packageName).isEqualTo("test.package.3");
    }

    @Test
    @EnableFlags({FLAG_REMOVE_HIDDEN_MODULE_USAGE})
    public void onResume_shouldIncludeSystemModule() {
        mSession.onResume();

        final List<ApplicationInfo> mApplications = mApplicationsState.mApplications;
        assertThat(mApplications).hasSize(3);
        assertThat(mApplications.get(0).packageName).isEqualTo("test.package.1");
        assertThat(mApplications.get(1).packageName).isEqualTo("test.hidden.module.2");
        assertThat(mApplications.get(2).packageName).isEqualTo("test.package.3");
    }

    @Test
    public void removeAndInstall_noWorkprofile_doResumeIfNeededLocked_shouldClearEntries()
            throws RemoteException {
@@ -832,6 +849,7 @@ public class ApplicationsStateRoboTest {
        mApplicationsState.mEntriesMap.clear();
        ApplicationInfo appInfo = createApplicationInfo(PKG_1, /* uid= */ 0);
        mApplicationsState.mApplications.add(appInfo);
        // TODO(b/382016780): to be removed after flag cleanup.
        mApplicationsState.mSystemModules.put(PKG_1, /* value= */ false);

        assertThat(mApplicationsState.getEntry(PKG_1, /* userId= */ 0).info.packageName)
@@ -839,6 +857,7 @@ public class ApplicationsStateRoboTest {
    }

    @Test
    @DisableFlags({FLAG_REMOVE_HIDDEN_MODULE_USAGE})
    public void isHiddenModule_hasApkInApexInfo_shouldSupportHiddenApexPackage() {
        mSetFlagsRule.enableFlags(FLAG_PROVIDE_INFO_OF_APK_IN_APEX);
        ApplicationsState.sInstance = null;
@@ -853,6 +872,7 @@ public class ApplicationsStateRoboTest {
    }

    @Test
    @DisableFlags({FLAG_REMOVE_HIDDEN_MODULE_USAGE})
    public void isHiddenModule_noApkInApexInfo_onlySupportHiddenModule() {
        mSetFlagsRule.disableFlags(FLAG_PROVIDE_INFO_OF_APK_IN_APEX);
        ApplicationsState.sInstance = null;
Loading