Merge "Add apex-system-service tag to AndroidManifest."

This commit is contained in:
Artur Satayev
2021-12-10 13:08:42 +00:00
committed by Android (Google) Code Review
12 changed files with 444 additions and 12 deletions

View File

@@ -27,6 +27,7 @@ import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager.Property;
import android.content.pm.SigningDetails;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedApexSystemService;
import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
@@ -56,6 +57,8 @@ public interface ParsingPackage extends ParsingPackageRead {
ParsingPackage addAdoptPermission(String adoptPermission);
ParsingPackage addApexSystemService(ParsedApexSystemService parsedApexSystemService);
ParsingPackage addConfigPreference(ConfigurationInfo configPreference);
ParsingPackage addFeatureGroup(FeatureGroupInfo featureGroup);

View File

@@ -35,6 +35,8 @@ import android.content.pm.PackageManager.Property;
import android.content.pm.SigningDetails;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedActivityImpl;
import android.content.pm.parsing.component.ParsedApexSystemService;
import android.content.pm.parsing.component.ParsedApexSystemServiceImpl;
import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedAttributionImpl;
import android.content.pm.parsing.component.ParsedComponent;
@@ -267,6 +269,9 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
@NonNull
protected List<ParsedActivity> activities = emptyList();
@NonNull
protected List<ParsedApexSystemService> apexSystemServices = emptyList();
@NonNull
protected List<ParsedActivity> receivers = emptyList();
@@ -763,6 +768,14 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
return this;
}
@Override
public final ParsingPackageImpl addApexSystemService(
ParsedApexSystemService parsedApexSystemService) {
this.apexSystemServices = CollectionUtils.add(
this.apexSystemServices, parsedApexSystemService);
return this;
}
@Override
public ParsingPackageImpl addReceiver(ParsedActivity parsedReceiver) {
this.receivers = CollectionUtils.add(this.receivers, parsedReceiver);
@@ -832,7 +845,6 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
return this;
}
@Override public ParsingPackageImpl removeUsesOptionalNativeLibrary(String libraryName) {
this.usesOptionalNativeLibraries = CollectionUtils.remove(this.usesOptionalNativeLibraries,
libraryName);
@@ -1198,6 +1210,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
ParsingPackageUtils.writeKeySetMapping(dest, this.keySetMapping);
sForInternedStringList.parcel(this.protectedBroadcasts, dest, flags);
dest.writeTypedList(this.activities);
dest.writeTypedList(this.apexSystemServices);
dest.writeTypedList(this.receivers);
dest.writeTypedList(this.services);
dest.writeTypedList(this.providers);
@@ -1339,6 +1352,8 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
this.protectedBroadcasts = sForInternedStringList.unparcel(in);
this.activities = ParsingUtils.createTypedInterfaceList(in, ParsedActivityImpl.CREATOR);
this.apexSystemServices = ParsingUtils.createTypedInterfaceList(in,
ParsedApexSystemServiceImpl.CREATOR);
this.receivers = ParsingUtils.createTypedInterfaceList(in, ParsedActivityImpl.CREATOR);
this.services = ParsingUtils.createTypedInterfaceList(in, ParsedServiceImpl.CREATOR);
this.providers = ParsingUtils.createTypedInterfaceList(in, ParsedProviderImpl.CREATOR);
@@ -1704,6 +1719,12 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
return activities;
}
@NonNull
@Override
public List<ParsedApexSystemService> getApexSystemServices() {
return apexSystemServices;
}
@NonNull
@Override
public List<ParsedActivity> getReceivers() {

View File

@@ -23,6 +23,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.Property;
import android.content.pm.PackageParser;
import android.content.pm.SigningDetails;
import android.content.pm.parsing.component.ParsedApexSystemService;
import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedPermissionGroup;
@@ -55,6 +56,12 @@ public interface ParsingPackageRead extends PkgWithoutStateAppInfo, PkgWithoutSt
@NonNull
List<String> getAdoptPermissions();
/**
* @see R.styleable#AndroidManifestApexSystemService
*/
@NonNull
List<ParsedApexSystemService> getApexSystemServices();
@NonNull
List<ParsedAttribution> getAttributions();

View File

@@ -53,6 +53,8 @@ import android.content.pm.parsing.component.ComponentMutateUtils;
import android.content.pm.parsing.component.ComponentParseUtils;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedActivityUtils;
import android.content.pm.parsing.component.ParsedApexSystemService;
import android.content.pm.parsing.component.ParsedApexSystemServiceUtils;
import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedAttributionUtils;
import android.content.pm.parsing.component.ParsedComponent;
@@ -2205,6 +2207,18 @@ public class ParsingPackageUtils {
result = activityResult;
break;
case "apex-system-service":
ParseResult<ParsedApexSystemService> systemServiceResult =
ParsedApexSystemServiceUtils.parseApexSystemService(res,
parser, input);
if (systemServiceResult.isSuccess()) {
ParsedApexSystemService systemService =
systemServiceResult.getResult();
pkg.addApexSystemService(systemService);
}
result = systemServiceResult;
break;
default:
result = parseBaseAppChildTag(input, tagName, pkg, res, parser, flags);
break;

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content.pm.parsing.component;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcelable;
/** @hide */
public interface ParsedApexSystemService extends Parcelable {
@NonNull
String getName();
@Nullable
String getJarPath();
@Nullable
String getMinSdkVersion();
@Nullable
String getMaxSdkVersion();
}

View File

@@ -0,0 +1,241 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content.pm.parsing.component;
import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
/** @hide **/
@DataClass(genGetters = true, genAidl = false, genSetters = true, genParcelable = true)
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class ParsedApexSystemServiceImpl implements ParsedApexSystemService {
@DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedString.class)
@NonNull
private String name;
@DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedString.class)
@Nullable
private String jarPath;
@DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedString.class)
@Nullable
private String minSdkVersion;
@DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedString.class)
@Nullable
private String maxSdkVersion;
public ParsedApexSystemServiceImpl() {
}
// Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedApexSystemServiceImpl.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
//@formatter:off
@DataClass.Generated.Member
public ParsedApexSystemServiceImpl(
@NonNull String name,
@Nullable String jarPath,
@Nullable String minSdkVersion,
@Nullable String maxSdkVersion) {
this.name = name;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, name);
this.jarPath = jarPath;
this.minSdkVersion = minSdkVersion;
this.maxSdkVersion = maxSdkVersion;
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
public @NonNull String getName() {
return name;
}
@DataClass.Generated.Member
public @Nullable String getJarPath() {
return jarPath;
}
@DataClass.Generated.Member
public @Nullable String getMinSdkVersion() {
return minSdkVersion;
}
@DataClass.Generated.Member
public @Nullable String getMaxSdkVersion() {
return maxSdkVersion;
}
@DataClass.Generated.Member
public @NonNull ParsedApexSystemServiceImpl setName(@NonNull String value) {
name = value;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, name);
return this;
}
@DataClass.Generated.Member
public @NonNull ParsedApexSystemServiceImpl setJarPath(@NonNull String value) {
jarPath = value;
return this;
}
@DataClass.Generated.Member
public @NonNull ParsedApexSystemServiceImpl setMinSdkVersion(@NonNull String value) {
minSdkVersion = value;
return this;
}
@DataClass.Generated.Member
public @NonNull ParsedApexSystemServiceImpl setMaxSdkVersion(@NonNull String value) {
maxSdkVersion = value;
return this;
}
@DataClass.Generated.Member
static Parcelling<String> sParcellingForName =
Parcelling.Cache.get(
Parcelling.BuiltIn.ForInternedString.class);
static {
if (sParcellingForName == null) {
sParcellingForName = Parcelling.Cache.put(
new Parcelling.BuiltIn.ForInternedString());
}
}
@DataClass.Generated.Member
static Parcelling<String> sParcellingForJarPath =
Parcelling.Cache.get(
Parcelling.BuiltIn.ForInternedString.class);
static {
if (sParcellingForJarPath == null) {
sParcellingForJarPath = Parcelling.Cache.put(
new Parcelling.BuiltIn.ForInternedString());
}
}
@DataClass.Generated.Member
static Parcelling<String> sParcellingForMinSdkVersion =
Parcelling.Cache.get(
Parcelling.BuiltIn.ForInternedString.class);
static {
if (sParcellingForMinSdkVersion == null) {
sParcellingForMinSdkVersion = Parcelling.Cache.put(
new Parcelling.BuiltIn.ForInternedString());
}
}
@DataClass.Generated.Member
static Parcelling<String> sParcellingForMaxSdkVersion =
Parcelling.Cache.get(
Parcelling.BuiltIn.ForInternedString.class);
static {
if (sParcellingForMaxSdkVersion == null) {
sParcellingForMaxSdkVersion = Parcelling.Cache.put(
new Parcelling.BuiltIn.ForInternedString());
}
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
if (jarPath != null) flg |= 0x2;
if (minSdkVersion != null) flg |= 0x4;
if (maxSdkVersion != null) flg |= 0x8;
dest.writeByte(flg);
sParcellingForName.parcel(name, dest, flags);
sParcellingForJarPath.parcel(jarPath, dest, flags);
sParcellingForMinSdkVersion.parcel(minSdkVersion, dest, flags);
sParcellingForMaxSdkVersion.parcel(maxSdkVersion, dest, flags);
}
@Override
@DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
protected ParsedApexSystemServiceImpl(@NonNull android.os.Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
String _name = sParcellingForName.unparcel(in);
String _jarPath = sParcellingForJarPath.unparcel(in);
String _minSdkVersion = sParcellingForMinSdkVersion.unparcel(in);
String _maxSdkVersion = sParcellingForMaxSdkVersion.unparcel(in);
this.name = _name;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, name);
this.jarPath = _jarPath;
this.minSdkVersion = _minSdkVersion;
this.maxSdkVersion = _maxSdkVersion;
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
public static final @NonNull android.os.Parcelable.Creator<ParsedApexSystemServiceImpl> CREATOR
= new android.os.Parcelable.Creator<ParsedApexSystemServiceImpl>() {
@Override
public ParsedApexSystemServiceImpl[] newArray(int size) {
return new ParsedApexSystemServiceImpl[size];
}
@Override
public ParsedApexSystemServiceImpl createFromParcel(@NonNull android.os.Parcel in) {
return new ParsedApexSystemServiceImpl(in);
}
};
@DataClass.Generated(
time = 1638903241144L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedApexSystemServiceImpl.java",
inputSignatures = "private @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.NonNull java.lang.String name\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.Nullable java.lang.String jarPath\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.Nullable java.lang.String minSdkVersion\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.Nullable java.lang.String maxSdkVersion\nclass ParsedApexSystemServiceImpl extends java.lang.Object implements [android.content.pm.parsing.component.ParsedApexSystemService]\n@com.android.internal.util.DataClass(genGetters=true, genAidl=false, genSetters=true, genParcelable=true)")
@Deprecated
private void __metadata() {}
//@formatter:on
// End of generated code
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content.pm.parsing.component;
import android.R;
import android.annotation.NonNull;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.text.TextUtils;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
/** @hide */
public class ParsedApexSystemServiceUtils {
@NonNull
public static ParseResult<ParsedApexSystemService> parseApexSystemService(
Resources res, XmlResourceParser parser, ParseInput input)
throws XmlPullParserException, IOException {
final ParsedApexSystemServiceImpl systemService =
new ParsedApexSystemServiceImpl();
TypedArray sa = res.obtainAttributes(parser,
R.styleable.AndroidManifestApexSystemService);
try {
String className = sa.getString(
R.styleable.AndroidManifestApexSystemService_name);
if (TextUtils.isEmpty(className)) {
return input.error("<apex-system-service> does not have name attribute");
}
String jarPath = sa.getString(
R.styleable.AndroidManifestApexSystemService_path);
String minSdkVersion = sa.getString(
R.styleable.AndroidManifestApexSystemService_minSdkVersion);
String maxSdkVersion = sa.getString(
R.styleable.AndroidManifestApexSystemService_maxSdkVersion);
systemService.setName(className)
.setMinSdkVersion(minSdkVersion)
.setMaxSdkVersion(maxSdkVersion);
if (!TextUtils.isEmpty(jarPath)) {
systemService.setJarPath(jarPath);
}
return input.success(systemService);
} finally {
sa.recycle();
}
}
}

View File

@@ -2808,6 +2808,22 @@
<attr name="attributionTags" />
</declare-styleable>
<!-- @hide The <code>apex-system-service</code> tag declares an apex system service
that is contained within an application.
The apex system service tag appears as a child tag of the
{@link #AndroidManifestApplication application} tag. -->
<declare-styleable name="AndroidManifestApexSystemService"
parent="AndroidManifestApplication">
<!-- The fully qualified class name of the system service. -->
<attr name="name" />
<!-- The filepath to the .jar that contains the system service. If this is not provided, it
is assumed that the system service exists in SYSTEMSERVERCLASSPATH. -->
<attr name="path" />
<attr name="minSdkVersion" />
<attr name="maxSdkVersion" />
</declare-styleable>
<!-- The <code>receiver</code> tag declares an
{@link android.content.BroadcastReceiver} class that is available
as part of the package's application components, allowing the
@@ -3051,6 +3067,7 @@
<declare-styleable name="AndroidManifestMetaData"
parent="AndroidManifestApplication
AndroidManifestActivity
AndroidManifestApexSystemService
AndroidManifestReceiver
AndroidManifestProvider
AndroidManifestService
@@ -3085,6 +3102,7 @@
<declare-styleable name="AndroidManifestProperty"
parent="AndroidManifestApplication
AndroidManifestActivity
AndroidManifestApexSystemService
AndroidManifestReceiver
AndroidManifestProvider
AndroidManifestService">

View File

@@ -24,17 +24,7 @@ import android.content.pm.FeatureInfo
import android.content.pm.PackageManager
import android.content.pm.SigningDetails
import android.content.pm.parsing.ParsingPackage
import android.content.pm.parsing.component.ParsedActivityImpl
import android.content.pm.parsing.component.ParsedAttributionImpl
import android.content.pm.parsing.component.ParsedComponentImpl
import android.content.pm.parsing.component.ParsedInstrumentationImpl
import android.content.pm.parsing.component.ParsedIntentInfoImpl
import android.content.pm.parsing.component.ParsedPermissionGroupImpl
import android.content.pm.parsing.component.ParsedPermissionImpl
import android.content.pm.parsing.component.ParsedProcessImpl
import android.content.pm.parsing.component.ParsedProviderImpl
import android.content.pm.parsing.component.ParsedServiceImpl
import android.content.pm.parsing.component.ParsedUsesPermissionImpl
import android.content.pm.parsing.component.*
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
@@ -359,6 +349,13 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedActivityImpl().apply { name = it }.withMimeGroups() }
),
getSetByValue(
AndroidPackage::getApexSystemServices,
PackageImpl::addApexSystemService,
"TestApexSystemServiceName",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedApexSystemServiceImpl().apply { name = it } }
),
getSetByValue(
AndroidPackage::getReceivers,
PackageImpl::addReceiver,

View File

@@ -46,6 +46,7 @@ import android.content.pm.SigningDetails;
import android.content.pm.parsing.ParsingPackage;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedActivityImpl;
import android.content.pm.parsing.component.ParsedApexSystemService;
import android.content.pm.parsing.component.ParsedComponent;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedInstrumentationImpl;
@@ -525,6 +526,23 @@ public class PackageParserTest {
}
}
@Test
public void testParseApexSystemService() throws Exception {
final File testFile = extractFile(TEST_APP4_APK);
try {
final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false);
final List<ParsedApexSystemService> systemServices = pkg.getApexSystemServices();
for (ParsedApexSystemService systemService: systemServices) {
assertEquals(PACKAGE_NAME + ".SystemService", systemService.getName());
assertEquals("service-test.jar", systemService.getJarPath());
assertEquals("30", systemService.getMinSdkVersion());
assertEquals("31", systemService.getMaxSdkVersion());
}
} finally {
testFile.delete();
}
}
@Test
public void testParseModernPackageHasNoCompatPermissions() throws Exception {
final File testFile = extractFile(TEST_APP1_APK);

View File

@@ -57,6 +57,11 @@
<property android:name="android.cts.PROPERTY_SERVICE" android:value="@integer/integer_property" />
<property android:name="android.cts.PROPERTY_COMPONENT" android:resource="@integer/integer_property" />
</service>
<apex-system-service
android:name="com.android.servicestests.apps.packageparserapp.SystemService"
android:path="service-test.jar"
android:minSdkVersion = "30"
android:maxSdkVersion = "31" />
</application>
<instrumentation

View File

@@ -544,6 +544,7 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
application_action["activity-alias"] = component_action;
application_action["service"] = component_action;
application_action["receiver"] = component_action;
application_action["apex-system-service"] = component_action;
// Provider actions.
application_action["provider"] = component_action;