Move mPermissionTrees to permission settings
Move more state / logic into the permission sub-package. We're
close to being able to wholesale move large amounts of code from
package manager into the permission manager.
Bug: 63539144
Test: Manual. Builds and runs
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.PermissionsHostTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsPermissionTestCases
Test: cts-tradefed run commandAndExit cts-dev -m CtsPermission2TestCases
Test: bit FrameworksServicesTests:com.android.server.pm.PackageManagerSettingsTests
Change-Id: Id292441ff22b14665fd77f700ad934bf2c5a3357
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index be7f921..143c51d 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -467,6 +467,7 @@
/** Updates the flags for the given permission. */
public abstract void updatePermissionFlagsTEMP(@NonNull String permName,
@NonNull String packageName, int flagMask, int flagValues, int userId);
- /** temporary until mPermissionTrees is moved to PermissionManager */
- public abstract Object enforcePermissionTreeTEMP(@NonNull String permName, int callingUid);
+ /** Returns a PermissionGroup. */
+ public abstract @Nullable PackageParser.PermissionGroup getPermissionGroupTEMP(
+ @NonNull String groupName);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 6c7c8a07..ec48ac5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6849,6 +6849,11 @@
dest.writeParcelable(group, flags);
}
+ /** @hide */
+ public boolean isAppOp() {
+ return info.isAppOp();
+ }
+
private Permission(Parcel in) {
super(in);
final ClassLoader boot = Object.class.getClassLoader();
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index b45c26c..5dd7aed 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -353,6 +353,11 @@
return size;
}
+ /** @hide */
+ public boolean isAppOp() {
+ return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
+ }
+
public static final Creator<PermissionInfo> CREATOR =
new Creator<PermissionInfo>() {
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0c1d4c1..60764a7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -397,7 +397,7 @@
static final boolean DEBUG_DOMAIN_VERIFICATION = false;
private static final boolean DEBUG_BACKUP = false;
private static final boolean DEBUG_INSTALL = false;
- private static final boolean DEBUG_REMOVE = false;
+ public static final boolean DEBUG_REMOVE = false;
private static final boolean DEBUG_BROADCASTS = false;
private static final boolean DEBUG_SHOW_INFO = false;
private static final boolean DEBUG_PACKAGE_INFO = false;
@@ -405,7 +405,7 @@
public static final boolean DEBUG_PACKAGE_SCANNING = false;
private static final boolean DEBUG_VERIFY = false;
private static final boolean DEBUG_FILTERS = false;
- private static final boolean DEBUG_PERMISSIONS = false;
+ public static final boolean DEBUG_PERMISSIONS = false;
private static final boolean DEBUG_SHARED_LIBRARIES = false;
private static final boolean DEBUG_COMPRESSION = Build.IS_DEBUGGABLE;
@@ -953,9 +953,6 @@
final SparseArray<PackageVerificationState> mPendingVerification
= new SparseArray<PackageVerificationState>();
- /** Set of packages associated with each app op permission. */
- final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
-
final PackageInstallerService mInstallerService;
private final PackageDexOptimizer mPackageDexOptimizer;
@@ -2880,7 +2877,7 @@
+ mSdkVersion + "; regranting permissions for internal storage");
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
- updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
+ updatePermissionsLocked(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;
// If this is the first boot or an update from pre-M, and it is a normal
@@ -5181,7 +5178,7 @@
final PermissionsState permissionsState = settingBase.getPermissionsState();
if (permissionsState.hasPermission(permName, userId)) {
if (isUidInstantApp) {
- if (mPermissionManager.isPermissionInstant(permName)) {
+ if (mSettings.mPermissions.isPermissionInstant(permName)) {
return PackageManager.PERMISSION_GRANTED;
}
} else {
@@ -5250,8 +5247,8 @@
}
}
- boolean addPermission(PermissionInfo info, final boolean async) {
- return mPermissionManager.addPermission(
+ private boolean addDynamicPermission(PermissionInfo info, final boolean async) {
+ return mPermissionManager.addDynamicPermission(
info, async, getCallingUid(), new PermissionCallback() {
@Override
public void onPermissionChanged() {
@@ -5267,20 +5264,20 @@
@Override
public boolean addPermission(PermissionInfo info) {
synchronized (mPackages) {
- return addPermission(info, false);
+ return addDynamicPermission(info, false);
}
}
@Override
public boolean addPermissionAsync(PermissionInfo info) {
synchronized (mPackages) {
- return addPermission(info, true);
+ return addDynamicPermission(info, true);
}
}
@Override
public void removePermission(String permName) {
- mPermissionManager.removePermission(permName, getCallingUid(), mPermissionCallback);
+ mPermissionManager.removeDynamicPermission(permName, getCallingUid(), mPermissionCallback);
}
@Override
@@ -5941,17 +5938,8 @@
}
@Override
- public String[] getAppOpPermissionPackages(String permissionName) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
- return null;
- }
- synchronized (mPackages) {
- ArraySet<String> pkgs = mAppOpPermissionPackages.get(permissionName);
- if (pkgs == null) {
- return null;
- }
- return pkgs.toArray(new String[pkgs.size()]);
- }
+ public String[] getAppOpPermissionPackages(String permName) {
+ return mPermissionManager.getAppOpPermissionPackages(permName);
}
@Override
@@ -10339,7 +10327,7 @@
Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ pkg.packageName);
// SIDE EFFECTS; updates permissions system state; move elsewhere
- mSettings.transferPermissionsLPw(origName, pkg.packageName);
+ mSettings.mPermissions.transferPermissions(origName, pkg.packageName);
}
}
}
@@ -11187,54 +11175,13 @@
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
}
- N = pkg.permissions.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Permission p = pkg.permissions.get(i);
- // Dont allow ephemeral apps to define new permissions.
- if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
- Slog.w(TAG, "Permission " + p.info.name + " from package "
- + p.info.packageName
- + " ignored: instant apps cannot define new permissions.");
- continue;
- }
-
- // Assume by default that we did not install this permission into the system.
- p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
-
- // Now that permission groups have a special meaning, we ignore permission
- // groups for legacy apps to prevent unexpected behavior. In particular,
- // permissions for one app being granted to someone just because they happen
- // to be in a group defined by another app (before this had no implications).
- if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
- p.group = mPermissionGroups.get(p.info.group);
- // Warn for a permission in an unknown group.
- if (DEBUG_PERMISSIONS && p.info.group != null && p.group == null) {
- Slog.i(TAG, "Permission " + p.info.name + " from package "
- + p.info.packageName + " in an unknown group " + p.info.group);
- }
- }
-
- // TODO Move to PermissionManager once mPermissionTrees moves there.
-// p.tree ? mSettings.mPermissionTrees
-// : mSettings.mPermissions;
-// final BasePermission bp = BasePermission.createOrUpdate(
-// permissionMap.get(p.info.name), p, pkg, mSettings.mPermissionTrees, chatty);
-// permissionMap.put(p.info.name, bp);
- if (p.tree) {
- final ArrayMap<String, BasePermission> permissionMap =
- mSettings.mPermissionTrees;
- final BasePermission bp = BasePermission.createOrUpdate(
- permissionMap.get(p.info.name), p, pkg, mSettings.mPermissionTrees,
- chatty);
- permissionMap.put(p.info.name, bp);
- } else {
- final BasePermission bp = BasePermission.createOrUpdate(
- (BasePermission) mPermissionManager.getPermissionTEMP(p.info.name),
- p, pkg, mSettings.mPermissionTrees, chatty);
- mPermissionManager.putPermissionTEMP(p.info.name, bp);
- }
+ // Dont allow ephemeral apps to define new permissions.
+ if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
+ Slog.w(TAG, "Permissions from package " + pkg.packageName
+ + " ignored: instant apps cannot define new permissions.");
+ } else {
+ mPermissionManager.addAllPermissions(pkg, chatty);
}
N = pkg.instrumentation.size();
@@ -11960,53 +11907,7 @@
if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
}
- N = pkg.permissions.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Permission p = pkg.permissions.get(i);
- BasePermission bp = (BasePermission) mPermissionManager.getPermissionTEMP(p.info.name);
- if (bp == null) {
- bp = mSettings.mPermissionTrees.get(p.info.name);
- }
- if (bp != null && bp.isPermission(p)) {
- bp.setPermission(null);
- if (DEBUG_REMOVE && chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(p.info.name);
- }
- }
- if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
- ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(p.info.name);
- if (appOpPkgs != null) {
- appOpPkgs.remove(pkg.packageName);
- }
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
- }
-
- N = pkg.requestedPermissions.size();
- r = null;
- for (i=0; i<N; i++) {
- String perm = pkg.requestedPermissions.get(i);
- if (mPermissionManager.isPermissionAppOp(perm)) {
- ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(perm);
- if (appOpPkgs != null) {
- appOpPkgs.remove(pkg.packageName);
- if (appOpPkgs.isEmpty()) {
- mAppOpPermissionPackages.remove(perm);
- }
- }
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
- }
+ mPermissionManager.removeAllPermissions(pkg, chatty);
N = pkg.instrumentation.size();
r = null;
@@ -12067,18 +11968,9 @@
}
}
- private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
- for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
- if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
- return true;
- }
- }
- return false;
- }
-
- static final int UPDATE_PERMISSIONS_ALL = 1<<0;
- static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
- static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
+ public static final int UPDATE_PERMISSIONS_ALL = 1<<0;
+ public static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
+ public static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
private void updatePermissionsLPw(PackageParser.Package pkg, int flags) {
// Update the parent permissions
@@ -12094,10 +11986,10 @@
private void updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo,
int flags) {
final String volumeUuid = (pkgInfo != null) ? getVolumeUuidForPackage(pkgInfo) : null;
- updatePermissionsLPw(changingPkg, pkgInfo, volumeUuid, flags);
+ updatePermissionsLocked(changingPkg, pkgInfo, volumeUuid, flags);
}
- private void updatePermissionsLPw(String changingPkg,
+ private void updatePermissionsLocked(String changingPkg,
PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags) {
// TODO: Most of the methods exposing BasePermission internals [source package name,
// etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
@@ -12109,55 +12001,11 @@
// normal permissions. Today, we need two separate loops because these BasePermission
// objects are stored separately.
// Make sure there are no dangling permission trees.
- Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
- while (it.hasNext()) {
- final BasePermission bp = it.next();
- if (bp.getSourcePackageSetting() == null) {
- // We may not yet have parsed the package, so just see if
- // we still know about its settings.
- bp.setSourcePackageSetting(mSettings.mPackages.get(bp.getSourcePackageName()));
- }
- if (bp.getSourcePackageSetting() == null) {
- Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- it.remove();
- } else if (changingPkg != null && changingPkg.equals(bp.getSourcePackageName())) {
- if (pkgInfo == null || !hasPermission(pkgInfo, bp.getName())) {
- Slog.i(TAG, "Removing old permission tree: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- flags |= UPDATE_PERMISSIONS_ALL;
- it.remove();
- }
- }
- }
+ flags = mPermissionManager.updatePermissionTrees(changingPkg, pkgInfo, flags);
// Make sure all dynamic permissions have been assigned to a package,
// and make sure there are no dangling permissions.
- final Iterator<BasePermission> permissionIter =
- mPermissionManager.getPermissionIteratorTEMP();
- while (permissionIter.hasNext()) {
- final BasePermission bp = permissionIter.next();
- if (bp.isDynamic()) {
- bp.updateDynamicPermission(mSettings.mPermissionTrees);
- }
- if (bp.getSourcePackageSetting() == null) {
- // We may not yet have parsed the package, so just see if
- // we still know about its settings.
- bp.setSourcePackageSetting(mSettings.mPackages.get(bp.getSourcePackageName()));
- }
- if (bp.getSourcePackageSetting() == null) {
- Slog.w(TAG, "Removing dangling permission: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- permissionIter.remove();
- } else if (changingPkg != null && changingPkg.equals(bp.getSourcePackageName())) {
- if (pkgInfo == null || !hasPermission(pkgInfo, bp.getName())) {
- Slog.i(TAG, "Removing old permission: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- flags |= UPDATE_PERMISSIONS_ALL;
- permissionIter.remove();
- }
- }
- }
+ flags = mPermissionManager.updatePermissions(changingPkg, pkgInfo, flags);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
// Now update the permissions for all packages, in particular
@@ -12279,12 +12127,7 @@
// Keep track of app op permissions.
if (bp.isAppOp()) {
- ArraySet<String> pkgs = mAppOpPermissionPackages.get(perm);
- if (pkgs == null) {
- pkgs = new ArraySet<>();
- mAppOpPermissionPackages.put(perm, pkgs);
- }
- pkgs.add(pkg.packageName);
+ mSettings.addAppOpPackage(perm, pkg.packageName);
}
if (bp.isNormal()) {
@@ -21227,7 +21070,7 @@
// permissions, ensure permissions are updated. Beware of dragons if you
// try optimizing this.
synchronized (mPackages) {
- updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL,
+ updatePermissionsLocked(null, null, StorageManager.UUID_PRIVATE_INTERNAL,
UPDATE_PERMISSIONS_ALL);
}
@@ -21773,22 +21616,6 @@
if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
mSettings.dumpPermissionsLPr(pw, packageName, permissionNames, dumpState);
- if (packageName == null && permissionNames == null) {
- for (int iperm=0; iperm<mAppOpPermissionPackages.size(); iperm++) {
- if (iperm == 0) {
- if (dumpState.onTitlePrinted())
- pw.println();
- pw.println("AppOp Permissions:");
- }
- pw.print(" AppOp Permission ");
- pw.print(mAppOpPermissionPackages.keyAt(iperm));
- pw.println(":");
- ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
- for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
- pw.print(" "); pw.println(pkgs.valueAt(ipkg));
- }
- }
- }
}
if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
@@ -22292,7 +22119,7 @@
+ mSdkVersion + "; regranting permissions for " + volumeUuid);
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
- updatePermissionsLPw(null, null, volumeUuid, updateFlags);
+ updatePermissionsLocked(null, null, volumeUuid, updateFlags);
// Yay, everything is now upgraded
ver.forceCurrent();
@@ -23300,15 +23127,15 @@
void onNewUserCreated(final int userId) {
synchronized(mPackages) {
mDefaultPermissionPolicy.grantDefaultPermissions(mPackages.values(), userId);
- }
- // If permission review for legacy apps is required, we represent
- // dagerous permissions for such apps as always granted runtime
- // permissions to keep per user flag state whether review is needed.
- // Hence, if a new user is added we have to propagate dangerous
- // permission grants for these legacy apps.
- if (mPermissionReviewRequired) {
- updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
- | UPDATE_PERMISSIONS_REPLACE_ALL);
+ // If permission review for legacy apps is required, we represent
+ // dagerous permissions for such apps as always granted runtime
+ // permissions to keep per user flag state whether review is needed.
+ // Hence, if a new user is added we have to propagate dangerous
+ // permission grants for these legacy apps.
+ if (mPermissionReviewRequired) {
+ updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
+ | UPDATE_PERMISSIONS_REPLACE_ALL);
+ }
}
}
@@ -23752,12 +23579,12 @@
}
@Override
- public Object enforcePermissionTreeTEMP(String permName, int callingUid) {
+ public PackageParser.PermissionGroup getPermissionGroupTEMP(String groupName) {
synchronized (mPackages) {
- return BasePermission.enforcePermissionTreeLP(
- mSettings.mPermissionTrees, permName, callingUid);
+ return mPermissionGroups.get(groupName);
}
}
+
@Override
public boolean isInstantApp(String packageName, int userId) {
return PackageManagerService.this.isInstantApp(packageName, userId);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0084411..56595c9 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -378,10 +378,6 @@
private final ArrayMap<Long, Integer> mKeySetRefs =
new ArrayMap<Long, Integer>();
- // Mapping from permission tree names to info about them.
- final ArrayMap<String, BasePermission> mPermissionTrees =
- new ArrayMap<String, BasePermission>();
-
// Packages that have been uninstalled and still need their external
// storage data deleted.
final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
@@ -416,7 +412,7 @@
public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
/** Settings and other information about permissions */
- private final PermissionSettings mPermissions;
+ final PermissionSettings mPermissions;
Settings(PermissionSettings permissions, Object lock) {
this(Environment.getDataDirectory(), permissions, lock);
@@ -622,6 +618,10 @@
return null;
}
+ void addAppOpPackage(String permName, String packageName) {
+ mPermissions.addAppOpPackage(permName, packageName);
+ }
+
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
SharedUserSetting s = mSharedUsers.get(name);
if (s != null) {
@@ -666,13 +666,6 @@
}
/**
- * Transfers ownership of permissions from one package to another.
- */
- void transferPermissionsLPw(String origPackageName, String newPackageName) {
- mPermissions.transferPermissions(origPackageName, newPackageName, mPermissionTrees);
- }
-
- /**
* Creates a new {@code PackageSetting} object.
* Use this method instead of the constructor to ensure a settings object is created
* with the correct base.
@@ -2496,9 +2489,7 @@
}
serializer.startTag(null, "permission-trees");
- for (BasePermission bp : mPermissionTrees.values()) {
- writePermissionLPr(serializer, bp);
- }
+ mPermissions.writePermissionTrees(serializer);
serializer.endTag(null, "permission-trees");
serializer.startTag(null, "permissions");
@@ -3042,7 +3033,7 @@
} else if (tagName.equals("permissions")) {
mPermissions.readPermissions(parser);
} else if (tagName.equals("permission-trees")) {
- PermissionSettings.readPermissions(mPermissionTrees, parser);
+ mPermissions.readPermissionTrees(parser);
} else if (tagName.equals("shared-user")) {
readSharedUserLPw(parser);
} else if (tagName.equals("preferred-packages")) {
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 09a6e9c..71d3202 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -48,6 +48,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -77,7 +78,7 @@
final String name;
- @PermissionType final int type;
+ final @PermissionType int type;
String sourcePackageName;
@@ -252,12 +253,12 @@
return changed;
}
- public void updateDynamicPermission(Map<String, BasePermission> permissionTrees) {
+ public void updateDynamicPermission(Collection<BasePermission> permissionTrees) {
if (PackageManagerService.DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
+ getName() + " pkg=" + getSourcePackageName()
+ " info=" + pendingPermissionInfo);
if (sourcePackageSetting == null && pendingPermissionInfo != null) {
- final BasePermission tree = findPermissionTreeLP(permissionTrees, name);
+ final BasePermission tree = findPermissionTree(permissionTrees, name);
if (tree != null && tree.perm != null) {
sourcePackageSetting = tree.sourcePackageSetting;
perm = new PackageParser.Permission(tree.perm.owner,
@@ -269,8 +270,8 @@
}
}
- public static BasePermission createOrUpdate(@Nullable BasePermission bp, @NonNull Permission p,
- @NonNull PackageParser.Package pkg, Map<String, BasePermission> permissionTrees,
+ static BasePermission createOrUpdate(@Nullable BasePermission bp, @NonNull Permission p,
+ @NonNull PackageParser.Package pkg, Collection<BasePermission> permissionTrees,
boolean chatty) {
final PackageSettingBase pkgSetting = (PackageSettingBase) pkg.mExtras;
// Allow system apps to redefine non-system permissions
@@ -300,7 +301,7 @@
if (bp.perm == null) {
if (bp.sourcePackageName == null
|| bp.sourcePackageName.equals(p.info.packageName)) {
- final BasePermission tree = findPermissionTreeLP(permissionTrees, p.info.name);
+ final BasePermission tree = findPermissionTree(permissionTrees, p.info.name);
if (tree == null
|| tree.sourcePackageName.equals(p.info.packageName)) {
bp.sourcePackageSetting = pkgSetting;
@@ -345,12 +346,12 @@
return bp;
}
- public static BasePermission enforcePermissionTreeLP(
- Map<String, BasePermission> permissionTrees, String permName, int callingUid) {
+ static BasePermission enforcePermissionTree(
+ Collection<BasePermission> permissionTrees, String permName, int callingUid) {
if (permName != null) {
- BasePermission bp = findPermissionTreeLP(permissionTrees, permName);
+ BasePermission bp = findPermissionTree(permissionTrees, permName);
if (bp != null) {
- if (bp.uid == UserHandle.getAppId(callingUid)) {//UserHandle.getAppId(Binder.getCallingUid())) {
+ if (bp.uid == UserHandle.getAppId(callingUid)) {
return bp;
}
throw new SecurityException("Calling uid " + callingUid
@@ -373,9 +374,9 @@
}
}
- private static BasePermission findPermissionTreeLP(
- Map<String, BasePermission> permissionTrees, String permName) {
- for (BasePermission bp : permissionTrees.values()) {
+ private static BasePermission findPermissionTree(
+ Collection<BasePermission> permissionTrees, String permName) {
+ for (BasePermission bp : permissionTrees) {
if (permName.startsWith(bp.name) &&
permName.length() > bp.name.length() &&
permName.charAt(bp.name.length()) == '.') {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index 3b20b42..8aac52a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -31,6 +31,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Internal interfaces to be used by other components within the system server.
@@ -81,11 +82,26 @@
@NonNull int[] allUserIds);
- public abstract boolean addPermission(@NonNull PermissionInfo info, boolean async,
+ /**
+ * Add all permissions in the given package.
+ * <p>
+ * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
+ * the permission settings.
+ */
+ public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
+ public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
+ public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async,
int callingUid, @Nullable PermissionCallback callback);
- public abstract void removePermission(@NonNull String permName, int callingUid,
+ public abstract void removeDynamicPermission(@NonNull String permName, int callingUid,
@Nullable PermissionCallback callback);
+ public abstract int updatePermissions(@Nullable String changingPkg,
+ @Nullable PackageParser.Package pkgInfo, int flags);
+ public abstract int updatePermissionTrees(@Nullable String changingPkg,
+ @Nullable PackageParser.Package pkgInfo, int flags);
+
+ public abstract @Nullable String[] getAppOpPermissionPackages(@NonNull String permName);
+
public abstract int getPermissionFlags(@NonNull String permName,
@NonNull String packageName, int callingUid, int userId);
/**
@@ -98,8 +114,6 @@
*/
public abstract @Nullable List<PermissionInfo> getPermissionInfoByGroup(@NonNull String group,
@PermissionInfoFlags int flags, int callingUid);
- public abstract boolean isPermissionAppOp(@NonNull String permName);
- public abstract boolean isPermissionInstant(@NonNull String permName);
/**
* Updates the flags associated with a permission by replacing the flags in
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 6c031a6..062aa33 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -69,6 +69,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
/**
* Manages all permissions and handles permissions related tasks.
@@ -260,7 +261,7 @@
// }
final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
- for (BasePermission bp : mSettings.getAllPermissionsLocked()) {
+ for (BasePermission bp : mSettings.mPermissions.values()) {
final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
if (pi != null) {
out.add(pi);
@@ -305,7 +306,98 @@
return protectionLevel;
}
- private boolean addPermission(
+ private void addAllPermissions(PackageParser.Package pkg, boolean chatty) {
+ final int N = pkg.permissions.size();
+ for (int i=0; i<N; i++) {
+ PackageParser.Permission p = pkg.permissions.get(i);
+
+ // Assume by default that we did not install this permission into the system.
+ p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
+
+ // Now that permission groups have a special meaning, we ignore permission
+ // groups for legacy apps to prevent unexpected behavior. In particular,
+ // permissions for one app being granted to someone just because they happen
+ // to be in a group defined by another app (before this had no implications).
+ if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
+ p.group = mPackageManagerInt.getPermissionGroupTEMP(p.info.group);
+ // Warn for a permission in an unknown group.
+ if (PackageManagerService.DEBUG_PERMISSIONS
+ && p.info.group != null && p.group == null) {
+ Slog.i(TAG, "Permission " + p.info.name + " from package "
+ + p.info.packageName + " in an unknown group " + p.info.group);
+ }
+ }
+
+ synchronized (PermissionManagerService.this.mLock) {
+ if (p.tree) {
+ final BasePermission bp = BasePermission.createOrUpdate(
+ mSettings.getPermissionTreeLocked(p.info.name), p, pkg,
+ mSettings.getAllPermissionTreesLocked(), chatty);
+ mSettings.putPermissionTreeLocked(p.info.name, bp);
+ } else {
+ final BasePermission bp = BasePermission.createOrUpdate(
+ mSettings.getPermissionLocked(p.info.name),
+ p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
+ mSettings.putPermissionLocked(p.info.name, bp);
+ }
+ }
+ }
+ }
+
+ private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
+ synchronized (mLock) {
+ int N = pkg.permissions.size();
+ StringBuilder r = null;
+ for (int i=0; i<N; i++) {
+ PackageParser.Permission p = pkg.permissions.get(i);
+ BasePermission bp = (BasePermission) mSettings.mPermissions.get(p.info.name);
+ if (bp == null) {
+ bp = mSettings.mPermissionTrees.get(p.info.name);
+ }
+ if (bp != null && bp.isPermission(p)) {
+ bp.setPermission(null);
+ if (PackageManagerService.DEBUG_REMOVE && chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(p.info.name);
+ }
+ }
+ if (p.isAppOp()) {
+ ArraySet<String> appOpPkgs =
+ mSettings.mAppOpPermissionPackages.get(p.info.name);
+ if (appOpPkgs != null) {
+ appOpPkgs.remove(pkg.packageName);
+ }
+ }
+ }
+ if (r != null) {
+ if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ }
+
+ N = pkg.requestedPermissions.size();
+ r = null;
+ for (int i=0; i<N; i++) {
+ String perm = pkg.requestedPermissions.get(i);
+ if (mSettings.isPermissionAppOp(perm)) {
+ ArraySet<String> appOpPkgs = mSettings.mAppOpPermissionPackages.get(perm);
+ if (appOpPkgs != null) {
+ appOpPkgs.remove(pkg.packageName);
+ if (appOpPkgs.isEmpty()) {
+ mSettings.mAppOpPermissionPackages.remove(perm);
+ }
+ }
+ }
+ }
+ if (r != null) {
+ if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ }
+ }
+ }
+
+ private boolean addDynamicPermission(
PermissionInfo info, int callingUid, PermissionCallback callback) {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
throw new SecurityException("Instant apps can't add permissions");
@@ -313,8 +405,7 @@
if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
throw new SecurityException("Label must be specified in permission");
}
- final BasePermission tree = (BasePermission) mPackageManagerInt.enforcePermissionTreeTEMP(
- info.name, callingUid);
+ final BasePermission tree = mSettings.enforcePermissionTree(info.name, callingUid);
final boolean added;
final boolean changed;
synchronized (mLock) {
@@ -341,13 +432,12 @@
return added;
}
- private void removePermission(
+ private void removeDynamicPermission(
String permName, int callingUid, PermissionCallback callback) {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
throw new SecurityException("Instant applications don't have access to this method");
}
- final BasePermission tree = (BasePermission) mPackageManagerInt.enforcePermissionTreeTEMP(
- permName, callingUid);
+ final BasePermission tree = mSettings.enforcePermissionTree(permName, callingUid);
synchronized (mLock) {
final BasePermission bp = mSettings.getPermissionLocked(permName);
if (bp == null) {
@@ -713,7 +803,21 @@
return runtimePermissionChangedUserIds;
}
- private int getPermissionFlags(String permName, String packageName, int callingUid, int userId) {
+ private String[] getAppOpPermissionPackages(String permName) {
+ if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ return null;
+ }
+ synchronized (mLock) {
+ final ArraySet<String> pkgs = mSettings.mAppOpPermissionPackages.get(permName);
+ if (pkgs == null) {
+ return null;
+ }
+ return pkgs.toArray(new String[pkgs.size()]);
+ }
+ }
+
+ private int getPermissionFlags(
+ String permName, String packageName, int callingUid, int userId) {
if (!mUserManagerInt.exists(userId)) {
return 0;
}
@@ -741,6 +845,96 @@
return permissionsState.getPermissionFlags(permName, userId);
}
+ private int updatePermissions(String packageName, PackageParser.Package pkgInfo, int flags) {
+ Set<BasePermission> needsUpdate = null;
+ synchronized (mLock) {
+ final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
+ while (it.hasNext()) {
+ final BasePermission bp = it.next();
+ if (bp.isDynamic()) {
+ bp.updateDynamicPermission(mSettings.mPermissionTrees.values());
+ }
+ if (bp.getSourcePackageSetting() != null) {
+ if (packageName != null && packageName.equals(bp.getSourcePackageName())
+ && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
+ Slog.i(TAG, "Removing old permission tree: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
+ it.remove();
+ }
+ continue;
+ }
+ if (needsUpdate == null) {
+ needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
+ }
+ needsUpdate.add(bp);
+ }
+ }
+ if (needsUpdate != null) {
+ for (final BasePermission bp : needsUpdate) {
+ final PackageParser.Package pkg =
+ mPackageManagerInt.getPackage(bp.getSourcePackageName());
+ synchronized (mLock) {
+ if (pkg != null && pkg.mExtras != null) {
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (bp.getSourcePackageSetting() == null) {
+ bp.setSourcePackageSetting(ps);
+ }
+ continue;
+ }
+ Slog.w(TAG, "Removing dangling permission: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ mSettings.removePermissionLocked(bp.getName());
+ }
+ }
+ }
+ return flags;
+ }
+
+ private int updatePermissionTrees(String packageName, PackageParser.Package pkgInfo,
+ int flags) {
+ Set<BasePermission> needsUpdate = null;
+ synchronized (mLock) {
+ final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
+ while (it.hasNext()) {
+ final BasePermission bp = it.next();
+ if (bp.getSourcePackageSetting() != null) {
+ if (packageName != null && packageName.equals(bp.getSourcePackageName())
+ && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
+ Slog.i(TAG, "Removing old permission tree: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
+ it.remove();
+ }
+ continue;
+ }
+ if (needsUpdate == null) {
+ needsUpdate = new ArraySet<>(mSettings.mPermissionTrees.size());
+ }
+ needsUpdate.add(bp);
+ }
+ }
+ if (needsUpdate != null) {
+ for (final BasePermission bp : needsUpdate) {
+ final PackageParser.Package pkg =
+ mPackageManagerInt.getPackage(bp.getSourcePackageName());
+ synchronized (mLock) {
+ if (pkg != null && pkg.mExtras != null) {
+ final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ if (bp.getSourcePackageSetting() == null) {
+ bp.setSourcePackageSetting(ps);
+ }
+ continue;
+ }
+ Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ mSettings.removePermissionLocked(bp.getName());
+ }
+ }
+ }
+ return flags;
+ }
+
private void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, PermissionCallback callback) {
if (!mUserManagerInt.exists(userId)) {
@@ -872,7 +1066,7 @@
private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
int size = 0;
- for (BasePermission perm : mSettings.getAllPermissionsLocked()) {
+ for (BasePermission perm : mSettings.mPermissions.values()) {
size += tree.calculateFootprint(perm);
}
return size;
@@ -889,6 +1083,15 @@
}
}
+ private static boolean hasPermission(PackageParser.Package pkgInfo, String permName) {
+ for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
+ if (pkgInfo.permissions.get(i).info.name.equals(permName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Get the first event id for the permission.
*
@@ -951,14 +1154,22 @@
private class PermissionManagerInternalImpl extends PermissionManagerInternal {
@Override
- public boolean addPermission(PermissionInfo info, boolean async, int callingUid,
- PermissionCallback callback) {
- return PermissionManagerService.this.addPermission(info, callingUid, callback);
+ public void addAllPermissions(Package pkg, boolean chatty) {
+ PermissionManagerService.this.addAllPermissions(pkg, chatty);
}
@Override
- public void removePermission(String permName, int callingUid,
+ public void removeAllPermissions(Package pkg, boolean chatty) {
+ PermissionManagerService.this.removeAllPermissions(pkg, chatty);
+ }
+ @Override
+ public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid,
PermissionCallback callback) {
- PermissionManagerService.this.removePermission(permName, callingUid, callback);
+ return PermissionManagerService.this.addDynamicPermission(info, callingUid, callback);
+ }
+ @Override
+ public void removeDynamicPermission(String permName, int callingUid,
+ PermissionCallback callback) {
+ PermissionManagerService.this.removeDynamicPermission(permName, callingUid, callback);
}
@Override
public void grantRuntimePermission(String permName, String packageName,
@@ -993,12 +1204,26 @@
(SharedUserSetting) suSetting, allUserIds);
}
@Override
+ public String[] getAppOpPermissionPackages(String permName) {
+ return PermissionManagerService.this.getAppOpPermissionPackages(permName);
+ }
+ @Override
public int getPermissionFlags(String permName, String packageName, int callingUid,
int userId) {
return PermissionManagerService.this.getPermissionFlags(permName, packageName,
callingUid, userId);
}
@Override
+ public int updatePermissions(String packageName,
+ PackageParser.Package pkgInfo, int flags) {
+ return PermissionManagerService.this.updatePermissions(packageName, pkgInfo, flags);
+ }
+ @Override
+ public int updatePermissionTrees(String packageName,
+ PackageParser.Package pkgInfo, int flags) {
+ return PermissionManagerService.this.updatePermissionTrees(packageName, pkgInfo, flags);
+ }
+ @Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, PermissionCallback callback) {
PermissionManagerService.this.updatePermissionFlags(
@@ -1038,20 +1263,6 @@
return PermissionManagerService.this.getPermissionInfoByGroup(group, flags, callingUid);
}
@Override
- public boolean isPermissionInstant(String permName) {
- synchronized (PermissionManagerService.this.mLock) {
- final BasePermission bp = mSettings.getPermissionLocked(permName);
- return (bp != null && bp.isInstant());
- }
- }
- @Override
- public boolean isPermissionAppOp(String permName) {
- synchronized (PermissionManagerService.this.mLock) {
- final BasePermission bp = mSettings.getPermissionLocked(permName);
- return (bp != null && bp.isAppOp());
- }
- }
- @Override
public PermissionSettings getPermissionSettings() {
return mSettings;
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
index 7a2e5ecc..7d125c9 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
@@ -24,6 +24,7 @@
import android.util.Log;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.DumpState;
import com.android.server.pm.PackageManagerService;
@@ -35,6 +36,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
+import java.util.Set;
/**
* Permissions and other related data. This class is not meant for
@@ -49,8 +51,25 @@
* All of the permissions known to the system. The mapping is from permission
* name to permission object.
*/
- private final ArrayMap<String, BasePermission> mPermissions =
+ @GuardedBy("mLock")
+ final ArrayMap<String, BasePermission> mPermissions =
new ArrayMap<String, BasePermission>();
+
+ /**
+ * All permission trees known to the system. The mapping is from permission tree
+ * name to permission object.
+ */
+ @GuardedBy("mLock")
+ final ArrayMap<String, BasePermission> mPermissionTrees =
+ new ArrayMap<String, BasePermission>();
+
+ /**
+ * Set of packages that request a particular app op. The mapping is from permission
+ * name to package names.
+ */
+ @GuardedBy("mLock")
+ final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
+
private final Object mLock;
PermissionSettings(@NonNull Context context, @NonNull Object lock) {
@@ -65,15 +84,23 @@
}
}
+ public void addAppOpPackage(String permName, String packageName) {
+ ArraySet<String> pkgs = mAppOpPermissionPackages.get(permName);
+ if (pkgs == null) {
+ pkgs = new ArraySet<>();
+ mAppOpPermissionPackages.put(permName, pkgs);
+ }
+ pkgs.add(packageName);
+ }
+
/**
* Transfers ownership of permissions from one package to another.
*/
- public void transferPermissions(String origPackageName, String newPackageName,
- ArrayMap<String, BasePermission> permissionTrees) {
+ public void transferPermissions(String origPackageName, String newPackageName) {
synchronized (mLock) {
for (int i=0; i<2; i++) {
ArrayMap<String, BasePermission> permissions =
- i == 0 ? permissionTrees : mPermissions;
+ i == 0 ? mPermissionTrees : mPermissions;
for (BasePermission bp : permissions.values()) {
bp.transfer(origPackageName, newPackageName);
}
@@ -94,9 +121,26 @@
}
}
+ public void readPermissionTrees(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ synchronized (mLock) {
+ readPermissions(mPermissionTrees, parser);
+ }
+ }
+
public void writePermissions(XmlSerializer serializer) throws IOException {
- for (BasePermission bp : mPermissions.values()) {
- bp.writeLPr(serializer);
+ synchronized (mLock) {
+ for (BasePermission bp : mPermissions.values()) {
+ bp.writeLPr(serializer);
+ }
+ }
+ }
+
+ public void writePermissionTrees(XmlSerializer serializer) throws IOException {
+ synchronized (mLock) {
+ for (BasePermission bp : mPermissionTrees.values()) {
+ bp.writeLPr(serializer);
+ }
}
}
@@ -128,6 +172,22 @@
printedSomething = bp.dumpPermissionsLPr(pw, packageName, permissionNames,
externalStorageEnforced, printedSomething, dumpState);
}
+ if (packageName == null && permissionNames == null) {
+ for (int iperm = 0; iperm<mAppOpPermissionPackages.size(); iperm++) {
+ if (iperm == 0) {
+ if (dumpState.onTitlePrinted())
+ pw.println();
+ pw.println("AppOp Permissions:");
+ }
+ pw.print(" AppOp Permission ");
+ pw.print(mAppOpPermissionPackages.keyAt(iperm));
+ pw.println(":");
+ ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
+ for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
+ pw.print(" "); pw.println(pkgs.valueAt(ipkg));
+ }
+ }
+ }
}
}
@@ -135,15 +195,58 @@
return mPermissions.get(permName);
}
+ @Nullable BasePermission getPermissionTreeLocked(@NonNull String permName) {
+ return mPermissionTrees.get(permName);
+ }
+
void putPermissionLocked(@NonNull String permName, @NonNull BasePermission permission) {
mPermissions.put(permName, permission);
}
+ void putPermissionTreeLocked(@NonNull String permName, @NonNull BasePermission permission) {
+ mPermissionTrees.put(permName, permission);
+ }
+
void removePermissionLocked(@NonNull String permName) {
mPermissions.remove(permName);
}
- Collection<BasePermission> getAllPermissionsLocked() {
+ void removePermissionTreeLocked(@NonNull String permName) {
+ mPermissionTrees.remove(permName);
+ }
+
+ @NonNull Collection<BasePermission> getAllPermissionsLocked() {
return mPermissions.values();
}
+
+ @NonNull Collection<BasePermission> getAllPermissionTreesLocked() {
+ return mPermissionTrees.values();
+ }
+
+ /**
+ * Returns the permission tree for the given permission.
+ * @throws SecurityException If the calling UID is not allowed to add permissions to the
+ * found permission tree.
+ */
+ @Nullable BasePermission enforcePermissionTree(@NonNull String permName, int callingUid) {
+ synchronized (mLock) {
+ return BasePermission.enforcePermissionTree(
+ mPermissionTrees.values(), permName, callingUid);
+ }
+ }
+
+ public boolean isPermissionInstant(String permName) {
+ synchronized (mLock) {
+ final BasePermission bp = mPermissions.get(permName);
+ return (bp != null && bp.isInstant());
+ }
+ }
+
+ boolean isPermissionAppOp(String permName) {
+ synchronized (mLock) {
+ final BasePermission bp = mPermissions.get(permName);
+ return (bp != null && bp.isAppOp());
+ }
+ }
+
}