Advanced Android - system server creates and starts the Installer service

introduction

By the way, if my article is of some help to you, maybe you can take a few seconds to move your finger to vote, thank you, through train Five star praise Come on, encourage each other!

After the system server process executes the startbootstrap services method, it first creates and starts the Installer system service through the system service manager.

Later, more selected series articles are released in the highly complete series in the official account, forming a complete technical stack. Welcome to the attention. The first series is about the Android system startup series, and there are about twenty dry cargo.

1, Intcaller system service overview

\frameworks\base\services\core\java\com\android\server\pm\Installer.java inherits from com android. server. Systemservice, which also holds the proxy object of the Binder service corresponding to the installd daemon, essentially communicates with the Linux underlying installd daemon through the Binder call to truly complete the optimization and conversion of Apk file format, establishment of relevant data directory, deletion of files, installation of applications, etc. Therefore, it is started first before other system core services are started,

    private void startBootstrapServices() {
    	...
       Installer installer = mSystemServiceManager.startService(Installer.class);

When systemservicemanager Startservice (installer. Class) triggers com android. server. pm. When Installer#onStart callbacks, it first gets the name of the installdBinder service proxy object through ServerManager, then calls the Binder service proxy object to communicate with Linux's installd daemon through socket.

package com.android.server.pm;

import com.android.internal.os.BackgroundThread;
import com.android.server.SystemService;
public class Installer extends SystemService {
    private volatile IInstalld mInstalld;

    public Installer(Context context, boolean isolated) {
        super(context);
        mIsolated = isolated;
    }

    @Override
    public void onStart() {
        if (mIsolated) {
            mInstalld = null;
        } else {
            connect();
        }
    }

    private void connect() {
        IBinder binder = ServiceManager.getService("installd");
        if (binder != null) {
            try {
                binder.linkToDeath(new DeathRecipient() {
                    @Override
                    public void binderDied() {
                        Slog.w(TAG, "installd died; reconnecting");
                        connect();
                    }
                }, 0);
            }
        }

        if (binder != null) {
            mInstalld = IInstalld.Stub.asInterface(binder);
            try {
                invalidateMounts();
            }
        } else {
            Slog.w(TAG, "installd not found; trying again");
            BackgroundThread.getHandler().postDelayed(() -> {
                connect();
            }, DateUtils.SECOND_IN_MILLIS);
        }
    }
    public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
            int dexoptNeeded, @Nullable String outputPath, int dexFlags,
            String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries,
            @Nullable String seInfo, boolean downgrade, int targetSdkVersion,
            @Nullable String profileName, @Nullable String dexMetadataPath,
            @Nullable String compilationReason) throws InstallerException {
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
                    dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade,
                    targetSdkVersion, profileName, dexMetadataPath, compilationReason);
        }
    }
    public void rmdex(String codePath, String instructionSet) throws InstallerException {
        try {
            mInstalld.rmdex(codePath, instructionSet);
        }
    }
    public void createUserData(String uuid, int userId, int userSerial, int flags)
            throws InstallerException {
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.createUserData(uuid, userId, userSerial, flags);
        }
    }
	...
    public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32,
            int userId) throws InstallerException {
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId);
        }
    }
    public void createOatDir(String oatDir, String dexInstructionSet)
            throws InstallerException {
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.createOatDir(oatDir, dexInstructionSet);
        }
    }
    public void linkFile(String relativePath, String fromBase, String toBase)
            throws InstallerException {
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.linkFile(relativePath, fromBase, toBase);
        }
    }
    public void deleteOdex(String apkPath, String instructionSet, String outputPath)
            throws InstallerException {
            mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
    }
    public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)
            throws InstallerException {
        if (!checkBeforeRemote()) return;
         mInstalld.installApkVerity(filePath, verityInput, contentSize);
    }
    public boolean reconcileSecondaryDexFile(String apkPath, String packageName, int uid,
            String[] isas, @Nullable String volumeUuid, int flags) throws InstallerException {
            return mInstalld.reconcileSecondaryDexFile(apkPath, packageName, uid, isas,
                    volumeUuid, flags);
    }

    public void invalidateMounts() throws InstallerException {
        if (!checkBeforeRemote()) return;
            mInstalld.invalidateMounts();
    }
    ...
}

2, Com android. server. Systemservice overview

\frameworks\base\services\core\java\com\android\server\SystemService.java essentially abstracts some services running in the system process and defines some unified life cycle methods and running rules (all methods must be called in the main looper thread of the system service process).

package com.android.server;

import android.os.ServiceManager;
/**
 * The base class for services running in the system process. Override and implement
 * the lifecycle event callback methods as needed.
 * {@hide}
 */
public abstract class SystemService {
    ...
    private final Context mContext;
    public SystemService(Context context) {
        mContext = context;
    }
    public abstract void onStart();
		...
    protected final void publishBinderService(String name, IBinder service) {
        publishBinderService(name, service, false);
    }
    protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated) {
        ServiceManager.addService(name, service, allowIsolated);
    }
    protected final IBinder getBinderService(String name) {
        return ServiceManager.getService(name);
    }
    protected final <T> void publishLocalService(Class<T> type, T service) {
        LocalServices.addService(type, service);
    }
    protected final <T> T getLocalService(Class<T> type) {
        return LocalServices.getService(type);
    }

    private SystemServiceManager getManager() {
        return LocalServices.getService(SystemServiceManager.class);
    }
}

3, Startup of intcaller system service

1,com. android. server. Systemserver #startbootstrap services triggers the Installer system service to start

    private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);

2,com.android.server.SystemServiceManager#startService reflection creates and callback com android. server. pm. Installer#onStart

\frameworks\base\services\core\java\com\android\server\SystemServiceManager.java

2.1,com.android.server.SystemServiceManager#startService(String className) gets the bytecode object of the Installer

    public SystemService startService(String className) {
        final Class<SystemService> serviceClass;
        serviceClass = (Class<SystemService>)Class.forName(className);
        return startService(serviceClass);
    }

2.2,com. android. server. The systemservicemanager #startservice (Java. Lang. class < T >) reflection creates an Installer object

 /**
     * Creates and starts a system service. The class must be a subclass of
     * {@link com.android.server.SystemService}.
     */
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();
            // Create the service.
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } 
            startService(service);
            return service;
        }
    }

2.3,com.android.server.SystemServiceManager#startService(SystemService) registers with SystemServerManager and triggers the Installer#onStart callback

 public void startService(@NonNull final SystemService service) {
        // @Link ArrayList < systemservice > mservices register with SystemServerManager
        mServices.add(service);
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

3,com.android.server.pm.Installer#onStart gets the Binder service proxy object of installd

3.1,com. android. server. pm. The installer #onstart triggers to get the Binder service proxy object of installd

    @Override
    public void onStart() {
        if (mIsolated) {
            mInstalld = null;
        } else {
            connect();
        }
    } 

3.2,com. android. server. pm. The installer #connect really gets the Binder service proxy object of installd

    private void connect() {
    	//First, get the Binder object of the installd service through the ServiceManager
        IBinder binder = ServiceManager.getService("installd");
        if (binder != null) {
            try {
                binder.linkToDeath(new DeathRecipient() {
                    @Override
                    public void binderDied() {
                        Slog.w(TAG, "installd died; reconnecting");
                        connect();
                    }
                }, 0);
            } catch (RemoteException e) {
                binder = null;
            }
        }

        if (binder != null) {
            //Turn the Binder object into a specific Binder service object
            mInstalld = IInstalld.Stub.asInterface(binder);
            try {
                invalidateMounts();
            } catch (InstallerException ignored) {
            }
        } else {
            Slog.w(TAG, "installd not found; trying again");
            BackgroundThread.getHandler().postDelayed(() -> {
                connect();
            }, DateUtils.SECOND_IN_MILLIS);
        }
    }

At this point, the Installer system service is started, and then other system services are started. Please refer to the next episode.

Keywords: Android

Added by robh76 on Tue, 04 Jan 2022 02:58:29 +0200