Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2d6884e authored by Tej Singh's avatar Tej Singh
Browse files

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
parent 55447e37
Loading
Loading
Loading
Loading
+39 −7
Original line number Diff line number Diff line
@@ -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);
    }

    /**
+4 −1
Original line number Diff line number Diff line
@@ -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