Revert "Revert "Revert "Introduce initOrder for apex-system-services."""

This reverts commit 5a38385882.

Reason for revert: DroidMonitor: Potential culprit for Bug 217580573 - verified through ABTD:
https://android-build.googleplex.com/builds/abtd/run/L65800000952890870

Change-Id: Ib9fdb4af623c93cd445d1031e57716b1df0f708e
This commit is contained in:
Muhammad Qureshi
2022-02-02 21:03:51 +00:00
parent 5a38385882
commit 00029af7e0
14 changed files with 43 additions and 234 deletions

View File

@@ -2839,14 +2839,6 @@
<attr name="path" />
<attr name="minSdkVersion" />
<attr name="maxSdkVersion" />
<!-- The order in which the apex system services are initiated. When there are dependencies
among apex system services, setting this attribute for each of them ensures that they are
created in the order required by those dependencies. The apex-system-services that are
started manually within SystemServer ignore the initOrder and are not considered for
automatic starting of the other services.
The value is a simple integer, with higher number being initialized first. If not specified,
the default order is 0. -->
<attr name="initOrder" format="integer" />
</declare-styleable>
<!-- The <code>receiver</code> tag declares an

View File

@@ -32,6 +32,9 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.SigningDetails;
import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.pm.pkg.component.ParsedApexSystemService;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.os.Binder;
@@ -56,9 +59,6 @@ import com.android.modules.utils.build.UnboundedSdkLevel;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.pkg.component.ParsedApexSystemService;
import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.utils.TimingsTraceAndSlog;
import com.google.android.collect.Lists;
@@ -414,11 +414,9 @@ public abstract class ApexManager {
throws PackageManagerException;
/**
* Get a list of apex system services implemented in an apex.
*
* <p>The list is sorted by initOrder for consistency.
* Get a map of system services defined in an apex mapped to the jar files they reside in.
*/
public abstract List<ApexSystemServiceInfo> getApexSystemServices();
public abstract Map<String, String> getApexSystemServices();
/**
* Dumps various state information to the provided {@link PrintWriter} object.
@@ -451,7 +449,7 @@ public abstract class ApexManager {
* Map of all apex system services to the jar files they are contained in.
*/
@GuardedBy("mLock")
private List<ApexSystemServiceInfo> mApexSystemServices = new ArrayList<>();
private Map<String, String> mApexSystemServices = new ArrayMap<>();
/**
* Contains the list of {@code packageName}s of apks-in-apex for given
@@ -607,19 +605,14 @@ public abstract class ApexManager {
}
String name = service.getName();
for (ApexSystemServiceInfo info : mApexSystemServices) {
if (info.getName().equals(name)) {
throw new IllegalStateException(String.format(
"Duplicate apex-system-service %s from %s, %s",
name, info.mJarPath, service.getJarPath()));
}
if (mApexSystemServices.containsKey(name)) {
throw new IllegalStateException(String.format(
"Duplicate apex-system-service %s from %s, %s",
name, mApexSystemServices.get(name), service.getJarPath()));
}
ApexSystemServiceInfo info = new ApexSystemServiceInfo(
service.getName(), service.getJarPath(), service.getInitOrder());
mApexSystemServices.add(info);
mApexSystemServices.put(name, service.getJarPath());
}
Collections.sort(mApexSystemServices);
mPackageNameToApexModuleName.put(packageInfo.packageName, ai.moduleName);
if (ai.isActive) {
if (activePackagesSet.contains(packageInfo.packageName)) {
@@ -1140,7 +1133,7 @@ public abstract class ApexManager {
}
@Override
public List<ApexSystemServiceInfo> getApexSystemServices() {
public Map<String, String> getApexSystemServices() {
synchronized (mLock) {
Preconditions.checkState(mApexSystemServices != null,
"APEX packages have not been scanned");
@@ -1430,10 +1423,10 @@ public abstract class ApexManager {
}
@Override
public List<ApexSystemServiceInfo> getApexSystemServices() {
public Map<String, String> getApexSystemServices() {
// TODO(satayev): we can't really support flattened apex use case, and need to migrate
// the manifest entries into system's manifest asap.
return Collections.emptyList();
return Collections.emptyMap();
}
@Override

View File

@@ -1,58 +0,0 @@
/*
* Copyright (C) 2022 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 com.android.server.pm;
import android.annotation.Nullable;
/**
* A helper class that contains information about apex-system-service to be used within system
* server process.
*/
public final class ApexSystemServiceInfo implements Comparable<ApexSystemServiceInfo> {
final String mName;
@Nullable
final String mJarPath;
final int mInitOrder;
public ApexSystemServiceInfo(String name, String jarPath, int initOrder) {
this.mName = name;
this.mJarPath = jarPath;
this.mInitOrder = initOrder;
}
public String getName() {
return mName;
}
public String getJarPath() {
return mJarPath;
}
public int getInitOrder() {
return mInitOrder;
}
@Override
public int compareTo(ApexSystemServiceInfo other) {
if (mInitOrder == other.mInitOrder) {
return mName.compareTo(other.mName);
}
// higher initOrder values take precedence
return -Integer.compare(mInitOrder, other.mInitOrder);
}
}

View File

@@ -34,7 +34,4 @@ public interface ParsedApexSystemService {
@Nullable
String getMaxSdkVersion();
int getInitOrder();
}

View File

@@ -48,18 +48,18 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
@Nullable
private String maxSdkVersion;
private int initOrder;
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/services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceImpl.java
// $ 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
@@ -71,15 +71,13 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
@NonNull String name,
@Nullable String jarPath,
@Nullable String minSdkVersion,
@Nullable String maxSdkVersion,
int initOrder) {
@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;
this.initOrder = initOrder;
// onConstructed(); // You can define this method to get a callback
}
@@ -104,11 +102,6 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
return maxSdkVersion;
}
@DataClass.Generated.Member
public int getInitOrder() {
return initOrder;
}
@DataClass.Generated.Member
public @NonNull ParsedApexSystemServiceImpl setName(@NonNull String value) {
name = value;
@@ -135,12 +128,6 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
return this;
}
@DataClass.Generated.Member
public @NonNull ParsedApexSystemServiceImpl setInitOrder( int value) {
initOrder = value;
return this;
}
@DataClass.Generated.Member
static Parcelling<String> sParcellingForName =
Parcelling.Cache.get(
@@ -200,7 +187,6 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
sParcellingForJarPath.parcel(jarPath, dest, flags);
sParcellingForMinSdkVersion.parcel(minSdkVersion, dest, flags);
sParcellingForMaxSdkVersion.parcel(maxSdkVersion, dest, flags);
dest.writeInt(initOrder);
}
@Override
@@ -219,7 +205,6 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
String _jarPath = sParcellingForJarPath.unparcel(in);
String _minSdkVersion = sParcellingForMinSdkVersion.unparcel(in);
String _maxSdkVersion = sParcellingForMaxSdkVersion.unparcel(in);
int _initOrder = in.readInt();
this.name = _name;
com.android.internal.util.AnnotationValidations.validate(
@@ -227,7 +212,6 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
this.jarPath = _jarPath;
this.minSdkVersion = _minSdkVersion;
this.maxSdkVersion = _maxSdkVersion;
this.initOrder = _initOrder;
// onConstructed(); // You can define this method to get a callback
}
@@ -247,10 +231,10 @@ public class ParsedApexSystemServiceImpl implements ParsedApexSystemService, Par
};
@DataClass.Generated(
time = 1643723578605L,
time = 1641431950080L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/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\nprivate int initOrder\nclass ParsedApexSystemServiceImpl extends java.lang.Object implements [com.android.server.pm.pkg.component.ParsedApexSystemService, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genAidl=false, genSetters=true, genParcelable=true)")
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, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genAidl=false, genSetters=true, genParcelable=true)")
@Deprecated
private void __metadata() {}

View File

@@ -53,13 +53,10 @@ public class ParsedApexSystemServiceUtils {
R.styleable.AndroidManifestApexSystemService_minSdkVersion);
String maxSdkVersion = sa.getString(
R.styleable.AndroidManifestApexSystemService_maxSdkVersion);
int initOrder = sa.getInt(R.styleable.AndroidManifestApexSystemService_initOrder, 0);
systemService.setName(className)
.setMinSdkVersion(minSdkVersion)
.setMaxSdkVersion(maxSdkVersion)
.setInitOrder(initOrder);
.setMaxSdkVersion(maxSdkVersion);
if (!TextUtils.isEmpty(jarPath)) {
systemService.setJarPath(jarPath);
}

View File

@@ -154,7 +154,6 @@ import com.android.server.os.NativeTombstoneManagerService;
import com.android.server.os.SchedulingPolicyService;
import com.android.server.people.PeopleService;
import com.android.server.pm.ApexManager;
import com.android.server.pm.ApexSystemServiceInfo;
import com.android.server.pm.CrossProfileAppsService;
import com.android.server.pm.DataLoaderManagerService;
import com.android.server.pm.DynamicCodeLoggingService;
@@ -225,8 +224,8 @@ import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Timer;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
@@ -1471,7 +1470,7 @@ public final class SystemServer implements Dumpable {
// TelecomLoader hooks into classes with defined HFP logic,
// so check for either telephony or microphone.
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE) ||
mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
t.traceBegin("StartTelecomLoaderService");
mSystemServiceManager.startService(TelecomLoaderService.class);
t.traceEnd();
@@ -1479,7 +1478,7 @@ public final class SystemServer implements Dumpable {
t.traceBegin("StartTelephonyRegistry");
telephonyRegistry = new TelephonyRegistry(
context, new TelephonyRegistry.ConfigurationProvider());
context, new TelephonyRegistry.ConfigurationProvider());
ServiceManager.addService("telephony.registry", telephonyRegistry);
t.traceEnd();
@@ -3009,9 +3008,7 @@ public final class SystemServer implements Dumpable {
t.traceEnd();
t.traceBegin("MakeTelephonyRegistryReady");
try {
if (telephonyRegistryF != null) {
telephonyRegistryF.systemRunning();
}
if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying TelephonyRegistry running", e);
}
@@ -3076,12 +3073,10 @@ public final class SystemServer implements Dumpable {
*/
private void startApexServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startApexServices");
// TODO(b/192880996): get the list from "android" package, once the manifest entries
// are migrated to system manifest.
List<ApexSystemServiceInfo> services = ApexManager.getInstance().getApexSystemServices();
for (ApexSystemServiceInfo info : services) {
String name = info.getName();
String jarPath = info.getJarPath();
Map<String, String> services = ApexManager.getInstance().getApexSystemServices();
// TODO(satayev): introduce android:order for services coming the same apexes
for (String name : new TreeSet<>(services.keySet())) {
String jarPath = services.get(name);
t.traceBegin("starting " + name);
if (TextUtils.isEmpty(jarPath)) {
mSystemServiceManager.startService(name);

View File

@@ -32,7 +32,7 @@ apex_test {
name: "test_com.android.server",
manifest: "manifest.json",
androidManifest: "AndroidManifest.xml",
java_libs: ["FakeApexSystemServices"],
java_libs: ["FakeApexSystemService"],
file_contexts: ":apex.test-file_contexts",
key: "test_com.android.server.key",
updatable: false,

View File

@@ -21,29 +21,21 @@
<application android:hasCode="false" android:testOnly="true">
<apex-system-service
android:name="com.android.server.testing.FakeApexSystemService"
android:path="/apex/test_com.android.server/javalib/FakeApexSystemServices.jar"
android:minSdkVersion="30"
/>
<apex-system-service
android:name="com.android.server.testing.FakeApexSystemService2"
android:path="/apex/test_com.android.server/javalib/FakeApexSystemServices.jar"
android:minSdkVersion="30"
android:initOrder="1"
/>
android:path="/apex/test_com.android.server/javalib/FakeApexSystemService.jar"
android:minSdkVersion="30"/>
<!-- Always inactive system service, since maxSdkVersion is low -->
<apex-system-service
android:name="com.android.server.testing.OldApexSystemService"
android:path="/apex/test_com.android.server/javalib/fake.jar"
android:name="com.android.apex.test.OldApexSystemService"
android:path="/apex/com.android.apex.test/javalib/fake.jar"
android:minSdkVersion="1"
android:maxSdkVersion="1"
/>
<!-- Always inactive system service, since minSdkVersion is high -->
<apex-system-service
android:name="com.android.server.testing.NewApexSystemService"
android:path="/apex/test_com.android.server/javalib/fake.jar"
android:name="com.android.apex.test.NewApexSystemService"
android:path="/apex/com.android.apex.test/javalib/fake.jar"
android:minSdkVersion="999999"
/>
</application>

View File

@@ -8,7 +8,7 @@ package {
}
java_library {
name: "FakeApexSystemServices",
name: "FakeApexSystemService",
srcs: ["**/*.java"],
sdk_version: "system_server_current",
libs: [

View File

@@ -1,41 +0,0 @@
/*
* 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 com.android.server.testing;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.server.SystemService;
/**
* A fake system service that just logs when it is started.
*/
public class FakeApexSystemService2 extends SystemService {
private static final String TAG = "FakeApexSystemService";
public FakeApexSystemService2(@NonNull Context context) {
super(context);
}
@Override
public void onStart() {
Log.d(TAG, "FakeApexSystemService2 onStart");
}
}

View File

@@ -37,15 +37,9 @@ import org.junit.rules.RuleChain;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@RunWith(DeviceJUnit4ClassRunner.class)
public class ApexSystemServicesTestCases extends BaseHostJUnit4Test {
private static final int REBOOT_TIMEOUT = 1 * 60 * 1000;
private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
private final TemporaryFolder mTemporaryFolder = new TemporaryFolder();
private final SystemPreparer mPreparer = new SystemPreparer(mTemporaryFolder, this::getDevice);
@@ -73,7 +67,7 @@ public class ApexSystemServicesTestCases extends BaseHostJUnit4Test {
}
@Test
public void testNoApexSystemServiceStartsWithoutApex() throws Exception {
public void noApexSystemServerStartsWithoutApex() throws Exception {
mPreparer.reboot();
assertThat(getFakeApexSystemServiceLogcat())
@@ -81,55 +75,20 @@ public class ApexSystemServicesTestCases extends BaseHostJUnit4Test {
}
@Test
public void testApexSystemServiceStarts() throws Exception {
public void apexSystemServerStarts() throws Exception {
// Pre-install the apex
String apex = "test_com.android.server.apex";
mPreparer.pushResourceFile(apex, "/system/apex/" + apex);
// Reboot activates the apex
mPreparer.reboot();
mDevice.waitForBootComplete(REBOOT_TIMEOUT);
assertThat(getFakeApexSystemServiceLogcat())
.contains("FakeApexSystemService onStart");
}
@Test
public void testInitOrder() throws Exception {
// Pre-install the apex
String apex = "test_com.android.server.apex";
mPreparer.pushResourceFile(apex, "/system/apex/" + apex);
// Reboot activates the apex
mPreparer.reboot();
mDevice.waitForBootComplete(REBOOT_TIMEOUT);
assertThat(getFakeApexSystemServiceLogcat().lines()
.map(ApexSystemServicesTestCases::getDebugMessage)
.filter(Objects::nonNull)
.collect(Collectors.toList()))
.containsExactly(
// Second service has a higher initOrder and must be started first
"FakeApexSystemService2 onStart",
"FakeApexSystemService onStart"
)
.inOrder();
}
private String getFakeApexSystemServiceLogcat() throws DeviceNotAvailableException {
return mDevice.executeAdbCommand("logcat", "-v", "brief", "-d", "FakeApexSystemService:D",
"*:S");
}
private static final Pattern DEBUG_MESSAGE =
Pattern.compile("(FakeApexSystemService[0-9]* onStart)");
private static String getDebugMessage(String logcatLine) {
return DEBUG_MESSAGE.matcher(logcatLine)
.results()
.map(m -> m.group(1))
.findFirst()
.orElse(null);
}
}

View File

@@ -61,7 +61,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
@SmallTest
@Presubmit
@@ -136,10 +136,9 @@ public class ApexManagerTest {
mApexManager.scanApexPackagesTraced(mPackageParser2,
ParallelPackageParser.makeExecutorService());
List<ApexSystemServiceInfo> services = mApexManager.getApexSystemServices();
Map<String, String> services = mApexManager.getApexSystemServices();
assertThat(services).hasSize(1);
assertThat(services.stream().map(ApexSystemServiceInfo::getName).findFirst().orElse(null))
.matches("com.android.apex.test.ApexSystemService");
assertThat(services).containsKey("com.android.apex.test.ApexSystemService");
}
@Test