Merge "Implement issue #34842682: Add ability to limit permissions based on features"
This commit is contained in:
committed by
Android (Google) Code Review
commit
594ea5f8b0
@@ -1005,7 +1005,7 @@ package android {
|
||||
field public static final int preferenceStyle = 16842894; // 0x101008e
|
||||
field public static final int presentationTheme = 16843712; // 0x10103c0
|
||||
field public static final int previewImage = 16843482; // 0x10102da
|
||||
field public static final int primaryContentAlpha = 16843367; // 0x1010267
|
||||
field public static final int primaryContentAlpha = 16844117; // 0x1010555
|
||||
field public static final int priority = 16842780; // 0x101001c
|
||||
field public static final int privateImeOptions = 16843299; // 0x1010223
|
||||
field public static final int process = 16842769; // 0x1010011
|
||||
@@ -1061,7 +1061,9 @@ package android {
|
||||
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
|
||||
field public static final int required = 16843406; // 0x101028e
|
||||
field public static final int requiredAccountType = 16843734; // 0x10103d6
|
||||
field public static final int requiredFeature = 16844119; // 0x1010557
|
||||
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
|
||||
field public static final int requiredNotFeature = 16844120; // 0x1010558
|
||||
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
|
||||
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
|
||||
field public static final int resizeClip = 16843983; // 0x10104cf
|
||||
@@ -1130,7 +1132,7 @@ package android {
|
||||
field public static final int searchSuggestSelection = 16843224; // 0x10101d8
|
||||
field public static final int searchSuggestThreshold = 16843373; // 0x101026d
|
||||
field public static final int searchViewStyle = 16843904; // 0x1010480
|
||||
field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
|
||||
field public static final int secondaryContentAlpha = 16844118; // 0x1010556
|
||||
field public static final int secondaryProgress = 16843064; // 0x1010138
|
||||
field public static final int secondaryProgressTint = 16843879; // 0x1010467
|
||||
field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
|
||||
|
||||
@@ -1117,7 +1117,7 @@ package android {
|
||||
field public static final int preferenceStyle = 16842894; // 0x101008e
|
||||
field public static final int presentationTheme = 16843712; // 0x10103c0
|
||||
field public static final int previewImage = 16843482; // 0x10102da
|
||||
field public static final int primaryContentAlpha = 16843367; // 0x1010267
|
||||
field public static final int primaryContentAlpha = 16844117; // 0x1010555
|
||||
field public static final int priority = 16842780; // 0x101001c
|
||||
field public static final int privateImeOptions = 16843299; // 0x1010223
|
||||
field public static final int process = 16842769; // 0x1010011
|
||||
@@ -1173,7 +1173,9 @@ package android {
|
||||
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
|
||||
field public static final int required = 16843406; // 0x101028e
|
||||
field public static final int requiredAccountType = 16843734; // 0x10103d6
|
||||
field public static final int requiredFeature = 16844119; // 0x1010557
|
||||
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
|
||||
field public static final int requiredNotFeature = 16844120; // 0x1010558
|
||||
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
|
||||
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
|
||||
field public static final int resizeClip = 16843983; // 0x10104cf
|
||||
@@ -1246,7 +1248,7 @@ package android {
|
||||
field public static final int searchSuggestSelection = 16843224; // 0x10101d8
|
||||
field public static final int searchSuggestThreshold = 16843373; // 0x101026d
|
||||
field public static final int searchViewStyle = 16843904; // 0x1010480
|
||||
field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
|
||||
field public static final int secondaryContentAlpha = 16844118; // 0x1010556
|
||||
field public static final int secondaryProgress = 16843064; // 0x1010138
|
||||
field public static final int secondaryProgressTint = 16843879; // 0x1010467
|
||||
field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
|
||||
|
||||
@@ -1005,7 +1005,7 @@ package android {
|
||||
field public static final int preferenceStyle = 16842894; // 0x101008e
|
||||
field public static final int presentationTheme = 16843712; // 0x10103c0
|
||||
field public static final int previewImage = 16843482; // 0x10102da
|
||||
field public static final int primaryContentAlpha = 16843367; // 0x1010267
|
||||
field public static final int primaryContentAlpha = 16844117; // 0x1010555
|
||||
field public static final int priority = 16842780; // 0x101001c
|
||||
field public static final int privateImeOptions = 16843299; // 0x1010223
|
||||
field public static final int process = 16842769; // 0x1010011
|
||||
@@ -1061,7 +1061,9 @@ package android {
|
||||
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
|
||||
field public static final int required = 16843406; // 0x101028e
|
||||
field public static final int requiredAccountType = 16843734; // 0x10103d6
|
||||
field public static final int requiredFeature = 16844119; // 0x1010557
|
||||
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
|
||||
field public static final int requiredNotFeature = 16844120; // 0x1010558
|
||||
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
|
||||
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
|
||||
field public static final int resizeClip = 16843983; // 0x10104cf
|
||||
@@ -1130,7 +1132,7 @@ package android {
|
||||
field public static final int searchSuggestSelection = 16843224; // 0x10101d8
|
||||
field public static final int searchSuggestThreshold = 16843373; // 0x101026d
|
||||
field public static final int searchViewStyle = 16843904; // 0x1010480
|
||||
field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
|
||||
field public static final int secondaryContentAlpha = 16844118; // 0x1010556
|
||||
field public static final int secondaryProgress = 16843064; // 0x1010138
|
||||
field public static final int secondaryProgressTint = 16843879; // 0x1010467
|
||||
field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
|
||||
|
||||
@@ -5000,6 +5000,7 @@ public abstract class PackageManager {
|
||||
*/
|
||||
public PackageInfo getPackageArchiveInfo(String archiveFilePath, @PackageInfoFlags int flags) {
|
||||
final PackageParser parser = new PackageParser();
|
||||
parser.setCallback(new PackageParser.CallbackImpl(this));
|
||||
final File apkFile = new File(archiveFilePath);
|
||||
try {
|
||||
if ((flags & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
|
||||
|
||||
@@ -285,6 +285,7 @@ public class PackageParser {
|
||||
private String[] mSeparateProcesses;
|
||||
private boolean mOnlyCoreApps;
|
||||
private DisplayMetrics mMetrics;
|
||||
private Callback mCallback;
|
||||
private File mCacheDir;
|
||||
|
||||
private static final int SDK_VERSION = Build.VERSION.SDK_INT;
|
||||
@@ -506,6 +507,37 @@ public class PackageParser {
|
||||
mCacheDir = cacheDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback interface for retrieving information that may be needed while parsing
|
||||
* a package.
|
||||
*/
|
||||
public interface Callback {
|
||||
boolean hasFeature(String feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard implementation of {@link Callback} on top of the public {@link PackageManager}
|
||||
* class.
|
||||
*/
|
||||
public static final class CallbackImpl implements Callback {
|
||||
private final PackageManager mPm;
|
||||
|
||||
public CallbackImpl(PackageManager pm) {
|
||||
mPm = pm;
|
||||
}
|
||||
|
||||
@Override public boolean hasFeature(String feature) {
|
||||
return mPm.hasSystemFeature(feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link Callback} that can be used while parsing.
|
||||
*/
|
||||
public void setCallback(Callback cb) {
|
||||
mCallback = cb;
|
||||
}
|
||||
|
||||
public static final boolean isApkFile(File file) {
|
||||
return isApkPath(file.getName());
|
||||
}
|
||||
@@ -2079,15 +2111,15 @@ public class PackageParser {
|
||||
return null;
|
||||
}
|
||||
} else if (tagName.equals(TAG_PERMISSION_GROUP)) {
|
||||
if (parsePermissionGroup(pkg, flags, res, parser, outError) == null) {
|
||||
if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
|
||||
return null;
|
||||
}
|
||||
} else if (tagName.equals(TAG_PERMISSION)) {
|
||||
if (parsePermission(pkg, res, parser, outError) == null) {
|
||||
if (!parsePermission(pkg, res, parser, outError)) {
|
||||
return null;
|
||||
}
|
||||
} else if (tagName.equals(TAG_PERMISSION_TREE)) {
|
||||
if (parsePermissionTree(pkg, res, parser, outError) == null) {
|
||||
if (!parsePermissionTree(pkg, res, parser, outError)) {
|
||||
return null;
|
||||
}
|
||||
} else if (tagName.equals(TAG_USES_PERMISSION)) {
|
||||
@@ -2708,22 +2740,44 @@ public class PackageParser {
|
||||
}
|
||||
}
|
||||
|
||||
final String requiredFeature = sa.getNonConfigurationString(
|
||||
com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
|
||||
|
||||
final String requiredNotfeature = sa.getNonConfigurationString(
|
||||
com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
|
||||
|
||||
sa.recycle();
|
||||
|
||||
if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) {
|
||||
if (name != null) {
|
||||
int index = pkg.requestedPermissions.indexOf(name);
|
||||
if (index == -1) {
|
||||
pkg.requestedPermissions.add(name.intern());
|
||||
} else {
|
||||
Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
|
||||
+ name + " in package: " + pkg.packageName + " at: "
|
||||
+ parser.getPositionDescription());
|
||||
}
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
|
||||
if (name == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only allow requesting this permission if the platform supports the given feature.
|
||||
if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only allow requesting this permission if the platform doesn't support the given feature.
|
||||
if (requiredNotfeature != null && mCallback != null
|
||||
&& mCallback.hasFeature(requiredNotfeature)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int index = pkg.requestedPermissions.indexOf(name);
|
||||
if (index == -1) {
|
||||
pkg.requestedPermissions.add(name.intern());
|
||||
} else {
|
||||
Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
|
||||
+ name + " in package: " + pkg.packageName + " at: "
|
||||
+ parser.getPositionDescription());
|
||||
}
|
||||
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2951,7 +3005,7 @@ public class PackageParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
|
||||
private boolean parsePermissionGroup(Package owner, int flags, Resources res,
|
||||
XmlResourceParser parser, String[] outError)
|
||||
throws XmlPullParserException, IOException {
|
||||
PermissionGroup perm = new PermissionGroup(owner);
|
||||
@@ -2968,7 +3022,7 @@ public class PackageParser {
|
||||
com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
|
||||
sa.recycle();
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
perm.info.descriptionRes = sa.getResourceId(
|
||||
@@ -2987,22 +3041,22 @@ public class PackageParser {
|
||||
if (!parseAllMetaData(res, parser, "<permission-group>", perm,
|
||||
outError)) {
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
owner.permissionGroups.add(perm);
|
||||
|
||||
return perm;
|
||||
return true;
|
||||
}
|
||||
|
||||
private Permission parsePermission(Package owner, Resources res,
|
||||
private boolean parsePermission(Package owner, Resources res,
|
||||
XmlResourceParser parser, String[] outError)
|
||||
throws XmlPullParserException, IOException {
|
||||
Permission perm = new Permission(owner);
|
||||
|
||||
TypedArray sa = res.obtainAttributes(parser,
|
||||
com.android.internal.R.styleable.AndroidManifestPermission);
|
||||
|
||||
Permission perm = new Permission(owner);
|
||||
if (!parsePackageItemInfo(owner, perm.info, outError,
|
||||
"<permission>", sa, true /*nameRequired*/,
|
||||
com.android.internal.R.styleable.AndroidManifestPermission_name,
|
||||
@@ -3013,7 +3067,7 @@ public class PackageParser {
|
||||
com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
|
||||
sa.recycle();
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: don't allow this value to be a reference to a resource
|
||||
@@ -3040,7 +3094,7 @@ public class PackageParser {
|
||||
if (perm.info.protectionLevel == -1) {
|
||||
outError[0] = "<permission> does not specify protectionLevel";
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
|
||||
@@ -3052,21 +3106,21 @@ public class PackageParser {
|
||||
outError[0] = "<permission> protectionLevel specifies a non-ephemeral flag but is "
|
||||
+ "not based on signature type";
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
owner.permissions.add(perm);
|
||||
|
||||
return perm;
|
||||
return true;
|
||||
}
|
||||
|
||||
private Permission parsePermissionTree(Package owner, Resources res,
|
||||
private boolean parsePermissionTree(Package owner, Resources res,
|
||||
XmlResourceParser parser, String[] outError)
|
||||
throws XmlPullParserException, IOException {
|
||||
Permission perm = new Permission(owner);
|
||||
@@ -3084,7 +3138,7 @@ public class PackageParser {
|
||||
com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
|
||||
sa.recycle();
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
sa.recycle();
|
||||
@@ -3097,7 +3151,7 @@ public class PackageParser {
|
||||
outError[0] = "<permission-tree> name has less than three segments: "
|
||||
+ perm.info.name;
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
perm.info.descriptionRes = 0;
|
||||
@@ -3107,12 +3161,12 @@ public class PackageParser {
|
||||
if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
|
||||
outError)) {
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
owner.permissions.add(perm);
|
||||
|
||||
return perm;
|
||||
return true;
|
||||
}
|
||||
|
||||
private Instrumentation parseInstrumentation(Package owner, Resources res,
|
||||
|
||||
@@ -1534,6 +1534,14 @@
|
||||
of Android higher than the number given here, the permission will not
|
||||
be requested. -->
|
||||
<attr name="maxSdkVersion" format="integer" />
|
||||
<!-- Optional: the system must support this feature for the permission to be
|
||||
requested. If it doesn't support the feature, it will be as if the manifest didn't
|
||||
request it at all. -->
|
||||
<attr name="requiredFeature" format="string" />
|
||||
<!-- Optional: the system must NOT support this feature for the permission to be
|
||||
requested. If it does support the feature, it will be as if the manifest didn't
|
||||
request it at all. -->
|
||||
<attr name="requiredNotFeature" format="string" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>uses-configuration</code> tag specifies
|
||||
|
||||
@@ -2797,6 +2797,10 @@
|
||||
<public name="fontProviderAuthority" />
|
||||
<public name="fontProviderQuery" />
|
||||
<public name="autoFillMode" />
|
||||
<public name="primaryContentAlpha" />
|
||||
<public name="secondaryContentAlpha" />
|
||||
<public name="requiredFeature" />
|
||||
<public name="requiredNotFeature" />
|
||||
</public-group>
|
||||
|
||||
<public-group type="style" first-id="0x010302e0">
|
||||
@@ -2806,9 +2810,6 @@
|
||||
<public name="textAssist" />
|
||||
</public-group>
|
||||
|
||||
<public type="attr" name="primaryContentAlpha" />
|
||||
<public type="attr" name="secondaryContentAlpha" />
|
||||
|
||||
|
||||
<!-- ===============================================================
|
||||
DO NOT ADD UN-GROUPED ITEMS HERE
|
||||
|
||||
@@ -746,6 +746,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
@GuardedBy("mPackages")
|
||||
final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>();
|
||||
|
||||
final PackageParser.Callback mPackageParserCallback = new PackageParser.Callback() {
|
||||
@Override public boolean hasFeature(String feature) {
|
||||
return PackageManagerService.this.hasSystemFeature(feature, 0);
|
||||
}
|
||||
};
|
||||
|
||||
public static final class SharedLibraryEntry {
|
||||
public final String path;
|
||||
public final String apk;
|
||||
@@ -7584,7 +7590,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
+ " flags=0x" + Integer.toHexString(parseFlags));
|
||||
}
|
||||
ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
|
||||
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir);
|
||||
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback);
|
||||
|
||||
// Submit files for parsing in parallel
|
||||
int fileCount = 0;
|
||||
@@ -7753,6 +7759,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
pp.setSeparateProcesses(mSeparateProcesses);
|
||||
pp.setOnlyCoreApps(mOnlyCore);
|
||||
pp.setDisplayMetrics(mMetrics);
|
||||
pp.setCallback(mPackageParserCallback);
|
||||
|
||||
if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
|
||||
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
|
||||
@@ -9616,7 +9623,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
/**
|
||||
* Asserts the parsed package is valid according to the given policy. If the
|
||||
* package is invalid, for whatever reason, throws {@link PackgeManagerException}.
|
||||
* package is invalid, for whatever reason, throws {@link PackageManagerException}.
|
||||
* <p>
|
||||
* Implementation detail: This method must NOT have any side effects. It would
|
||||
* ideally be static, but, it requires locks to read system state.
|
||||
@@ -12814,7 +12821,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
* By having a field variable, we're able to track filter ordering as soon as
|
||||
* a non-zero order is defined. Otherwise, multiple loops across the result set
|
||||
* would be needed to apply ordering. If the intent resolver becomes re-entrant,
|
||||
* this needs to be contained entirely within {@link #filterResults()}.
|
||||
* this needs to be contained entirely within {@link #filterResults}.
|
||||
*/
|
||||
final ArrayMap<String, Pair<Integer, EphemeralResolveInfo>> mOrderResult = new ArrayMap<>();
|
||||
|
||||
@@ -16636,6 +16643,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
PackageParser pp = new PackageParser();
|
||||
pp.setSeparateProcesses(mSeparateProcesses);
|
||||
pp.setDisplayMetrics(mMetrics);
|
||||
pp.setCallback(mPackageParserCallback);
|
||||
|
||||
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
|
||||
final PackageParser.Package pkg;
|
||||
|
||||
@@ -46,6 +46,7 @@ class ParallelPackageParser implements AutoCloseable {
|
||||
private final boolean mOnlyCore;
|
||||
private final DisplayMetrics mMetrics;
|
||||
private final File mCacheDir;
|
||||
private final PackageParser.Callback mPackageParserCallback;
|
||||
private volatile String mInterruptedInThread;
|
||||
|
||||
private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
|
||||
@@ -54,11 +55,12 @@ class ParallelPackageParser implements AutoCloseable {
|
||||
"package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND);
|
||||
|
||||
ParallelPackageParser(String[] separateProcesses, boolean onlyCoreApps,
|
||||
DisplayMetrics metrics, File cacheDir) {
|
||||
DisplayMetrics metrics, File cacheDir, PackageParser.Callback callback) {
|
||||
mSeparateProcesses = separateProcesses;
|
||||
mOnlyCore = onlyCoreApps;
|
||||
mMetrics = metrics;
|
||||
mCacheDir = cacheDir;
|
||||
mPackageParserCallback = callback;
|
||||
}
|
||||
|
||||
static class ParseResult {
|
||||
@@ -110,6 +112,7 @@ class ParallelPackageParser implements AutoCloseable {
|
||||
pp.setOnlyCoreApps(mOnlyCore);
|
||||
pp.setDisplayMetrics(mMetrics);
|
||||
pp.setCacheDir(mCacheDir);
|
||||
pp.setCallback(mPackageParserCallback);
|
||||
pr.scanFile = scanFile;
|
||||
pr.pkg = parsePackage(pp, scanFile, parseFlags);
|
||||
} catch (Throwable e) {
|
||||
|
||||
@@ -69,7 +69,7 @@ public class ParallelPackageParserTest {
|
||||
class TestParallelPackageParser extends ParallelPackageParser {
|
||||
|
||||
TestParallelPackageParser() {
|
||||
super(null, false, null, null);
|
||||
super(null, false, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -309,6 +309,8 @@ enum {
|
||||
CATEGORY_ATTR = 0x010103e8,
|
||||
BANNER_ATTR = 0x10103f2,
|
||||
ISGAME_ATTR = 0x10103f4,
|
||||
REQUIRED_FEATURE_ATTR = 0x1010557,
|
||||
REQUIRED_NOT_FEATURE_ATTR = 0x1010558,
|
||||
};
|
||||
|
||||
String8 getComponentName(String8 &pkgName, String8 &componentName) {
|
||||
@@ -366,11 +368,19 @@ static void printCompatibleScreens(ResXMLTree& tree, String8* outError) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
|
||||
static void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1,
|
||||
const String8& requiredFeature = String8::empty(),
|
||||
const String8& requiredNotFeature = String8::empty()) {
|
||||
printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
|
||||
if (maxSdkVersion != -1) {
|
||||
printf(" maxSdkVersion='%d'", maxSdkVersion);
|
||||
}
|
||||
if (requiredFeature.length() > 0) {
|
||||
printf(" requiredFeature='%s'", requiredFeature.string());
|
||||
}
|
||||
if (requiredNotFeature.length() > 0) {
|
||||
printf(" requiredNotFeature='%s'", requiredNotFeature.string());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (optional) {
|
||||
@@ -1545,6 +1555,10 @@ int doDump(Bundle* bundle)
|
||||
|
||||
const int32_t maxSdkVersion =
|
||||
AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, -1);
|
||||
const String8 requiredFeature = AaptXml::getAttribute(tree,
|
||||
REQUIRED_FEATURE_ATTR, &error);
|
||||
const String8 requiredNotFeature = AaptXml::getAttribute(tree,
|
||||
REQUIRED_NOT_FEATURE_ATTR, &error);
|
||||
|
||||
if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
|
||||
hasWriteExternalStoragePermission = true;
|
||||
@@ -1565,7 +1579,7 @@ int doDump(Bundle* bundle)
|
||||
|
||||
printUsesPermission(name,
|
||||
AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
|
||||
maxSdkVersion);
|
||||
maxSdkVersion, requiredFeature, requiredNotFeature);
|
||||
|
||||
} else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") {
|
||||
String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
|
||||
|
||||
Reference in New Issue
Block a user