Merge changes from topic "appOpFeatureId"

* changes:
  Restrict the number of features or size of ids.
  Use Pools for noteOp related data objects
  Allow apps to define featureIds in the manifest
This commit is contained in:
Philip P. Moltmann
2020-01-03 20:31:01 +00:00
committed by Android (Google) Code Review
14 changed files with 964 additions and 190 deletions

View File

@@ -51,6 +51,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.Pools;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -2341,15 +2342,31 @@ public class AppOpsManager {
*/
@TestApi
@SystemApi
@Immutable
@DataClass(genHiddenConstructor = true)
// @DataClass(genHiddenConstructor = true, genHiddenCopyConstructor = true)
// genHiddenCopyConstructor does not work for @hide @SystemApi classes
public static final class OpEventProxyInfo implements Parcelable {
/** UID of the proxy app that noted the op */
private final @IntRange(from = 0) int mUid;
private @IntRange(from = 0) int mUid;
/** Package of the proxy that noted the op */
private final @Nullable String mPackageName;
private @Nullable String mPackageName;
/** ID of the feature of the proxy that noted the op */
private final @Nullable String mFeatureId;
private @Nullable String mFeatureId;
/**
* Reinit existing object with new state.
*
* @param uid UID of the proxy app that noted the op
* @param packageName Package of the proxy that noted the op
* @param featureId ID of the feature of the proxy that noted the op
*
* @hide
*/
public void reinit(@IntRange(from = 0) int uid, @Nullable String packageName,
@Nullable String featureId) {
mUid = Preconditions.checkArgumentNonnegative(uid);
mPackageName = packageName;
mFeatureId = featureId;
}
@@ -2392,6 +2409,18 @@ public class AppOpsManager {
// onConstructed(); // You can define this method to get a callback
}
/**
* Copy constructor
*
* @hide
*/
@DataClass.Generated.Member
public OpEventProxyInfo(@NonNull OpEventProxyInfo orig) {
mUid = orig.mUid;
mPackageName = orig.mPackageName;
mFeatureId = orig.mFeatureId;
}
/**
* UID of the proxy app that noted the op
*/
@@ -2471,14 +2500,15 @@ public class AppOpsManager {
}
};
/*
@DataClass.Generated(
time = 1576194071700L,
time = 1576814974615L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
inputSignatures = "private final @android.annotation.IntRange(from=0L) int mUid\nprivate final @android.annotation.Nullable java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nclass OpEventProxyInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
inputSignatures = "private @android.annotation.IntRange(from=0L) int mUid\nprivate @android.annotation.Nullable java.lang.String mPackageName\nprivate @android.annotation.Nullable java.lang.String mFeatureId\npublic void reinit(int,java.lang.String,java.lang.String)\nclass OpEventProxyInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genHiddenCopyConstructor=true)")
@Deprecated
private void __metadata() {}
*/
//@formatter:on
// End of generated code
@@ -2490,15 +2520,48 @@ public class AppOpsManager {
*
* @hide
*/
@Immutable
//@DataClass codegen verifier is broken
public static final class NoteOpEvent implements Parcelable {
/** Time of noteOp event */
public final @IntRange(from = 0) long noteTime;
private @IntRange(from = 0) long mNoteTime;
/** The duration of this event (in case this is a startOp event, -1 otherwise). */
public final @IntRange(from = -1) long duration;
private @IntRange(from = -1) long mDuration;
/** Proxy information of the noteOp event */
public final @Nullable OpEventProxyInfo proxy;
private @Nullable OpEventProxyInfo mProxy;
/**
* Reinit existing object with new state.
*
* @param noteTime Time of noteOp event
* @param duration The duration of this event (in case this is a startOp event,
* -1 otherwise).
* @param proxy Proxy information of the noteOp event
* @param proxyPool The pool to release previous {@link OpEventProxyInfo} to
*/
public void reinit(@IntRange(from = 0) long noteTime,
@IntRange(from = -1) long duration,
@Nullable OpEventProxyInfo proxy,
@NonNull Pools.Pool<OpEventProxyInfo> proxyPool) {
mNoteTime = Preconditions.checkArgumentNonnegative(noteTime);
mDuration = Preconditions.checkArgumentInRange(duration, -1L, Long.MAX_VALUE,
"duration");
if (mProxy != null) {
proxyPool.release(mProxy);
}
mProxy = proxy;
}
/**
* Copy constructor
*
* @hide
*/
public NoteOpEvent(@NonNull NoteOpEvent original) {
this(original.mNoteTime, original.mDuration,
original.mProxy != null ? new OpEventProxyInfo(original.mProxy) : null);
}
// Code below generated by codegen v1.0.14.
@@ -2529,19 +2592,43 @@ public class AppOpsManager {
@IntRange(from = 0) long noteTime,
@IntRange(from = -1) long duration,
@Nullable OpEventProxyInfo proxy) {
this.noteTime = noteTime;
this.mNoteTime = noteTime;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, noteTime,
IntRange.class, null, mNoteTime,
"from", 0);
this.duration = duration;
this.mDuration = duration;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, duration,
IntRange.class, null, mDuration,
"from", -1);
this.proxy = proxy;
this.mProxy = proxy;
// onConstructed(); // You can define this method to get a callback
}
/**
* Time of noteOp event
*/
@DataClass.Generated.Member
public @IntRange(from = 0) long getNoteTime() {
return mNoteTime;
}
/**
* The duration of this event (in case this is a startOp event, -1 otherwise).
*/
@DataClass.Generated.Member
public @IntRange(from = -1) long getDuration() {
return mDuration;
}
/**
* Proxy information of the noteOp event
*/
@DataClass.Generated.Member
public @Nullable OpEventProxyInfo getProxy() {
return mProxy;
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -2549,11 +2636,11 @@ public class AppOpsManager {
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
if (proxy != null) flg |= 0x4;
if (mProxy != null) flg |= 0x4;
dest.writeByte(flg);
dest.writeLong(noteTime);
dest.writeLong(duration);
if (proxy != null) dest.writeTypedObject(proxy, flags);
dest.writeLong(mNoteTime);
dest.writeLong(mDuration);
if (mProxy != null) dest.writeTypedObject(mProxy, flags);
}
@Override
@@ -2568,20 +2655,19 @@ public class AppOpsManager {
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
long _noteTime = in.readLong();
long _duration = in.readLong();
OpEventProxyInfo _proxy = (flg & 0x4) == 0 ? null : (OpEventProxyInfo) in.readTypedObject(
OpEventProxyInfo.CREATOR);
long noteTime = in.readLong();
long duration = in.readLong();
OpEventProxyInfo proxy = (flg & 0x4) == 0 ? null : (OpEventProxyInfo) in.readTypedObject(OpEventProxyInfo.CREATOR);
this.noteTime = _noteTime;
this.mNoteTime = noteTime;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, noteTime,
IntRange.class, null, mNoteTime,
"from", 0);
this.duration = _duration;
this.mDuration = duration;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, duration,
IntRange.class, null, mDuration,
"from", -1);
this.proxy = _proxy;
this.mProxy = proxy;
// onConstructed(); // You can define this method to get a callback
}
@@ -2602,10 +2688,10 @@ public class AppOpsManager {
/*
@DataClass.Generated(
time = 1574809856220L,
time = 1576811792274L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
inputSignatures = "public final @android.annotation.IntRange(from=0L) long noteTime\npublic final @android.annotation.IntRange(from=-1) long duration\npublic final @android.annotation.Nullable android.app.NoteOpEventProxyInfo proxy\nclass NoteOpEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
inputSignatures = "private @android.annotation.IntRange(from=0L) long mNoteTime\nprivate @android.annotation.IntRange(from=-1) long mDuration\nprivate @android.annotation.Nullable android.app.OpEventProxyInfo mProxy\npublic void reinit(long,long,android.app.OpEventProxyInfo,android.util.Pools.Pool<android.app.OpEventProxyInfo>)\npublic @java.lang.Override java.lang.Object clone()\nclass NoteOpEvent extends java.lang.Object implements [android.os.Parcelable, java.lang.Cloneable]\n@com.android.internal.util.DataClass")
@Deprecated
private void __metadata() {}
*/
@@ -2751,7 +2837,7 @@ public class AppOpsManager {
return -1;
}
return lastEvent.noteTime;
return lastEvent.getNoteTime();
}
/**
@@ -2847,7 +2933,7 @@ public class AppOpsManager {
return -1;
}
return lastEvent.noteTime;
return lastEvent.getNoteTime();
}
/**
@@ -2922,7 +3008,7 @@ public class AppOpsManager {
return -1;
}
return lastEvent.duration;
return lastEvent.getDuration();
}
/**
@@ -3000,7 +3086,7 @@ public class AppOpsManager {
return null;
}
return lastEvent.proxy;
return lastEvent.getProxy();
}
private static class LongSparseArrayParceling implements
@@ -3304,7 +3390,7 @@ public class AppOpsManager {
toUidState, flags);
if (lastAccessEvent == null || (lastFeatureAccessEvent != null
&& lastFeatureAccessEvent.noteTime > lastAccessEvent.noteTime)) {
&& lastFeatureAccessEvent.getNoteTime() > lastAccessEvent.getNoteTime())) {
lastAccessEvent = lastFeatureAccessEvent;
}
}
@@ -3335,7 +3421,7 @@ public class AppOpsManager {
return -1;
}
return lastEvent.noteTime;
return lastEvent.getNoteTime();
}
/**
@@ -3418,7 +3504,7 @@ public class AppOpsManager {
toUidState, flags);
if (lastAccessEvent == null || (lastFeatureAccessEvent != null
&& lastFeatureAccessEvent.noteTime > lastAccessEvent.noteTime)) {
&& lastFeatureAccessEvent.getNoteTime() > lastAccessEvent.getNoteTime())) {
lastAccessEvent = lastFeatureAccessEvent;
}
}
@@ -3449,7 +3535,7 @@ public class AppOpsManager {
return -1;
}
return lastEvent.noteTime;
return lastEvent.getNoteTime();
}
/**
@@ -3544,7 +3630,7 @@ public class AppOpsManager {
return -1;
}
return lastEvent.duration;
return lastEvent.getDuration();
}
/**
@@ -3674,7 +3760,7 @@ public class AppOpsManager {
return null;
}
return lastEvent.proxy;
return lastEvent.getProxy();
}
@@ -7331,7 +7417,8 @@ public class AppOpsManager {
final long key = makeKey(uidState, flag);
NoteOpEvent event = events.get(key);
if (lastEvent == null || event != null && event.noteTime > lastEvent.noteTime) {
if (lastEvent == null
|| event != null && event.getNoteTime() > lastEvent.getNoteTime()) {
lastEvent = event;
}
}

View File

@@ -202,6 +202,7 @@ public class PackageParser {
public static final String TAG_OVERLAY = "overlay";
public static final String TAG_PACKAGE = "package";
public static final String TAG_PACKAGE_VERIFIER = "package-verifier";
public static final String TAG_FEATURE = "feature";
public static final String TAG_PERMISSION = "permission";
public static final String TAG_PERMISSION_GROUP = "permission-group";
public static final String TAG_PERMISSION_TREE = "permission-tree";

View File

@@ -27,6 +27,7 @@ import android.content.pm.PackageUserState;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
@@ -244,6 +245,9 @@ public interface AndroidPackage extends Parcelable {
@Nullable
List<ParsedInstrumentation> getInstrumentations();
@Nullable
List<ParsedFeature> getFeatures();
@Nullable
List<ParsedPermissionGroup> getPermissionGroups();

View File

@@ -793,6 +793,10 @@ public class ApkParseUtils {
parseResult = parseKeySets(parseInput, parsingPackage, res, parser);
success = parseResult.isSuccess();
break;
case PackageParser.TAG_FEATURE:
parseResult = parseFeature(parseInput, parsingPackage, res, parser);
success = parseResult.isSuccess();
break;
case PackageParser.TAG_PERMISSION_GROUP:
parseResult = parsePermissionGroup(parseInput, parsingPackage, res,
parser);
@@ -880,6 +884,13 @@ public class ApkParseUtils {
);
}
if (!ComponentParseUtils.ParsedFeature.isCombinationValid(parsingPackage.getFeatures())) {
return parseInput.error(
INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Combination <feature> tags are not valid"
);
}
convertNewPermissions(parsingPackage);
convertSplitPermissions(parsingPackage);
@@ -1260,6 +1271,31 @@ public class ApkParseUtils {
return parseInput.success(parsingPackage);
}
private static ParseResult parseFeature(
ParseInput parseInput,
ParsingPackage parsingPackage,
Resources res,
XmlResourceParser parser
) throws IOException, XmlPullParserException {
// TODO(b/135203078): Remove, replace with ParseResult
String[] outError = new String[1];
ComponentParseUtils.ParsedFeature parsedFeature =
ComponentParseUtils.parseFeature(res, parser, outError);
if (parsedFeature == null || outError[0] != null) {
return parseInput.error(
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
outError[0]
);
}
parsingPackage.addFeature(parsedFeature);
return parseInput.success(parsingPackage);
}
private static ParseResult parsePermissionGroup(
ParseInput parseInput,
ParsingPackage parsingPackage,

View File

@@ -24,6 +24,9 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
@@ -47,6 +50,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -54,6 +58,7 @@ import android.util.TypedValue;
import android.view.Gravity;
import com.android.internal.R;
import com.android.internal.util.DataClass;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -62,6 +67,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@@ -931,6 +937,186 @@ public class ComponentParseUtils {
};
}
/**
* A {@link android.R.styleable#AndroidManifestFeature &lt;feature&gt;} tag parsed from the
* manifest.
*/
// @DataClass verifier is broken, hence comment out for now
public static class ParsedFeature implements Parcelable {
/** Maximum length of featureId */
public static final int MAX_FEATURE_ID_LEN = 50;
/** Maximum amount of features per package */
private static final int MAX_NUM_FEATURES = 1000;
/** Id of the feature */
public final @NonNull String id;
/** User visible label fo the feature */
public final @StringRes int label;
/** Ids of previously declared features this feature inherits from */
public final @NonNull List<String> inheritFrom;
/**
* @return Is this set of features a valid combination for a single package?
*/
public static boolean isCombinationValid(@Nullable List<ParsedFeature> features) {
if (features == null) {
return true;
}
ArraySet<String> featureIds = new ArraySet<>(features.size());
ArraySet<String> inheritFromFeatureIds = new ArraySet<>();
int numFeatures = features.size();
if (numFeatures > MAX_NUM_FEATURES) {
return false;
}
for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
boolean wasAdded = featureIds.add(features.get(featureNum).id);
if (!wasAdded) {
// feature id is not unique
return false;
}
}
for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
ParsedFeature feature = features.get(featureNum);
int numInheritFrom = feature.inheritFrom.size();
for (int inheritFromNum = 0; inheritFromNum < numInheritFrom; inheritFromNum++) {
String inheritFrom = feature.inheritFrom.get(inheritFromNum);
if (featureIds.contains(inheritFrom)) {
// Cannot inherit from a feature that is still defined
return false;
}
boolean wasAdded = inheritFromFeatureIds.add(inheritFrom);
if (!wasAdded) {
// inheritFrom is not unique
return false;
}
}
}
return true;
}
// Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/ComponentParseUtils.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
//@formatter:off
/**
* Creates a new ParsedFeature.
*
* @param id
* Id of the feature
* @param label
* User visible label fo the feature (if defined as resource)
* @param inheritFrom
* Ids of previously declared features this feature inherits from
*/
@DataClass.Generated.Member
public ParsedFeature(
@NonNull String id,
@StringRes int label,
@NonNull List<String> inheritFrom) {
this.id = id;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, id);
this.label = label;
com.android.internal.util.AnnotationValidations.validate(
StringRes.class, null, label);
this.inheritFrom = inheritFrom;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, inheritFrom);
// onConstructed(); // You can define this method to get a callback
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
dest.writeString(id);
dest.writeInt(label);
dest.writeStringList(inheritFrom);
}
@Override
@DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
protected ParsedFeature(@NonNull Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
String _id = in.readString();
int _label = in.readInt();
List<String> _inheritFrom = new ArrayList<>();
in.readStringList(_inheritFrom);
this.id = _id;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, id);
this.label = _label;
com.android.internal.util.AnnotationValidations.validate(
StringRes.class, null, label);
this.inheritFrom = _inheritFrom;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, inheritFrom);
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
public static final @NonNull Parcelable.Creator<ParsedFeature> CREATOR
= new Parcelable.Creator<ParsedFeature>() {
@Override
public ParsedFeature[] newArray(int size) {
return new ParsedFeature[size];
}
@Override
public ParsedFeature createFromParcel(@NonNull Parcel in) {
return new ParsedFeature(in);
}
};
/*@DataClass.Generated(
time = 1576783172965L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ComponentParseUtils.java",
inputSignatures = "public final @android.annotation.NonNull java.lang.String id\npublic final @android.annotation.StringRes int label\npublic final @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\npublic static boolean isCombinationValid(java.util.List<android.content.pm.parsing.ParsedFeature>)\nclass ParsedFeature extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
*/
@Deprecated
private void __metadata() {}
//@formatter:on
// End of generated code
}
public static class ParsedPermission extends ParsedComponent<ParsedIntentInfo> {
public String backgroundPermission;
@@ -2566,6 +2752,85 @@ public class ComponentParseUtils {
return result;
}
public static ParsedFeature parseFeature(
Resources res,
XmlResourceParser parser,
String[] outError
) throws IOException, XmlPullParserException {
String featureId;
int label;
List<String> inheritFrom = null;
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeature);
if (sa == null) {
outError[0] = "<feature> could not be parsed";
return null;
}
try {
featureId = sa.getNonConfigurationString(R.styleable.AndroidManifestFeature_featureId,
0);
if (featureId == null) {
outError[0] = "<featureId> does not specify android:featureId";
return null;
}
if (featureId.length() > ParsedFeature.MAX_FEATURE_ID_LEN) {
outError[0] = "<featureId> is too long. Max length is "
+ ParsedFeature.MAX_FEATURE_ID_LEN;
return null;
}
label = sa.getResourceId(R.styleable.AndroidManifestFeature_label, 0);
if (label == Resources.ID_NULL) {
outError[0] = "<featureId> does not specify android:label";
return null;
}
} finally {
sa.recycle();
}
int type;
final int innerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("inherit-from")) {
sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeatureInheritFrom);
if (sa == null) {
outError[0] = "<inherit-from> could not be parsed";
return null;
}
try {
String inheritFromId = sa.getNonConfigurationString(
R.styleable.AndroidManifestFeatureInheritFrom_featureId,0);
if (inheritFrom == null) {
inheritFrom = new ArrayList<>();
}
inheritFrom.add(inheritFromId);
} finally {
sa.recycle();
}
} else {
outError[0] = "Bad element under <feature>: " + tagName;
return null;
}
}
if (inheritFrom == null) {
inheritFrom = Collections.emptyList();
} else {
((ArrayList) inheritFrom).trimToSize();
}
return new ParsedFeature(featureId, label, inheritFrom);
}
public static ParsedPermission parsePermission(
ParsingPackage parsingPackage,
Resources res,

View File

@@ -36,6 +36,7 @@ import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
@@ -174,6 +175,9 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
@Nullable
private ArrayList<ComponentParseUtils.ParsedProvider> providers;
@Nullable
private ArrayList<ComponentParseUtils.ParsedFeature> features;
@Nullable
private ArrayList<ComponentParseUtils.ParsedPermission> permissions;
@@ -580,6 +584,12 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
return permissions;
}
@Nullable
@Override
public List<ParsedFeature> getFeatures() {
return features;
}
@Override
public String getCpuAbiOverride() {
return cpuAbiOverride;
@@ -791,6 +801,12 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
return this;
}
@Override
public PackageImpl addFeature(ParsedFeature feature) {
this.features = ArrayUtils.add(this.features, feature);
return this;
}
@Override
public PackageImpl addPermission(ParsedPermission permission) {
this.permissions = ArrayUtils.add(this.permissions, permission);
@@ -3021,6 +3037,7 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
dest.writeTypedList(this.receivers);
dest.writeTypedList(this.services);
dest.writeTypedList(this.providers);
dest.writeTypedList(this.features);
dest.writeTypedList(this.permissions);
dest.writeTypedList(this.permissionGroups);
dest.writeTypedList(this.instrumentations);
@@ -3173,6 +3190,7 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
this.receivers = in.createTypedArrayList(ParsedActivity.CREATOR);
this.services = in.createTypedArrayList(ParsedService.CREATOR);
this.providers = in.createTypedArrayList(ParsedProvider.CREATOR);
this.features = in.createTypedArrayList(ParsedFeature.CREATOR);
this.permissions = in.createTypedArrayList(ParsedPermission.CREATOR);
this.permissionGroups = in.createTypedArrayList(ParsedPermissionGroup.CREATOR);
this.instrumentations = in.createTypedArrayList(ParsedInstrumentation.CREATOR);

View File

@@ -24,6 +24,7 @@ import android.content.pm.FeatureInfo;
import android.content.pm.PackageParser;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
@@ -64,6 +65,8 @@ public interface ParsingPackage extends AndroidPackage {
ParsingPackage addOverlayable(String overlayableName, String actorName);
ParsingPackage addFeature(ParsedFeature permission);
ParsingPackage addPermission(ParsedPermission permission);
ParsingPackage addPermissionGroup(ParsedPermissionGroup permissionGroup);