Add permissions associated with app ops.

Change-Id: I575ad7a3ceea59486ca601f69760b14f6269511d
This commit is contained in:
Dianne Hackborn
2014-07-21 15:35:45 -07:00
parent 66e207ec54
commit 33f5ddd1be
8 changed files with 96 additions and 4 deletions

View File

@@ -3820,6 +3820,7 @@ package android.app {
method public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager.OnOpChangedListener);
method public void stopWatchingMode(android.app.AppOpsManager.OnOpChangedListener);
field public static final int MODE_ALLOWED = 0; // 0x0
field public static final int MODE_DEFAULT = 3; // 0x3
field public static final int MODE_ERRORED = 2; // 0x2
field public static final int MODE_IGNORED = 1; // 0x1
field public static final java.lang.String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -8877,6 +8878,7 @@ package android.content.pm {
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_COSTS_MONEY = 1; // 0x1
field public static final int PROTECTION_DANGEROUS = 1; // 0x1
field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
field public static final int PROTECTION_MASK_BASE = 15; // 0xf

View File

@@ -94,6 +94,13 @@ public class AppOpsManager {
*/
public static final int MODE_ERRORED = 2;
/**
* Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller should
* use its default security check. This mode is not normally used; it should only be used
* with appop permissions, and callers must explicitly check for it and deal with it.
*/
public static final int MODE_DEFAULT = 3;
// when adding one of these:
// - increment _NUM_OP
// - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
@@ -588,7 +595,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_IGNORED, // OP_GET_USAGE_STATS
AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA

View File

@@ -110,6 +110,8 @@ interface IPackageManager {
int getFlagsForUid(int uid);
String[] getAppOpPermissionPackages(String permissionName);
ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);

View File

@@ -68,6 +68,13 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
*/
public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20;
/**
* Additional flag for {@link #protectionLevel}, corresponding
* to the <code>development</code> value of
* {@link android.R.attr#protectionLevel}.
*/
public static final int PROTECTION_FLAG_APPOP = 0x40;
/**
* Mask for {@link #protectionLevel}: the basic protection type.
*/
@@ -153,6 +160,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
if ((level&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
protLevel += "|development";
}
if ((level&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
protLevel += "|appop";
}
return protLevel;
}

View File

@@ -2461,7 +2461,7 @@
<permission android:name="android.permission.PACKAGE_USAGE_STATS"
android:label="@string/permlab_pkgUsageStats"
android:description="@string/permdesc_pkgUsageStats"
android:protectionLevel="signature|system" />
android:protectionLevel="signature|system|development|appop" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<!-- @SystemApi Allows an application to collect battery statistics -->
@@ -2469,7 +2469,7 @@
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:label="@string/permlab_batteryStats"
android:description="@string/permdesc_batteryStats"
android:protectionLevel="signature|system" />
android:protectionLevel="signature|system|development" />
<!-- @SystemApi Allows an application to control the backup and restore process.
<p>Not for use by third-party applications.

View File

@@ -212,6 +212,9 @@
<!-- Additional flag from base permission type: this permission can also
(optionally) be granted to development applications. -->
<flag name="development" value="0x20" />
<!-- Additional flag from base permission type: this permission is closely
associated with an app op for controlling access. -->
<flag name="appop" value="0x40" />
</attr>
<!-- Flags indicating more context for a permission group. -->

View File

@@ -474,6 +474,9 @@ public class PackageManagerService extends IPackageManager.Stub {
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;
HashSet<PackageParser.Package> mDeferredDexOpt = null;
@@ -2916,6 +2919,17 @@ public class PackageManagerService extends IPackageManager.Stub {
return 0;
}
@Override
public String[] getAppOpPermissionPackages(String permissionName) {
synchronized (mPackages) {
ArraySet<String> pkgs = mAppOpPermissionPackages.get(permissionName);
if (pkgs == null) {
return null;
}
return pkgs.toArray(new String[pkgs.size()]);
}
}
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
@@ -6591,6 +6605,31 @@ public class PackageManagerService extends IPackageManager.Stub {
r.append(p.info.name);
}
}
if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(p.info.name);
if (appOpPerms != null) {
appOpPerms.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);
BasePermission bp = mSettings.mPermissions.get(perm);
if (bp != null && (bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(perm);
if (appOpPerms != null) {
appOpPerms.remove(pkg.packageName);
if (appOpPerms.isEmpty()) {
mAppOpPermissionPackages.remove(perm);
}
}
}
}
if (r != null) {
if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
@@ -6775,6 +6814,15 @@ public class PackageManagerService extends IPackageManager.Stub {
final String perm = bp.name;
boolean allowed;
boolean allowedSig = false;
if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
// Keep track of app op permissions.
ArraySet<String> pkgs = mAppOpPermissionPackages.get(bp.name);
if (pkgs == null) {
pkgs = new ArraySet<>();
mAppOpPermissionPackages.put(bp.name, pkgs);
}
pkgs.add(pkg.packageName);
}
final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
if (level == PermissionInfo.PROTECTION_NORMAL
|| level == PermissionInfo.PROTECTION_DANGEROUS) {
@@ -6837,7 +6885,9 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " (protectionLevel=" + bp.protectionLevel
+ " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ ")");
} else {
} else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {
// Don't print warning for app op permissions, since it is fine for them
// not to be granted, there is a UI for the user to decide.
Slog.w(TAG, "Not granting permission " + perm
+ " to package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
@@ -12426,6 +12476,22 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
if (packageName == 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)) {

View File

@@ -1,6 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.voiceinteraction">
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<application>
<activity android:name="VoiceInteractionMain" android:label="Voice Interaction"
android:theme="@android:style/Theme.Material">