Skip to content

Commit

Permalink
Secure MATCH_UNINSTALLED_PACKAGES across users
Browse files Browse the repository at this point in the history
Introduce a new internal flag MATCH_ANY_USER for genuine uses
of searching through all apps on the device.

Some temporary accommodations for Launchers that reach across
to the work profile until we have a new LauncherApps API to do
that officially.

Bug: 31000380
Test: CTS tests added
Change-Id: I2e43dc49d6c2e11814a8f8d1eb07ef557f31af34
  • Loading branch information
Amith Yamasani committed Nov 30, 2016
1 parent c1e6a12 commit 0d1fd8d
Show file tree
Hide file tree
Showing 28 changed files with 163 additions and 78 deletions.
6 changes: 5 additions & 1 deletion core/java/android/content/pm/LauncherActivityInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public UserHandle getUser() {
* @return The label for the activity.
*/
public CharSequence getLabel() {
// TODO: Go through LauncherAppsService
return mActivityInfo.loadLabel(mPm);
}

Expand All @@ -101,6 +102,7 @@ public CharSequence getLabel() {
* @return The drawable associated with the activity.
*/
public Drawable getIcon(int density) {
// TODO: Go through LauncherAppsService
final int iconRes = mActivityInfo.getIconResource();
Drawable icon = null;
// Get the preferred density icon from the app's resources
Expand Down Expand Up @@ -144,8 +146,9 @@ public ApplicationInfo getApplicationInfo() {
*/
public long getFirstInstallTime() {
try {
// TODO: Go through LauncherAppsService
return mPm.getPackageInfo(mActivityInfo.packageName,
PackageManager.GET_UNINSTALLED_PACKAGES).firstInstallTime;
PackageManager.MATCH_UNINSTALLED_PACKAGES).firstInstallTime;
} catch (NameNotFoundException nnfe) {
// Sorry, can't find package
return 0;
Expand All @@ -171,6 +174,7 @@ public Drawable getBadgedIcon(int density) {
Drawable originalIcon = getIcon(density);

if (originalIcon instanceof BitmapDrawable) {
// TODO: Go through LauncherAppsService
return mPm.getUserBadgedIcon(originalIcon, mUser);
} else {
Log.e(TAG, "Unable to create badged icon for " + mActivityInfo);
Expand Down
4 changes: 2 additions & 2 deletions core/java/android/content/pm/LauncherApps.java
Original file line number Diff line number Diff line change
Expand Up @@ -447,12 +447,12 @@ public boolean isPackageEnabled(String packageName, UserHandle user) {
/**
* Retrieve all of the information we know about a particular package / application.
*
* @param packageName The package of the application
* @param packageName The package name of the application
* @param flags Additional option flags {@link PackageManager#getApplicationInfo}
* @param user The UserHandle of the profile.
*
* @return An {@link ApplicationInfo} containing information about the package or
* null of the package isn't found.
* null if the package isn't installed for the given user.
* @hide
*/
public ApplicationInfo getApplicationInfo(String packageName, @ApplicationInfoFlags int flags,
Expand Down
14 changes: 14 additions & 0 deletions core/java/android/content/pm/PackageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,20 @@ public interface OnPermissionsChangedListener {
*/
public static final int MATCH_FACTORY_ONLY = 0x00200000;

/**
* Allows querying of packages installed for any user, not just the specific one. This flag
* is only meant for use by apps that have INTERACT_ACROSS_USERS_FULL permission.
* @hide
*/
public static final int MATCH_ANY_USER = 0x00400000;

/**
* Combination of MATCH_ANY_USER and MATCH_UNINSTALLED_PACKAGES to mean any known
* package.
* @hide
*/
public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;

/**
* Internal flag used to indicate that a system component has done their
* homework and verified that they correctly handle packages and components
Expand Down
27 changes: 16 additions & 11 deletions core/java/android/content/pm/PackageParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -478,20 +478,25 @@ public static PackageInfo generatePackageInfo(PackageParser.Package p,
/**
* Returns true if the package is installed and not hidden, or if the caller
* explicitly wanted all uninstalled and hidden packages as well.
* @param appInfo The applicationInfo of the app being checked.
*/
private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
return (state.installed && !state.hidden)
|| (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
ApplicationInfo appInfo) {
// If available for the target user, or trying to match uninstalled packages and it's
// a system app.
return state.isAvailable(flags)
|| (appInfo != null && appInfo.isSystemApp()
&& (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
}

public static boolean isAvailable(PackageUserState state) {
return checkUseInstalledOrHidden(0, state);
return checkUseInstalledOrHidden(0, state, null);
}

public static PackageInfo generatePackageInfo(PackageParser.Package p,
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Set<String> grantedPermissions, PackageUserState state, int userId) {
if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
return null;
}
PackageInfo pi = new PackageInfo();
Expand Down Expand Up @@ -5445,7 +5450,7 @@ private static void updateApplicationInfo(ApplicationInfo ai, int flags,
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
PackageUserState state, int userId) {
if (p == null) return null;
if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
return null;
}
if (!copyNeeded(flags, p, state, null, userId)
Expand Down Expand Up @@ -5483,7 +5488,7 @@ public static ApplicationInfo generateApplicationInfo(Package p, int flags,
public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
PackageUserState state, int userId) {
if (ai == null) return null;
if (!checkUseInstalledOrHidden(flags, state)) {
if (!checkUseInstalledOrHidden(flags, state, ai)) {
return null;
}
// This is only used to return the ResolverActivity; we will just always
Expand Down Expand Up @@ -5549,7 +5554,7 @@ public String toString() {
public static final ActivityInfo generateActivityInfo(Activity a, int flags,
PackageUserState state, int userId) {
if (a == null) return null;
if (!checkUseInstalledOrHidden(flags, state)) {
if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
return null;
}
if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Expand All @@ -5565,7 +5570,7 @@ public static final ActivityInfo generateActivityInfo(Activity a, int flags,
public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
PackageUserState state, int userId) {
if (ai == null) return null;
if (!checkUseInstalledOrHidden(flags, state)) {
if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
return null;
}
// This is only used to return the ResolverActivity; we will just always
Expand Down Expand Up @@ -5603,7 +5608,7 @@ public String toString() {
public static final ServiceInfo generateServiceInfo(Service s, int flags,
PackageUserState state, int userId) {
if (s == null) return null;
if (!checkUseInstalledOrHidden(flags, state)) {
if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
return null;
}
if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Expand Down Expand Up @@ -5652,7 +5657,7 @@ public String toString() {
public static final ProviderInfo generateProviderInfo(Provider p, int flags,
PackageUserState state, int userId) {
if (p == null) return null;
if (!checkUseInstalledOrHidden(flags, state)) {
if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
return null;
}
if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
Expand Down
19 changes: 13 additions & 6 deletions core/java/android/content/pm/PackageUserState.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

import android.util.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

/**
Expand Down Expand Up @@ -80,9 +79,14 @@ public PackageUserState(PackageUserState o) {
/**
* Test if this package is installed.
*/
public boolean isInstalled(int flags) {
return (this.installed && !this.hidden)
|| (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
public boolean isAvailable(int flags) {
// True if it is installed for this user and it is not hidden. If it is hidden,
// still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
return matchAnyUser
|| (this.installed
&& (!this.hidden || matchUninstalled));
}

/**
Expand All @@ -95,11 +99,14 @@ public boolean isInstalled(int flags) {
* </p>
*/
public boolean isMatch(ComponentInfo componentInfo, int flags) {
if (!isInstalled(flags)) return false;
final boolean isSystemApp = componentInfo.applicationInfo.isSystemApp();
final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
if (!isAvailable(flags)
&& !(isSystemApp && matchUninstalled)) return false;
if (!isEnabled(componentInfo, flags)) return false;

if ((flags & MATCH_SYSTEM_ONLY) != 0) {
if (!componentInfo.applicationInfo.isSystemApp()) {
if (!isSystemApp) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,8 @@ public Context getPackageContext(Context context) {
if (mContext == null) {
try {
ApplicationInfo ai = context.getPackageManager()
.getApplicationInfo(pkg, PackageManager.GET_UNINSTALLED_PACKAGES);
.getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES,
getUserId());
mContext = context.createApplicationContext(ai,
Context.CONTEXT_RESTRICTED);
} catch (PackageManager.NameNotFoundException e) {
Expand Down
4 changes: 2 additions & 2 deletions core/java/com/android/internal/content/PackageHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ public static String resolveInstallVolume(Context context, String packageName,
ApplicationInfo existingInfo = null;
try {
existingInfo = context.getPackageManager().getApplicationInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
PackageManager.MATCH_ANY_USER);
} catch (NameNotFoundException ignored) {
}

Expand Down Expand Up @@ -445,7 +445,7 @@ public static int resolveInstallLocation(Context context, String packageName,
ApplicationInfo existingInfo = null;
try {
existingInfo = context.getPackageManager().getApplicationInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
PackageManager.MATCH_ANY_USER);
} catch (NameNotFoundException ignored) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ private void assertPermissions(String[] cmds) {
try {
pkgInfo = pm.getPackageInfo(pkg,
PackageManager.GET_PERMISSIONS
| PackageManager.GET_UNINSTALLED_PACKAGES);
| PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException e) {
pkgInfo = null;
}
Expand Down Expand Up @@ -712,7 +712,7 @@ private void installFromRawResource(InstallParams ip, int flags, boolean cleanUp
// Make sure the package doesn't exist
try {
ApplicationInfo appInfo = pm.getApplicationInfo(pkg.packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
PackageManager.MATCH_UNINSTALLED_PACKAGES);
GenericReceiver receiver = new DeleteReceiver(pkg.packageName);
invokeDeletePackage(pkg.packageName, 0, receiver);
} catch (NameNotFoundException e) {
Expand Down Expand Up @@ -974,7 +974,7 @@ public boolean notifyNow(Intent intent) {
public boolean invokeDeletePackage(final String pkgName, int flags, GenericReceiver receiver)
throws Exception {
ApplicationInfo info = getPm().getApplicationInfo(pkgName,
PackageManager.GET_UNINSTALLED_PACKAGES);
PackageManager.MATCH_UNINSTALLED_PACKAGES);

mContext.registerReceiver(receiver, receiver.filter);
try {
Expand Down Expand Up @@ -1019,7 +1019,7 @@ public void deleteFromRawResource(int iFlags, int dFlags) throws Exception {
Log.i(TAG, "okay4");
try {
info = getPm().getApplicationInfo(ip.pkg.packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException e) {
info = null;
}
Expand Down Expand Up @@ -1323,7 +1323,7 @@ void cleanUpInstall(InstallParams ip) throws Exception {

ApplicationInfo info = null;
try {
info = getPm().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
info = getPm().getApplicationInfo(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException ignored) {
}

Expand All @@ -1350,7 +1350,7 @@ private void cleanUpInstall(String pkgName) throws Exception {
Log.i(TAG, "Deleting package : " + pkgName);
try {
ApplicationInfo info = getPm().getApplicationInfo(pkgName,
PackageManager.GET_UNINSTALLED_PACKAGES);
PackageManager.MATCH_UNINSTALLED_PACKAGES);

if (info != null) {
DeleteObserver observer = new DeleteObserver(pkgName);
Expand Down Expand Up @@ -3756,7 +3756,7 @@ public void testGetInstalledPackages() throws Exception {

public void testGetUnInstalledPackages() throws Exception {
List<PackageInfo> packages = getPm().getInstalledPackages(
PackageManager.GET_UNINSTALLED_PACKAGES);
PackageManager.MATCH_UNINSTALLED_PACKAGES);
assertNotNull("installed packages cannot be null", packages);
assertTrue("installed packages cannot be empty", packages.size() > 0);
}
Expand All @@ -3769,7 +3769,7 @@ public void testGetInstalledPackagesAll() throws Exception {
| PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
| PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
| PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
| PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
| PackageManager.GET_SIGNATURES | PackageManager.MATCH_UNINSTALLED_PACKAGES;

final InstallParams ip =
installFromRawResource("install.apk", R.raw.install_complete_package_info,
Expand Down Expand Up @@ -3809,12 +3809,12 @@ public void testGetInstalledPackagesAll() throws Exception {
* flags when the GET_UNINSTALLED_PACKAGES flag is set.
*/
public void testGetUnInstalledPackagesAll() throws Exception {
final int flags = PackageManager.GET_UNINSTALLED_PACKAGES
final int flags = PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
| PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
| PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
| PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
| PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
| PackageManager.GET_SIGNATURES;

// first, install the package
final InstallParams ip =
Expand Down
2 changes: 1 addition & 1 deletion graphics/java/android/graphics/drawable/Icon.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ private Drawable loadDrawableInner(Context context) {
final PackageManager pm = context.getPackageManager();
try {
ApplicationInfo ai = pm.getApplicationInfo(
resPackage, PackageManager.GET_UNINSTALLED_PACKAGES);
resPackage, PackageManager.MATCH_UNINSTALLED_PACKAGES);
if (ai != null) {
mObj1 = pm.getResourcesForApplication(ai);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,11 @@ private ApplicationsState(Application app) {
mBackgroundHandler = new BackgroundHandler(mThread.getLooper());

// Only the owner can see all apps.
mAdminRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |
PackageManager.GET_DISABLED_COMPONENTS |
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
mRetrieveFlags = PackageManager.GET_DISABLED_COMPONENTS |
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
mAdminRetrieveFlags = PackageManager.MATCH_ANY_USER |
PackageManager.MATCH_DISABLED_COMPONENTS |
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
mRetrieveFlags = PackageManager.MATCH_DISABLED_COMPONENTS |
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;

/**
* This is a trick to prevent the foreground thread from being delayed.
Expand Down Expand Up @@ -855,7 +855,7 @@ public void handleMessage(Message msg) {
// explicitly include both direct boot aware and unaware components here.
List<ResolveInfo> intents = mPm.queryIntentActivitiesAsUser(
launchIntent,
PackageManager.GET_DISABLED_COMPONENTS
PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ private void measureExactStorage(IMediaContainerService imcs) {
// Measure all apps hosted on this volume for all users
if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
final List<ApplicationInfo> apps = packageManager.getInstalledApplications(
PackageManager.GET_UNINSTALLED_PACKAGES
| PackageManager.GET_DISABLED_COMPONENTS);
PackageManager.MATCH_ANY_USER
| PackageManager.MATCH_DISABLED_COMPONENTS);

final List<ApplicationInfo> volumeApps = new ArrayList<>();
for (ApplicationInfo app : apps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public void applyUserAppState(String packageName, boolean enabled,
// Enable selected apps
try {
ApplicationInfo info = mIPm.getApplicationInfo(packageName,
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
PackageManager.MATCH_ANY_USER, userId);
if (info == null || !info.enabled
|| (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier());
Expand Down Expand Up @@ -178,7 +178,7 @@ public void fetchAndMergeApps() {
addSystemApps(mVisibleApps, widgetIntent, excludePackages);

List<ApplicationInfo> installedApps = pm.getInstalledApplications(
PackageManager.MATCH_UNINSTALLED_PACKAGES);
PackageManager.MATCH_ANY_USER);
for (ApplicationInfo app : installedApps) {
// If it's not installed, skip
if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue;
Expand Down
Loading

0 comments on commit 0d1fd8d

Please sign in to comment.