Dynamically load statsd-service

Previously, service-statsd.jar was on the SYSTEM_SERVER_CLASSPATH. This
CL loads StatsCompanion from SystemServer.java dynamically so that the
jar does not have to be on the classpath.

Bug: 146064616
Test: boots
Change-Id: Ia0e98ed0b6e35da01b38ead2fcf45d440eae31c3
This commit is contained in:
Tej Singh
2020-01-08 15:03:38 -08:00
parent 55447e3702
commit b2d6884ecf
2 changed files with 43 additions and 8 deletions

View File

@@ -25,10 +25,13 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.util.ArrayMap;
import android.util.Slog;
import com.android.server.utils.TimingsTraceAndSlog;
import dalvik.system.PathClassLoader;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -62,6 +65,9 @@ public class SystemServiceManager {
// Services that should receive lifecycle events.
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
// Map of paths to PathClassLoader, so we don't load the same path multiple times.
private final ArrayMap<String, PathClassLoader> mLoadedPaths = new ArrayMap<>();
private int mCurrentPhase = -1;
private UserManagerInternal mUserManagerInternal;
@@ -75,20 +81,46 @@ public class SystemServiceManager {
*
* @return The service instance.
*/
@SuppressWarnings("unchecked")
public SystemService startService(String className) {
final Class<SystemService> serviceClass;
final Class<SystemService> serviceClass = loadClassFromLoader(className,
this.getClass().getClassLoader());
return startService(serviceClass);
}
/**
* Starts a service by class name and a path that specifies the jar where the service lives.
*
* @return The service instance.
*/
public SystemService startServiceFromJar(String className, String path) {
PathClassLoader pathClassLoader = mLoadedPaths.get(path);
if (pathClassLoader == null) {
// NB: the parent class loader should always be the system server class loader.
// Changing it has implications that require discussion with the mainline team.
pathClassLoader = new PathClassLoader(path, this.getClass().getClassLoader());
mLoadedPaths.put(path, pathClassLoader);
}
final Class<SystemService> serviceClass = loadClassFromLoader(className, pathClassLoader);
return startService(serviceClass);
}
/*
* Loads and initializes a class from the given classLoader. Returns the class.
*/
@SuppressWarnings("unchecked")
private static Class<SystemService> loadClassFromLoader(String className,
ClassLoader classLoader) {
try {
serviceClass = (Class<SystemService>)Class.forName(className);
return (Class<SystemService>) Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
Slog.i(TAG, "Starting " + className);
throw new RuntimeException("Failed to create service " + className
+ ": service class not found, usually indicates that the caller should "
+ " from class loader " + classLoader.toString() + ": service class not "
+ "found, usually indicates that the caller should "
+ "have called PackageManager.hasSystemFeature() to check whether the "
+ "feature is available on this device before trying to start the "
+ "services that implement it", ex);
+ "services that implement it. Also ensure that the correct path for the "
+ "classloader is supplied, if applicable.", ex);
}
return startService(serviceClass);
}
/**

View File

@@ -212,6 +212,8 @@ public final class SystemServer {
"com.android.server.print.PrintManagerService";
private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
"com.android.server.companion.CompanionDeviceManagerService";
private static final String STATS_COMPANION_APEX_PATH =
"/apex/com.android.os.statsd/javalib/service-statsd.jar";
private static final String STATS_COMPANION_LIFECYCLE_CLASS =
"com.android.server.stats.StatsCompanion$Lifecycle";
private static final String USB_SERVICE_CLASS =
@@ -1972,7 +1974,8 @@ public final class SystemServer {
// Statsd helper
t.traceBegin("StartStatsCompanion");
mSystemServiceManager.startService(STATS_COMPANION_LIFECYCLE_CLASS);
mSystemServiceManager.startServiceFromJar(
STATS_COMPANION_LIFECYCLE_CLASS, STATS_COMPANION_APEX_PATH);
t.traceEnd();
// Incidentd and dumpstated helper