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: I670c95350e3c21db9f74f37b675aba1b23c67a61
This commit is contained in:
Alyssa Ketpreechasawat
2024-10-04 16:22:43 +00:00
parent 999cf6ec6c
commit f480cdd56f
6 changed files with 92 additions and 3 deletions

View File

@@ -186,7 +186,8 @@ public class RecentAppStatsMixin implements LifecycleObserver, OnStart {
return false; return false;
} }
if (AppUtils.isHiddenSystemModule(mContext, pkgName)) { if (!android.content.pm.Flags.removeHiddenModuleUsage()
&& AppUtils.isHiddenSystemModule(mContext, pkgName)) {
return false; return false;
} }

View File

@@ -243,7 +243,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
if (!ensurePackageInfoAvailable(activity)) { if (!ensurePackageInfoAvailable(activity)) {
return; return;
} }
if (!ensureDisplayableModule(activity)) { if (!android.content.pm.Flags.removeHiddenModuleUsage() && !ensureDisplayableModule(activity)) {
return; return;
} }
startListeningToPackageRemove(); startListeningToPackageRemove();
@@ -386,6 +386,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
* If it's not, the fragment will finish. * If it's not, the fragment will finish.
* *
* @return true if package is displayable. * @return true if package is displayable.
* TODO(b/382016780): to be removed after flag cleanup.
*/ */
@VisibleForTesting @VisibleForTesting
boolean ensureDisplayableModule(Activity activity) { boolean ensureDisplayableModule(Activity activity) {

View File

@@ -223,10 +223,16 @@ public class BatteryUtils {
public boolean shouldHideUidBatteryConsumerUnconditionally( public boolean shouldHideUidBatteryConsumerUnconditionally(
UidBatteryConsumer consumer, String[] packages) { UidBatteryConsumer consumer, String[] packages) {
final int uid = consumer.getUid(); final int uid = consumer.getUid();
if (android.content.pm.Flags.removeHiddenModuleUsage()) {
return uid == UID_TETHERING ? false : uid < 0;
}
return uid == UID_TETHERING ? false : uid < 0 || isHiddenSystemModule(packages); return uid == UID_TETHERING ? false : uid < 0 || isHiddenSystemModule(packages);
} }
/** Returns true if one the specified packages belongs to a hidden system module. */ /**
* Returns true if one the specified packages belongs to a hidden system module.
* TODO(b/382016780): to be removed after flag cleanup.
*/
public boolean isHiddenSystemModule(String[] packages) { public boolean isHiddenSystemModule(String[] packages) {
if (packages != null) { if (packages != null) {
for (int i = 0, length = packages.length; i < length; i++) { for (int i = 0, length = packages.length; i < length; i++) {

View File

@@ -38,12 +38,16 @@ import android.content.pm.ResolveInfo;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider; import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
@@ -88,6 +92,9 @@ public class RecentAppStatsMixinTest {
private RecentAppStatsMixin mRecentAppStatsMixin; private RecentAppStatsMixin mRecentAppStatsMixin;
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before @Before
public void setUp() throws PackageManager.NameNotFoundException { public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
@@ -255,6 +262,59 @@ public class RecentAppStatsMixinTest {
} }
@Test @Test
@EnableFlags({android.content.pm.Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE})
public void loadDisplayableRecentApps_twoSystemModulesSet_shouldHaveTwoSystemModules() {
final List<UsageStats> stats = new ArrayList<>();
// System modules.
final UsageStats stat1 = new UsageStats();
stat1.mLastTimeUsed = System.currentTimeMillis();
stat1.mPackageName = "com.foo.module1";
stats.add(stat1);
final UsageStats stat2 = new UsageStats();
stat2.mLastTimeUsed = System.currentTimeMillis() + 200;
stat2.mPackageName = "com.foo.module2";
stats.add(stat2);
ApplicationsState.AppEntry stat1Entry = mock(ApplicationsState.AppEntry.class);
ApplicationsState.AppEntry stat2Entry = mock(ApplicationsState.AppEntry.class);
stat1Entry.info = mApplicationInfo;
stat2Entry.info = mApplicationInfo;
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())).thenReturn(stat1Entry);
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())).thenReturn(stat2Entry);
// Hidden status set to false and true, but they should not cause the difference in
// the behavior.
final ModuleInfo moduleInfo1 = new ModuleInfo();
moduleInfo1.setPackageName(stat1.mPackageName);
moduleInfo1.setHidden(false);
final ModuleInfo moduleInfo2 = new ModuleInfo();
moduleInfo2.setPackageName(stat2.mPackageName);
moduleInfo2.setHidden(true);
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null);
final List<ModuleInfo> modules = new ArrayList<>();
modules.add(moduleInfo1);
modules.add(moduleInfo2);
when(mPackageManager.getInstalledModules(anyInt() /* flags */))
.thenReturn(modules);
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(2);
}
// TODO(b/382016780): to be removed after flag cleanup.
@Test
@DisableFlags({android.content.pm.Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE})
public void loadDisplayableRecentApps_hiddenSystemModuleSet_shouldNotHaveHiddenSystemModule() { public void loadDisplayableRecentApps_hiddenSystemModuleSet_shouldNotHaveHiddenSystemModule() {
final List<UsageStats> stats = new ArrayList<>(); final List<UsageStats> stats = new ArrayList<>();
// Regular app. // Regular app.

View File

@@ -50,7 +50,9 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserManager; import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArraySet; import android.util.ArraySet;
import android.view.View; import android.view.View;
@@ -68,6 +70,7 @@ import com.android.settingslib.widget.ActionButtonsPreference;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Answers; import org.mockito.Answers;
@@ -128,6 +131,9 @@ public class AppButtonsPreferenceControllerTest {
private ActionButtonsPreference mButtonPrefs; private ActionButtonsPreference mButtonPrefs;
private AppButtonsPreferenceController mController; private AppButtonsPreferenceController mController;
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
@@ -543,12 +549,21 @@ public class AppButtonsPreferenceControllerTest {
@Test @Test
@Config(shadows = ShadowAppUtils.class) @Config(shadows = ShadowAppUtils.class)
@DisableFlags({android.content.pm.Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE})
public void getAvailabilityStatus_systemModule() { public void getAvailabilityStatus_systemModule() {
ShadowAppUtils.addHiddenModule(mController.mPackageName); ShadowAppUtils.addHiddenModule(mController.mPackageName);
assertThat(mController.getAvailabilityStatus()).isEqualTo( assertThat(mController.getAvailabilityStatus()).isEqualTo(
AppButtonsPreferenceController.DISABLED_FOR_USER); AppButtonsPreferenceController.DISABLED_FOR_USER);
} }
@Test
@Config(shadows = ShadowAppUtils.class)
public void getAvailabilityStatus_mainlineModule() {
ShadowAppUtils.addMainlineModule(mController.mPackageName);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
AppButtonsPreferenceController.DISABLED_FOR_USER);
}
@Test @Test
public void handleActivityResult_onAppUninstall_removeTask() { public void handleActivityResult_onAppUninstall_removeTask() {
mController.handleActivityResult(REQUEST_UNINSTALL, 0, new Intent()); mController.handleActivityResult(REQUEST_UNINSTALL, 0, new Intent());
@@ -639,15 +654,18 @@ public class AppButtonsPreferenceControllerTest {
@Implements(AppUtils.class) @Implements(AppUtils.class)
public static class ShadowAppUtils { public static class ShadowAppUtils {
// TODO(b/382016780): to be removed after flag cleanup.
public static Set<String> sSystemModules = new ArraySet<>(); public static Set<String> sSystemModules = new ArraySet<>();
public static Set<String> sMainlineModules = new ArraySet<>(); public static Set<String> sMainlineModules = new ArraySet<>();
@Resetter @Resetter
public static void reset() { public static void reset() {
// TODO(b/382016780): to be removed after flag cleanup.
sSystemModules.clear(); sSystemModules.clear();
sMainlineModules.clear(); sMainlineModules.clear();
} }
// TODO(b/382016780): to be removed after flag cleanup.
public static void addHiddenModule(String pkg) { public static void addHiddenModule(String pkg) {
sSystemModules.add(pkg); sSystemModules.add(pkg);
} }
@@ -661,6 +679,7 @@ public class AppButtonsPreferenceControllerTest {
return false; return false;
} }
// TODO(b/382016780): to be removed after flag cleanup.
@Implementation @Implementation
protected static boolean isSystemModule(Context context, String packageName) { protected static boolean isSystemModule(Context context, String packageName) {
return sSystemModules.contains(packageName); return sSystemModules.contains(packageName);

View File

@@ -205,6 +205,7 @@ public final class AppInfoDashboardFragmentTest {
verify(mActivity, never()).finishAndRemoveTask(); verify(mActivity, never()).finishAndRemoveTask();
} }
// TODO(b/382016780): to be removed after flag cleanup.
@Test @Test
@Config(shadows = ShadowAppUtils.class) @Config(shadows = ShadowAppUtils.class)
public void ensureDisplayableModule_hiddenModule_shouldReturnFalse() { public void ensureDisplayableModule_hiddenModule_shouldReturnFalse() {
@@ -215,6 +216,7 @@ public final class AppInfoDashboardFragmentTest {
assertThat(mFragment.ensureDisplayableModule(mActivity)).isFalse(); assertThat(mFragment.ensureDisplayableModule(mActivity)).isFalse();
} }
// TODO(b/382016780): to be removed after flag cleanup.
@Test @Test
@Config(shadows = ShadowAppUtils.class) @Config(shadows = ShadowAppUtils.class)
public void ensureDisplayableModule_regularApp_shouldReturnTrue() { public void ensureDisplayableModule_regularApp_shouldReturnTrue() {