From 8615a9026dd590a21f638f2b2d8aa8de98581fe9 Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Wed, 9 Jan 2019 14:58:26 -0800 Subject: [PATCH] Hide mainline module apps in settings. - check whether an app is system hidden module and do not include them when we retrieve the installed apps list. Bug: 120546598 Test: make RunSettingsLibRoboTests Change-Id: I7dc78a62bf8664d4316511467a9e046a1726935f --- .../settingslib/applications/AppUtils.java | 9 ++ .../applications/ApplicationsState.java | 30 ++++- .../ApplicationsStateRoboTest.java | 109 +++++++++++++----- 3 files changed, 116 insertions(+), 32 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java index 7357fe63d9b0f..42afb69a27f48 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java @@ -16,6 +16,7 @@ package com.android.settingslib.applications; +import android.app.Application; import android.content.ComponentName; import android.content.Context; import android.content.IntentFilter; @@ -123,4 +124,12 @@ public class AppUtils { return null; } + /** + * Returns a boolean indicating whether the given package is a hidden system module + */ + public static boolean isHiddenSystemModule(Context context, String packageName) { + return ApplicationsState.getInstance((Application) context.getApplicationContext()) + .isHiddenModule(packageName); + } + } diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index a936df2bf2ebf..c9fbc7ba9f052 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -29,6 +29,7 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.IPackageStatsObserver; +import android.content.pm.ModuleInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageStats; @@ -71,6 +72,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.UUID; @@ -95,9 +97,14 @@ public class ApplicationsState { static ApplicationsState sInstance; public static ApplicationsState getInstance(Application app) { + return getInstance(app, AppGlobals.getPackageManager()); + } + + @VisibleForTesting + static ApplicationsState getInstance(Application app, IPackageManager iPackageManager) { synchronized (sLock) { if (sInstance == null) { - sInstance = new ApplicationsState(app); + sInstance = new ApplicationsState(app, iPackageManager); } return sInstance; } @@ -132,6 +139,7 @@ public class ApplicationsState { String mCurComputingSizePkg; int mCurComputingSizeUserId; boolean mSessionsChanged; + final HashSet mHiddenModules = new HashSet<>(); // Temporary for dispatching session callbacks. Only touched by main thread. final ArrayList> mActiveSessions = new ArrayList<>(); @@ -172,11 +180,11 @@ public class ApplicationsState { FLAG_SESSION_REQUEST_HOME_APP | FLAG_SESSION_REQUEST_ICONS | FLAG_SESSION_REQUEST_SIZES | FLAG_SESSION_REQUEST_LAUNCHER; - private ApplicationsState(Application app) { + private ApplicationsState(Application app, IPackageManager iPackageManager) { mContext = app; mPm = mContext.getPackageManager(); mDrawableFactory = IconDrawableFactory.newInstance(mContext); - mIpm = AppGlobals.getPackageManager(); + mIpm = iPackageManager; mUm = mContext.getSystemService(UserManager.class); mStats = mContext.getSystemService(StorageStatsManager.class); for (int userId : mUm.getProfileIdsWithDisabled(UserHandle.myUserId())) { @@ -194,6 +202,13 @@ public class ApplicationsState { mRetrieveFlags = PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; + final List moduleInfos = mPm.getInstalledModules(0 /* flags */); + for (ModuleInfo info : moduleInfos) { + if (info.isHidden()) { + mHiddenModules.add(info.getPackageName()); + } + } + /** * This is a trick to prevent the foreground thread from being delayed. * The problem is that Dalvik monitors are initially spin locks, to keep @@ -283,6 +298,10 @@ public class ApplicationsState { } mHaveDisabledApps = true; } + if (isHiddenModule(info.packageName)) { + mApplications.remove(i--); + continue; + } if (!mHaveInstantApps && AppUtils.isInstant(info)) { mHaveInstantApps = true; } @@ -314,10 +333,15 @@ public class ApplicationsState { public boolean haveDisabledApps() { return mHaveDisabledApps; } + public boolean haveInstantApps() { return mHaveInstantApps; } + boolean isHiddenModule(String packageName) { + return mHiddenModules.contains(packageName); + } + void doPauseIfNeededLocked() { if (!mResumed) { return; diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java index ccec175aefadc..a098ecc17b3da 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java @@ -18,7 +18,9 @@ package com.android.settingslib.applications; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.shadow.api.Shadow.extract; @@ -33,12 +35,16 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; +import android.content.pm.ModuleInfo; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.UserHandle; +import android.text.TextUtils; import android.util.IconDrawableFactory; import com.android.settingslib.applications.ApplicationsState.AppEntry; @@ -46,11 +52,11 @@ import com.android.settingslib.applications.ApplicationsState.Callbacks; import com.android.settingslib.applications.ApplicationsState.Session; import com.android.settingslib.testutils.shadow.ShadowUserManager; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatchers; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -78,6 +84,8 @@ public class ApplicationsStateRoboTest { /** Class under test */ private ApplicationsState mApplicationsState; + private Session mSession; + @Mock private Callbacks mCallbacks; @@ -85,6 +93,8 @@ public class ApplicationsStateRoboTest { private ArgumentCaptor> mAppEntriesCaptor; @Mock private StorageStatsManager mStorageStatsManager; + @Mock + private IPackageManager mPackageManagerService; @Implements(value = IconDrawableFactory.class) public static class ShadowIconDrawableFactory { @@ -99,6 +109,11 @@ public class ApplicationsStateRoboTest { public static class ShadowPackageManager extends org.robolectric.shadows.ShadowApplicationPackageManager { + // test installed modules, 2 regular, 2 hidden + private final String[] mModuleNames = { + "test.module.1", "test.hidden.module.2", "test.hidden.module.3", "test.module.4"}; + private final List mInstalledModules = new ArrayList<>(); + @Implementation protected ComponentName getHomeActivities(List outActivities) { ResolveInfo resolveInfo = new ResolveInfo(); @@ -109,6 +124,16 @@ public class ApplicationsStateRoboTest { return ComponentName.createRelative(resolveInfo.activityInfo.packageName, "foo"); } + @Implementation + public List getInstalledModules(int flags) { + if (mInstalledModules.isEmpty()) { + for (String moduleName : mModuleNames) { + mInstalledModules.add(createModuleInfo(moduleName)); + } + } + return mInstalledModules; + } + public List queryIntentActivitiesAsUser(Intent intent, @PackageManager.ResolveInfoFlags int flags, @UserIdInt int userId) { List resolveInfos = new ArrayList<>(); @@ -121,6 +146,15 @@ public class ApplicationsStateRoboTest { resolveInfos.add(resolveInfo); return resolveInfos; } + + private ModuleInfo createModuleInfo(String packageName) { + final ModuleInfo info = new ModuleInfo(); + info.setName(packageName); + info.setPackageName(packageName); + // will treat any app with package name that contains "hidden" as hidden module + info.setHidden(!TextUtils.isEmpty(packageName) && packageName.contains("hidden")); + return info; + } } @Before @@ -136,12 +170,28 @@ public class ApplicationsStateRoboTest { storageStats.codeBytes = 10; storageStats.dataBytes = 20; storageStats.cacheBytes = 30; - when(mStorageStatsManager.queryStatsForPackage(ArgumentMatchers.any(UUID.class), - anyString(), ArgumentMatchers.any(UserHandle.class))).thenReturn(storageStats); + when(mStorageStatsManager.queryStatsForPackage(any(UUID.class), + anyString(), any(UserHandle.class))).thenReturn(storageStats); + + // Set up 3 installed apps, in which 1 is hidden module + final List infos = new ArrayList<>(); + infos.add(createApplicationInfo("test.package.1")); + infos.add(createApplicationInfo("test.hidden.module.2")); + infos.add(createApplicationInfo("test.package.3")); + when(mPackageManagerService.getInstalledApplications( + anyInt() /* flags */, anyInt() /* userId */)).thenReturn(new ParceledListSlice(infos)); ApplicationsState.sInstance = null; - mApplicationsState = ApplicationsState.getInstance(RuntimeEnvironment.application); + mApplicationsState = + ApplicationsState.getInstance(RuntimeEnvironment.application, mPackageManagerService); mApplicationsState.clearEntries(); + + mSession = mApplicationsState.newSession(mCallbacks); + } + + @After + public void tearDown() { + mSession.onDestroy(); } private ApplicationInfo createApplicationInfo(String packageName) { @@ -187,12 +237,11 @@ public class ApplicationsStateRoboTest { @Test public void testDefaultSessionLoadsAll() { - Session session = mApplicationsState.newSession(mCallbacks); - session.onResume(); + mSession.onResume(); addApp(HOME_PACKAGE_NAME, 1); addApp(LAUNCHABLE_PACKAGE_NAME, 2); - session.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); + mSession.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); processAllMessages(); verify(mCallbacks).onRebuildComplete(mAppEntriesCaptor.capture()); @@ -211,17 +260,15 @@ public class ApplicationsStateRoboTest { AppEntry launchableEntry = findAppEntry(appEntries, 2); assertThat(launchableEntry.hasLauncherEntry).isTrue(); assertThat(launchableEntry.launcherEntryEnabled).isTrue(); - session.onDestroy(); } @Test public void testCustomSessionLoadsIconsOnly() { - Session session = mApplicationsState.newSession(mCallbacks); - session.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_ICONS); - session.onResume(); + mSession.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_ICONS); + mSession.onResume(); addApp(LAUNCHABLE_PACKAGE_NAME, 1); - session.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); + mSession.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); processAllMessages(); verify(mCallbacks).onRebuildComplete(mAppEntriesCaptor.capture()); @@ -232,17 +279,15 @@ public class ApplicationsStateRoboTest { assertThat(launchableEntry.icon).isNotNull(); assertThat(launchableEntry.size).isEqualTo(-1); assertThat(launchableEntry.hasLauncherEntry).isFalse(); - session.onDestroy(); } @Test public void testCustomSessionLoadsSizesOnly() { - Session session = mApplicationsState.newSession(mCallbacks); - session.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_SIZES); - session.onResume(); + mSession.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_SIZES); + mSession.onResume(); addApp(LAUNCHABLE_PACKAGE_NAME, 1); - session.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); + mSession.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); processAllMessages(); verify(mCallbacks).onRebuildComplete(mAppEntriesCaptor.capture()); @@ -253,17 +298,15 @@ public class ApplicationsStateRoboTest { assertThat(launchableEntry.icon).isNull(); assertThat(launchableEntry.hasLauncherEntry).isFalse(); assertThat(launchableEntry.size).isGreaterThan(0L); - session.onDestroy(); } @Test public void testCustomSessionLoadsHomeOnly() { - Session session = mApplicationsState.newSession(mCallbacks); - session.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_HOME_APP); - session.onResume(); + mSession.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_HOME_APP); + mSession.onResume(); addApp(HOME_PACKAGE_NAME, 1); - session.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); + mSession.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); processAllMessages(); verify(mCallbacks).onRebuildComplete(mAppEntriesCaptor.capture()); @@ -275,17 +318,15 @@ public class ApplicationsStateRoboTest { assertThat(launchableEntry.hasLauncherEntry).isFalse(); assertThat(launchableEntry.size).isEqualTo(-1); assertThat(launchableEntry.isHomeApp).isTrue(); - session.onDestroy(); } @Test public void testCustomSessionLoadsLeanbackOnly() { - Session session = mApplicationsState.newSession(mCallbacks); - session.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_LEANBACK_LAUNCHER); - session.onResume(); + mSession.setSessionFlags(ApplicationsState.FLAG_SESSION_REQUEST_LEANBACK_LAUNCHER); + mSession.onResume(); addApp(LAUNCHABLE_PACKAGE_NAME, 1); - session.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); + mSession.rebuild(ApplicationsState.FILTER_EVERYTHING, ApplicationsState.SIZE_COMPARATOR); processAllMessages(); verify(mCallbacks).onRebuildComplete(mAppEntriesCaptor.capture()); @@ -298,6 +339,16 @@ public class ApplicationsStateRoboTest { assertThat(launchableEntry.isHomeApp).isFalse(); assertThat(launchableEntry.hasLauncherEntry).isTrue(); assertThat(launchableEntry.launcherEntryEnabled).isTrue(); - session.onDestroy(); } + + @Test + public void onResume_shouldNotIncludeSystemHiddenModule() { + mSession.onResume(); + + final List mApplications = mApplicationsState.mApplications; + assertThat(mApplications).hasSize(2); + assertThat(mApplications.get(0).packageName).isEqualTo("test.package.1"); + assertThat(mApplications.get(1).packageName).isEqualTo("test.package.3"); + } + }