Skip to content

Commit 5265466

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "New development permissions."
2 parents 2abb138 + e639da7 commit 5265466

File tree

17 files changed

+691
-200
lines changed

17 files changed

+691
-200
lines changed

api/current.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6195,6 +6195,8 @@ package android.content.pm {
61956195
method public int describeContents();
61966196
method public void writeToParcel(android.os.Parcel, int);
61976197
field public static final android.os.Parcelable.Creator CREATOR;
6198+
field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
6199+
field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
61986200
field public android.content.pm.ActivityInfo[] activities;
61996201
field public android.content.pm.ApplicationInfo applicationInfo;
62006202
field public android.content.pm.ConfigurationInfo[] configPreferences;
@@ -6208,6 +6210,7 @@ package android.content.pm {
62086210
field public android.content.pm.ActivityInfo[] receivers;
62096211
field public android.content.pm.FeatureInfo[] reqFeatures;
62106212
field public java.lang.String[] requestedPermissions;
6213+
field public int[] requestedPermissionsFlags;
62116214
field public android.content.pm.ServiceInfo[] services;
62126215
field public java.lang.String sharedUserId;
62136216
field public int sharedUserLabel;
@@ -6430,6 +6433,10 @@ package android.content.pm {
64306433
method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
64316434
field public static final android.os.Parcelable.Creator CREATOR;
64326435
field public static final int PROTECTION_DANGEROUS = 1; // 0x1
6436+
field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
6437+
field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
6438+
field public static final int PROTECTION_MASK_BASE = 15; // 0xf
6439+
field public static final int PROTECTION_MASK_FLAGS = 240; // 0xf0
64336440
field public static final int PROTECTION_NORMAL = 0; // 0x0
64346441
field public static final int PROTECTION_SIGNATURE = 2; // 0x2
64356442
field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3

cmds/pm/src/com/android/commands/pm/Pm.java

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ public void run(String[] args) {
126126
return;
127127
}
128128

129+
if ("grant".equals(op)) {
130+
runGrantRevokePermission(true);
131+
return;
132+
}
133+
134+
if ("revoke".equals(op)) {
135+
runGrantRevokePermission(false);
136+
return;
137+
}
138+
129139
if ("set-install-location".equals(op)) {
130140
runSetInstallLocation();
131141
return;
@@ -596,8 +606,9 @@ private void doListPermissions(ArrayList<String> groupList,
596606
if (groups && groupName == null && pi.group != null) {
597607
continue;
598608
}
599-
if (pi.protectionLevel < startProtectionLevel
600-
|| pi.protectionLevel > endProtectionLevel) {
609+
final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
610+
if (base < startProtectionLevel
611+
|| base > endProtectionLevel) {
601612
continue;
602613
}
603614
if (summary) {
@@ -627,22 +638,8 @@ private void doListPermissions(ArrayList<String> groupList,
627638
+ loadText(pi, pi.descriptionRes,
628639
pi.nonLocalizedDescription));
629640
}
630-
String protLevel = "unknown";
631-
switch(pi.protectionLevel) {
632-
case PermissionInfo.PROTECTION_DANGEROUS:
633-
protLevel = "dangerous";
634-
break;
635-
case PermissionInfo.PROTECTION_NORMAL:
636-
protLevel = "normal";
637-
break;
638-
case PermissionInfo.PROTECTION_SIGNATURE:
639-
protLevel = "signature";
640-
break;
641-
case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
642-
protLevel = "signatureOrSystem";
643-
break;
644-
}
645-
System.out.println(prefix + " protectionLevel:" + protLevel);
641+
System.out.println(prefix + " protectionLevel:"
642+
+ PermissionInfo.protectionToString(pi.protectionLevel));
646643
}
647644
}
648645
}
@@ -1063,6 +1060,36 @@ private void runSetEnabledSetting(int state) {
10631060
}
10641061
}
10651062

1063+
private void runGrantRevokePermission(boolean grant) {
1064+
String pkg = nextArg();
1065+
if (pkg == null) {
1066+
System.err.println("Error: no package specified");
1067+
showUsage();
1068+
return;
1069+
}
1070+
String perm = nextArg();
1071+
if (perm == null) {
1072+
System.err.println("Error: no permission specified");
1073+
showUsage();
1074+
return;
1075+
}
1076+
try {
1077+
if (grant) {
1078+
mPm.grantPermission(pkg, perm);
1079+
} else {
1080+
mPm.revokePermission(pkg, perm);
1081+
}
1082+
} catch (RemoteException e) {
1083+
System.err.println(e.toString());
1084+
System.err.println(PM_NOT_RUNNING_ERR);
1085+
} catch (IllegalArgumentException e) {
1086+
System.err.println("Bad argument: " + e.toString());
1087+
showUsage();
1088+
} catch (SecurityException e) {
1089+
System.err.println("Operation not allowed: " + e.toString());
1090+
}
1091+
}
1092+
10661093
/**
10671094
* Displays the package file for a package.
10681095
* @param pckg
@@ -1158,6 +1185,8 @@ private static void showUsage() {
11581185
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
11591186
System.err.println(" pm disable PACKAGE_OR_COMPONENT");
11601187
System.err.println(" pm disable-user PACKAGE_OR_COMPONENT");
1188+
System.err.println(" pm grant PACKAGE PERMISSION");
1189+
System.err.println(" pm revoke PACKAGE PERMISSION");
11611190
System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]");
11621191
System.err.println(" pm get-install-location");
11631192
System.err.println(" pm create-profile USER_NAME");
@@ -1208,6 +1237,10 @@ private static void showUsage() {
12081237
System.err.println("pm enable, disable, disable-user: these commands change the enabled state");
12091238
System.err.println(" of a given package or component (written as \"package/class\").");
12101239
System.err.println("");
1240+
System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
1241+
System.err.println(" to applications. Only optional permissions the application has");
1242+
System.err.println(" declared can be granted or revoked.");
1243+
System.err.println("");
12111244
System.err.println("pm get-install-location: returns the current install location.");
12121245
System.err.println(" 0 [auto]: Let system decide the best location");
12131246
System.err.println(" 1 [internal]: Install on internal device storage");

core/java/android/app/ApplicationPackageManager.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,24 @@ public void removePermission(String name) {
331331
}
332332
}
333333

334+
@Override
335+
public void grantPermission(String packageName, String permissionName) {
336+
try {
337+
mPM.grantPermission(packageName, permissionName);
338+
} catch (RemoteException e) {
339+
throw new RuntimeException("Package manager has died", e);
340+
}
341+
}
342+
343+
@Override
344+
public void revokePermission(String packageName, String permissionName) {
345+
try {
346+
mPM.revokePermission(packageName, permissionName);
347+
} catch (RemoteException e) {
348+
throw new RuntimeException("Package manager has died", e);
349+
}
350+
}
351+
334352
@Override
335353
public int checkSignatures(String pkg1, String pkg2) {
336354
try {

core/java/android/content/pm/IPackageManager.aidl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ interface IPackageManager {
8181
boolean addPermission(in PermissionInfo info);
8282

8383
void removePermission(String name);
84-
84+
85+
void grantPermission(String packageName, String permissionName);
86+
87+
void revokePermission(String packageName, String permissionName);
88+
8589
boolean isProtectedBroadcast(String actionName);
8690

8791
int checkSignatures(String pkg1, String pkg2);

core/java/android/content/pm/PackageInfo.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,30 @@ public class PackageInfo implements Parcelable {
140140
*/
141141
public String[] requestedPermissions;
142142

143+
/**
144+
* Array of flags of all {@link android.R.styleable#AndroidManifestUsesPermission
145+
* &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
146+
* or null if there were none. This is only filled in if the flag
147+
* {@link PackageManager#GET_PERMISSIONS} was set. Each value matches
148+
* the corresponding entry in {@link #requestedPermissions}, and will have
149+
* the flags {@link #REQUESTED_PERMISSION_REQUIRED} and
150+
* {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
151+
*/
152+
public int[] requestedPermissionsFlags;
153+
154+
/**
155+
* Flag for {@link #requestedPermissionsFlags}: the requested permission
156+
* is required for the application to run; the user can not optionally
157+
* disable it.
158+
*/
159+
public static final int REQUESTED_PERMISSION_REQUIRED = 1<<0;
160+
161+
/**
162+
* Flag for {@link #requestedPermissionsFlags}: the requested permission
163+
* is currently granted to the application.
164+
*/
165+
public static final int REQUESTED_PERMISSION_GRANTED = 1<<1;
166+
143167
/**
144168
* Array of all signatures read from the package file. This is only filled
145169
* in if the flag {@link PackageManager#GET_SIGNATURES} was set.
@@ -229,6 +253,7 @@ public void writeToParcel(Parcel dest, int parcelableFlags) {
229253
dest.writeTypedArray(instrumentation, parcelableFlags);
230254
dest.writeTypedArray(permissions, parcelableFlags);
231255
dest.writeStringArray(requestedPermissions);
256+
dest.writeIntArray(requestedPermissionsFlags);
232257
dest.writeTypedArray(signatures, parcelableFlags);
233258
dest.writeTypedArray(configPreferences, parcelableFlags);
234259
dest.writeTypedArray(reqFeatures, parcelableFlags);
@@ -266,6 +291,7 @@ private PackageInfo(Parcel source) {
266291
instrumentation = source.createTypedArray(InstrumentationInfo.CREATOR);
267292
permissions = source.createTypedArray(PermissionInfo.CREATOR);
268293
requestedPermissions = source.createStringArray();
294+
requestedPermissionsFlags = source.createIntArray();
269295
signatures = source.createTypedArray(Signature.CREATOR);
270296
configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
271297
reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);

core/java/android/content/pm/PackageManager.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,29 @@ public abstract ProviderInfo getProviderInfo(ComponentName component,
14741474
*/
14751475
public abstract void removePermission(String name);
14761476

1477+
/**
1478+
* Grant a permission to an application which the application does not
1479+
* already have. The permission must have been requested by the application,
1480+
* but as an optional permission. If the application is not allowed to
1481+
* hold the permission, a SecurityException is thrown.
1482+
* @hide
1483+
*
1484+
* @param packageName The name of the package that the permission will be
1485+
* granted to.
1486+
* @param permissionName The name of the permission.
1487+
*/
1488+
public abstract void grantPermission(String packageName, String permissionName);
1489+
1490+
/**
1491+
* Revoke a permission that was previously granted by {@link #grantPermission}.
1492+
* @hide
1493+
*
1494+
* @param packageName The name of the package that the permission will be
1495+
* granted to.
1496+
* @param permissionName The name of the permission.
1497+
*/
1498+
public abstract void revokePermission(String packageName, String permissionName);
1499+
14771500
/**
14781501
* Compare the signatures of two packages to determine if the same
14791502
* signature appears in both of them. If they do contain the same
@@ -2125,7 +2148,7 @@ public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
21252148
if ((flags & GET_SIGNATURES) != 0) {
21262149
packageParser.collectCertificates(pkg, 0);
21272150
}
2128-
return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0);
2151+
return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null);
21292152
}
21302153

21312154
/**

core/java/android/content/pm/PackageParser.java

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import java.security.spec.X509EncodedKeySpec;
5252
import java.util.ArrayList;
5353
import java.util.Enumeration;
54+
import java.util.HashSet;
5455
import java.util.Iterator;
5556
import java.util.List;
5657
import java.util.jar.Attributes;
@@ -211,7 +212,8 @@ private static final boolean isPackageFilename(String name) {
211212
* @param flags indicating which optional information is included.
212213
*/
213214
public static PackageInfo generatePackageInfo(PackageParser.Package p,
214-
int gids[], int flags, long firstInstallTime, long lastUpdateTime) {
215+
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
216+
HashSet<String> grantedPermissions) {
215217

216218
final int userId = Binder.getOrigCallingUser();
217219

@@ -346,8 +348,16 @@ public static PackageInfo generatePackageInfo(PackageParser.Package p,
346348
N = p.requestedPermissions.size();
347349
if (N > 0) {
348350
pi.requestedPermissions = new String[N];
351+
pi.requestedPermissionsFlags = new int[N];
349352
for (int i=0; i<N; i++) {
350-
pi.requestedPermissions[i] = p.requestedPermissions.get(i);
353+
final String perm = p.requestedPermissions.get(i);
354+
pi.requestedPermissions[i] = perm;
355+
if (p.requestedPermissionsRequired.get(i)) {
356+
pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
357+
}
358+
if (grantedPermissions != null && grantedPermissions.contains(perm)) {
359+
pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
360+
}
351361
}
352362
}
353363
}
@@ -927,11 +937,14 @@ private Package parsePackage(
927937
// that may change.
928938
String name = sa.getNonResourceString(
929939
com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
940+
boolean required = sa.getBoolean(
941+
com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true);
930942

931943
sa.recycle();
932944

933945
if (name != null && !pkg.requestedPermissions.contains(name)) {
934946
pkg.requestedPermissions.add(name.intern());
947+
pkg.requestedPermissionsRequired.add(required);
935948
}
936949

937950
XmlUtils.skipCurrentTag(parser);
@@ -1419,12 +1432,24 @@ private Permission parsePermission(Package owner, Resources res,
14191432
PermissionInfo.PROTECTION_NORMAL);
14201433

14211434
sa.recycle();
1422-
1435+
14231436
if (perm.info.protectionLevel == -1) {
14241437
outError[0] = "<permission> does not specify protectionLevel";
14251438
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
14261439
return null;
14271440
}
1441+
1442+
perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
1443+
1444+
if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
1445+
if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
1446+
PermissionInfo.PROTECTION_SIGNATURE) {
1447+
outError[0] = "<permission> protectionLevel specifies a flag but is "
1448+
+ "not based on signature type";
1449+
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1450+
return null;
1451+
}
1452+
}
14281453

14291454
if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
14301455
outError)) {
@@ -2951,6 +2976,7 @@ public final static class Package {
29512976
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
29522977

29532978
public final ArrayList<String> requestedPermissions = new ArrayList<String>();
2979+
public final ArrayList<Boolean> requestedPermissionsRequired = new ArrayList<Boolean>();
29542980

29552981
public ArrayList<String> protectedBroadcasts;
29562982

0 commit comments

Comments
 (0)