diff options
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/app/ApplicationPackageManager.java | 22 | ||||
| -rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 9 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 38 | ||||
| -rw-r--r-- | services/java/com/android/server/AppOpsService.java | 1 | ||||
| -rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 68 | ||||
| -rw-r--r-- | test-runner/src/android/test/mock/MockPackageManager.java | 6 |
7 files changed, 143 insertions, 3 deletions
diff --git a/api/current.txt b/api/current.txt index 71b6b14f776a..ac367f657d64 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6592,6 +6592,7 @@ package android.content.pm { method public abstract int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract java.lang.String[] getPackagesForUid(int); + method public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int); method public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String); @@ -21689,6 +21690,7 @@ package android.test.mock { method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public java.lang.String[] getPackagesForUid(int); + method public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int); method public android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 03d1a3f3fec3..2ef39443e5e9 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -444,6 +444,28 @@ final class ApplicationPackageManager extends PackageManager { @SuppressWarnings("unchecked") @Override + public List<PackageInfo> getPackagesHoldingPermissions( + String[] permissions, int flags) { + final int userId = mContext.getUserId(); + try { + final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); + PackageInfo lastItem = null; + ParceledListSlice<PackageInfo> slice; + + do { + final String lastKey = lastItem != null ? lastItem.packageName : null; + slice = mPM.getPackagesHoldingPermissions(permissions, flags, lastKey, userId); + lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); + } while (!slice.isLastSlice()); + + return packageInfos; + } catch (RemoteException e) { + throw new RuntimeException("Package manager has died", e); + } + } + + @SuppressWarnings("unchecked") + @Override public List<ApplicationInfo> getInstalledApplications(int flags) { final int userId = mContext.getUserId(); try { diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index b9e432c120fb..4c9c278a718e 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -130,6 +130,15 @@ interface IPackageManager { ParceledListSlice getInstalledPackages(int flags, in String lastRead, in int userId); /** + * This implements getPackagesHoldingPermissions via a "last returned row" + * mechanism that is not exposed in the API. This is to get around the IPC + * limit that kicks in when flags are included that bloat up the data + * returned. + */ + ParceledListSlice getPackagesHoldingPermissions(in String[] permissions, + int flags, in String lastRead, int userId); + + /** * This implements getInstalledApplications via a "last returned row" * mechanism that is not exposed in the API. This is to get around the IPC * limit that kicks in when flags are included that bloat up the data diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index cdd91951387c..a69f2202ca28 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1512,11 +1512,43 @@ public abstract class PackageManager { * @see #GET_SERVICES * @see #GET_SIGNATURES * @see #GET_UNINSTALLED_PACKAGES - * */ public abstract List<PackageInfo> getInstalledPackages(int flags); /** + * Return a List of all installed packages that are currently + * holding any of the given permissions. + * + * @param flags Additional option flags. Use any combination of + * {@link #GET_ACTIVITIES}, + * {@link #GET_GIDS}, + * {@link #GET_CONFIGURATIONS}, + * {@link #GET_INSTRUMENTATION}, + * {@link #GET_PERMISSIONS}, + * {@link #GET_PROVIDERS}, + * {@link #GET_RECEIVERS}, + * {@link #GET_SERVICES}, + * {@link #GET_SIGNATURES}, + * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. + * + * @return Returns a List of PackageInfo objects, one for each installed + * application that is holding any of the permissions that were provided. + * + * @see #GET_ACTIVITIES + * @see #GET_GIDS + * @see #GET_CONFIGURATIONS + * @see #GET_INSTRUMENTATION + * @see #GET_PERMISSIONS + * @see #GET_PROVIDERS + * @see #GET_RECEIVERS + * @see #GET_SERVICES + * @see #GET_SIGNATURES + * @see #GET_UNINSTALLED_PACKAGES + */ + public abstract List<PackageInfo> getPackagesHoldingPermissions( + String[] permissions, int flags); + + /** * Return a List of all packages that are installed on the device, for a specific user. * Requesting a list of installed packages for another user * will require the permission INTERACT_ACROSS_USERS_FULL. @@ -1742,14 +1774,14 @@ public abstract class PackageManager { /** * Return a List of all application packages that are installed on the * device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all - * applications including those deleted with DONT_DELETE_DATA(partially + * applications including those deleted with DONT_DELETE_DATA (partially * installed apps with data directory) will be returned. * * @param flags Additional option flags. Use any combination of * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. * - * @return A List of ApplicationInfo objects, one for each application that + * @return Returns a List of ApplicationInfo objects, one for each application that * is installed on the device. In the unlikely case of there being * no installed applications, an empty list is returned. * If flag GET_UNINSTALLED_PACKAGES is set, a list of all diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java index aff994c14732..17128062b0a1 100644 --- a/services/java/com/android/server/AppOpsService.java +++ b/services/java/com/android/server/AppOpsService.java @@ -233,6 +233,7 @@ public class AppOpsService extends IAppOpsService.Stub { + " code " + code + " time=" + op.time + " duration=" + op.duration + " nesting=" + op.nesting); } + op.nesting = 0; } else { op.nesting--; } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 9a925d66ed66..9b3795a073ea 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -2944,6 +2944,74 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override + public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions( + String[] permissions, int flags, String lastRead, int userId) { + if (!sUserManager.exists(userId)) return null; + final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>(); + final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; + + // writer + synchronized (mPackages) { + ArrayList<String> keysList = new ArrayList<String>(); + if (listUninstalled) { + for (PackageSetting ps : mSettings.mPackages.values()) { + for (String perm : permissions) { + if (ps.grantedPermissions.contains(perm)) { + keysList.add(ps.name); + break; + } + } + } + } else { + for (PackageParser.Package pkg : mPackages.values()) { + PackageSetting ps = (PackageSetting)pkg.mExtras; + if (ps != null) { + for (String perm : permissions) { + if (ps.grantedPermissions.contains(perm)) { + keysList.add(ps.name); + break; + } + } + } + } + } + + String[] keys = new String[keysList.size()]; + keysList.toArray(keys); + Arrays.sort(keys); + int i = getContinuationPoint(keys, lastRead); + final int N = keys.length; + + while (i < N) { + final String packageName = keys[i++]; + + PackageInfo pi = null; + if (listUninstalled) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId); + } + } else { + final PackageParser.Package p = mPackages.get(packageName); + if (p != null) { + pi = generatePackageInfo(p, flags, userId); + } + } + + if (pi != null && list.append(pi)) { + break; + } + } + + if (i == N) { + list.setLastSlice(true); + } + } + + return list; + } + + @Override public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, String lastRead, int userId) { if (!sUserManager.exists(userId)) return null; diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 5ee52de0a32d..20a26ab86a01 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -146,6 +146,12 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } + @Override + public List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, + int flags) { + throw new UnsupportedOperationException(); + } + /** @hide */ @Override public List<PackageInfo> getInstalledPackages(int flags, int userId) { |