The opening

This article uses Android – 11.0.0_R25 as the basic analysis

We analyze how the SystemServer process is started, today this article, we will analyze the SystemServer process started to do what

main

As we saw in the previous chapter, Zygote forks a child process and eventually calls systemServer. main. SystemServer source code in the frameworks/base/services/Java/com/android/server/SystemServer. In Java, we came to see as a what

public static void main(String[] args) {
    new SystemServer().run();
}
Copy the code

A constructor

Very simple, just new a SystemServer object, then call its run method, let’s look at the constructor

public SystemServer(a) {
    // Factory modemFactoryTestMode = FactoryTest.getMode(); .// Record the startup information

    // Record whether a restart was experienced
    mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
Copy the code

The factory pattern

First, we get the factory pattern level from the system properties, which are three:

  • FACTORY_TEST_OFF: Normal mode
  • FACTORY_TEST_LOW_LEVEL: Low-level factory mode, in which many services do not start
  • FACTORY_TEST_HIGH_LEVEL: High-level factory mode, this mode is basically the same as normal mode, with slight differences

They are defined in the frameworks/base/core/Java/android/OS/FactoryTest. In Java

run

The run method is then executed

private void run(a) {...// Record the startup information
    // If no time zone is set, set the time zone to GMT
    String timezoneProperty = SystemProperties.get("persist.sys.timezone");
    if (timezoneProperty == null || timezoneProperty.isEmpty()) {
        Slog.w(TAG, "Timezone not set; setting to GMT.");
        SystemProperties.set("persist.sys.timezone"."GMT");
    }

    // Set the region and language
    if(! SystemProperties.get("persist.sys.language").isEmpty()) {
        final String languageTag = Locale.getDefault().toLanguageTag();

        SystemProperties.set("persist.sys.locale", languageTag);
        SystemProperties.set("persist.sys.language"."");
        SystemProperties.set("persist.sys.country"."");
        SystemProperties.set("persist.sys.localevar"."");
    }

    // Warn when a Binder transaction is blocked
    Binder.setWarnOnBlocking(true);
    / / PackageManager relatedPackageItemInfo.forceSafeLabels(); .// Set the virtual library file libart.so
    SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
    // Clear the maximum memory growth limit for the VIRTUAL machine to obtain more memory
    VMRuntime.getRuntime().clearGrowthLimit();
    // Some devices rely on runtime fingerprint generation, so make sure
    // we've defined it before booting further.
    Build.ensureFingerprintProperty();
    Before accessing environment variables, you need to explicitly specify the user
    Environment.setUserRequired(true);
    // Set the flag to handle BadParcelableException conservatively and not throw an exception
    BaseBundle.setShouldDefuse(true);
    // Set exception tracing
    Parcel.setStackTraceParceling(true);
    // Ensure that Binder call priority is always foreground priority
    BinderInternal.disableBackgroundScheduling(true);
    // Set the maximum number of Binder thread pools
    BinderInternal.setMaxThreads(sMaxBinderThreads);
    // Set the process priority to the foreground process
    // Prepare the main looper thread (this thread).
    android.os.Process.setThreadPriority(
            android.os.Process.THREAD_PRIORITY_FOREGROUND);
    android.os.Process.setCanSelfBackground(false);
    // Prepare with the current thread as MainLooper
    Looper.prepareMainLooper();
    Looper.getMainLooper().setSlowLogThresholdMs(
            SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

    SystemServiceRegistry.sEnableServiceNotFoundWtf = true;

    // Load the android_Servers. so library
    System.loadLibrary("android_servers");
    // Mark the process as heapable
    initZygoteChildHeapProfiling();
    //Debug option - start a thread to detect FD leaks
    if (Build.IS_DEBUGGABLE) {
        spawnFdLeakCheckThread();
    }
    // Check whether the last shutdown failed
    performPendingShutdown();
    // Initialize the System Context
    createSystemContext();
    // Create and set some modules that are required for each process to start (TelephonyServiceManager, StatsServiceManager)
    ActivityThread.initializeMainlineModules();
    
    // Create SystemServiceManager (manage all system Services)
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setStartInfo(mRuntimeRestart,
            mRuntimeStartElapsedTime, mRuntimeStartUptime);
    // Use SystemServiceManager as a local process Service
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    // Prepare the thread pool for the initialization taskSystemServerInitThreadPool.start(); .// Set the default exception handlerRuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf); .// Start the boot service
    startBootstrapServices(t);
    // Start the core service
    startCoreServices(t);
    // Start other servicesstartOtherServices(t); .// Initialize vm policies in strict mode
    StrictMode.initVmDefaults(null); .// Enter the Looper loop and wait for Handler events
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
Copy the code

As you can see, the run method mainly does the following

  1. Check and set various parameters handler
  2. createSystemContext
  3. createSystemServiceManager
  4. Start the service
  5. Loopercycle

The SystemContext creation step is done by ContextImpl, which will be examined in detail later, as will Looper, and we will focus on starting the service

Start the service

Starting a service is a three-step process, starting the boot service, starting the core service, and finally starting the other services, starting with the boot service

Because there are so many services launched, we will cover only those we are familiar with

startBootstrapServices

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {.../ / watchdog
    finalWatchdog watchdog = Watchdog.getInstance(); watchdog.start(); .final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
    // Read the system configurationSystemServerInitThreadPool.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG); .//Installer service (actually communicating with installd across processes)Installer installer = mSystemServiceManager.startService(Installer.class); .// create ATMS & AMSActivityTaskManagerService atm = mSystemServiceManager.startService( ActivityTaskManagerService.Lifecycle.class).getService(); mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mWindowManagerGlobalLock = atm.getGlobalLock(); .// The power management service needs to be started earlier because other services depend on itmPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); . mActivityManagerService.initPowerManagement(); .// Light servicemSystemServiceManager.startService(LightsService.class); .// Display management servicesmDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); .100 / / stagemSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); ./ / create the PMS
    try {
        Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain"); mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode ! = FactoryTest.FACTORY_TEST_OFF, mOnlyCore); }finally {
        Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
    }

    // Capture the dex load behavior
    SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);
    // Whether to start for the first time
    mFirstBoot = mPackageManagerService.isFirstBoot();
    / / get the PMSmPackageManager = mSystemContext.getPackageManager(); .// User management servicesmSystemServiceManager.startService(UserManagerService.LifeCycle.class); .// Initialize the property cacheAttributeCache.init(mSystemContext); .// Register various system servicesmActivityManagerService.setSystemProcess(); .// Use AMS to complete the watchdog setup and listen for a restartwatchdog.init(mSystemContext, mActivityManagerService); .// Set the scheduling policymDisplayManagerService.setupSchedulerPolicies(); .// Start sensor service in a separate threadmSensorServiceStart = SystemServerInitThreadPool.submit(() -> { TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog(); traceLog.traceBegin(START_SENSOR_SERVICE); startSensorService(); traceLog.traceEnd(); }, START_SENSOR_SERVICE); . }Copy the code

startCoreServices

private void startCoreServices(@NonNull TimingsTraceAndSlog t) {...// Battery power service depends on LightsServicemSystemServiceManager.startService(BatteryService.class); .// Apply the statistics servicemSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); . }Copy the code

startOtherServices

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {...//AccountManagerService - Account managementmSystemServiceManager.startService(ACCOUNT_SERVICE_CLASS); .//ContentService - ContentServicemSystemServiceManager.startService(CONTENT_SERVICE_CLASS); ./ / load SettingProvidermActivityManagerService.installSystemProviders(); .//DropBox log servicemSystemServiceManager.startService(DropBoxManagerService.class); .// Vibration service
    vibrator = new VibratorService(context);
    ServiceManager.addService("vibrator", vibrator); .// Clock/alarm clock service
    mSystemServiceManager.startService(new AlarmManagerService(context));
    // Enter the service
    inputManager = newInputManagerService(context); .// Wait for sensor service to be ready
    ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
    mSensorServiceStart = null;
    / / start WindowManagerServicewm = WindowManagerService.main(context, inputManager, ! mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
    ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
            DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
            /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); . mActivityManagerService.setWindowManager(wm); . wm.onInitReady(); .//HIDL servicesSystemServerInitThreadPool.submit(() -> { startHidlServices(); }, START_HIDL_SERVICES); .// Associate the WMS to start the input serviceinputManager.setWindowManagerCallbacks(wm.getInputManagerCallback()); inputManager.start(); . mDisplayManagerService.windowManagerAndInputReady(); .// Bluetooth enabled and not low level factory mode, enable Bluetooth service
    if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        ...
    } else if(! context.getPackageManager().hasSystemFeature (PackageManager.FEATURE_BLUETOOTH)) { ... }else{ mSystemServiceManager.startService(BluetoothService.class); }...// Input method/barrier-free service
    if(mFactoryTestMode ! = FactoryTest.FACTORY_TEST_LOW_LEVEL) {if (InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) {
            mSystemServiceManager.startService(
                    MultiClientInputMethodManagerService.Lifecycle.class);
        } else {
            mSystemServiceManager.startService(InputMethodManagerService.Lifecycle.class);
        }
        mSystemServiceManager.startService(ACCESSIBILITY_MANAGER_SERVICE_CLASS);
    }

    wm.displayReady();
    
    // Store related services
    if(mFactoryTestMode ! = FactoryTest.FACTORY_TEST_LOW_LEVEL) {if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
            mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);
            storageManager = IStorageManager.Stub.asInterface(
                        ServiceManager.getService("mount")); mSystemServiceManager.startService(STORAGE_STATS_SERVICE_CLASS); }}//UIMode service (night mode, driving mode, etc.)mSystemServiceManager.startService(UiModeManagerService.class); .// Clear the disk to release disk space
    mPackageManagerService.performFstrimIfNeeded();

    if(mFactoryTestMode ! = FactoryTest.FACTORY_TEST_LOW_LEVEL) { ...final booleanhasPdb = ! SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals(""); .if (hasPdb || OemLockService.isHalPresent()) {
            / / OEM lock servicemSystemServiceManager.startService(OemLockService.class); }...if(! isWatch) {// Status bar management services
            statusBar = new StatusBarManagerService(context);
            ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
        }
        
        // Network related services
        ConnectivityModuleConnector.getInstance().init(context);
        NetworkStackClient.getInstance().init();
        networkManagement = NetworkManagementService.create(context);
        ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
        ipSecService = IpSecService.create(context, networkManagement);
        ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService);
        
        // Text services
        mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
        mSystemServiceManager
                    .startService(TextClassificationManagerService.Lifecycle.class);

        // Network related services
        mSystemServiceManager.startService(NetworkScoreService.Lifecycle.class);
        networkStats = NetworkStatsService.create(context, networkManagement);
        ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
        networkPolicy = new NetworkPolicyManagerService(context, mActivityManagerService,
                    networkManagement);
        ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_WIFI)) {
            mSystemServiceManager.startServiceFromJar(
                    WIFI_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
            mSystemServiceManager.startServiceFromJar(
                    WIFI_SCANNING_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
        }
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_WIFI_RTT)) {
            mSystemServiceManager.startServiceFromJar(
                    WIFI_RTT_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
        }
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_WIFI_AWARE)) {
            mSystemServiceManager.startServiceFromJar(
                    WIFI_AWARE_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
        }
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_WIFI_DIRECT)) {
            mSystemServiceManager.startServiceFromJar(
                    WIFI_P2P_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
        }
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_LOWPAN)) {
            mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
        }
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
                mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
            mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
        }
        connectivity = new ConnectivityService(
                    context, networkManagement, networkStats, networkPolicy);
        ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); networkPolicy.bindConnectivityManager(connectivity); .// System update service
        ServiceManager.addService(Context.SYSTEM_UPDATE_SERVICE,
                    new SystemUpdateManagerService(context));
        ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
                    new UpdateLockService(context));
        // Notification servicemSystemServiceManager.startService(NotificationManagerService.class); SystemNotificationChannels.removeDeprecated(context); SystemNotificationChannels.createAll(context); notification = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); .// Location servicesmSystemServiceManager.startService(LocationManagerService.Lifecycle.class); .// Wallpaper service
        if (context.getResources().getBoolean(R.bool.config_enableWallpaperService)) {
            mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS);
        } else{... }// Audio service
        if(! isArc) { mSystemServiceManager.startService(AudioService.Lifecycle.class); }else {
            String className = context.getResources()
                    .getString(R.string.config_deviceSpecificAudioService);
            mSystemServiceManager.startService(className + "$Lifecycle"); }.../ / ADB service
        mSystemServiceManager.startService(ADB_SERVICE_CLASS);
        / / USB service
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
                || mPackageManager.hasSystemFeature(
                PackageManager.FEATURE_USB_ACCESSORY)
                || isEmulator) {
            mSystemServiceManager.startService(USB_SERVICE_CLASS);
        }
        // Widget service
        if(mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS) || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) { mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS); }...// New in Android10 for reporting information from runtime modules
        ServiceManager.addService("runtime".newRuntimeService(context)); .//App background Dex optimizationBackgroundDexOptService.schedule(context); . }...// Camera service
    if(! disableCameraService) { mSystemServiceManager.startService(CameraServiceProxy.class); }// Enter safe mode
    if (safeMode) {
        mActivityManagerService.enterSafeMode();
    }

    // SMS servicemmsService = mSystemServiceManager.startService(MmsServiceBroker.class); .// Clipboard servicemSystemServiceManager.startService(ClipboardService.class); .// Call the systemReady method of each major service

    vibrator.systemReady();
    lockSettings.systemReady();
    
    480 / / stage
    mSystemServiceManager.startBootPhase(t, SystemService.PHASE_LOCK_SETTINGS_READY);
    500 / / stagemSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY); wm.systemReady(); .// Manually update Context Configuration
    final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
    DisplayMetrics metrics = new DisplayMetrics();
    context.getDisplay().getMetrics(metrics);
    context.getResources().updateConfiguration(config, metrics);

    final Theme systemTheme = context.getTheme();
    if(systemTheme.getChangingConfigurations() ! =0) { systemTheme.rebase(); } mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); . mPackageManagerService.systemReady(); mDisplayManagerService.systemReady(safeMode, mOnlyCore); mSystemServiceManager.setSafeMode(safeMode);520 / / stagemSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY); .// Finally run ams.systemReady
    mActivityManagerService.systemReady(() -> {
        550 / / stagemSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY); .600 / / stagemSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); . }, t); }Copy the code

The startup of the service is done in phases, from 0-100-480-500-520-550-600-1000, with the final phase 1000, entered after AMS calls the finishBooting method

As you can see, there are so many services launched that it is impossible to see all of them. The most important ones are: Before we look at ActivityManagerService, WindowManagerService, PackageManagerService, and InputManagerService, let’s look at how services start

SystemServiceManager

Most of the services is through SystemServiceManager launched, its source code path for frameworks/base/services/core/Java/com/android/server/SystemServiceManager. Java

startService

Let’s look at the start service method in this class

There are three methods in this class to start Serivce:

  • public SystemService startService(String className)
  • public SystemService startServiceFromJar(String className, String path)
  • public <T extends SystemService> T startService(Class<T> serviceClass)
  • public void startService(@NonNull final SystemService service)

In fact, it always ends up calling the last method

Start with the startService method, which takes a String

public SystemService startService(String className) {
    final Class<SystemService> serviceClass = loadClassFromLoader(className,
            this.getClass().getClassLoader());
    return startService(serviceClass);
}
Copy the code
private static Class<SystemService> loadClassFromLoader(String className, ClassLoader classLoader) {
    try {
        return (Class<SystemService>) Class.forName(className, true, classLoader);
    } catch(ClassNotFoundException ex) { ... }}Copy the code

In effect, the Class name is reflected and the startService method is called with Class as an argument

StartServiceFromJar is actually the same, but the JAR is loaded through the PathClassLoader first

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);
}
Copy the code

Next, let’s look at the startService method with a Class parameter

public <T extends SystemService> T startService(Class<T> serviceClass) {
    final String name = serviceClass.getName();

    // Create the service.
    if(! SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("Failed to create " + name
                + ": service must extend " + SystemService.class.getName());
    }
    final T service;
    try {
        Constructor<T> constructor = serviceClass.getConstructor(Context.class);
        service = constructor.newInstance(mContext);
    } catch (...) {
        ...
    }

    startService(service);
    return service;
}
Copy the code

This method only accepts subclasses of SystemService. At the beginning of the method, isAssignableFrom is used as a type check to avoid subclasses of SystemService obtained by String reflection

The logic is simple: reflect the instantiated object and call another overloaded method that takes the SystemService object as an argument

public void startService(@NonNull final SystemService service) {
    mServices.add(service);
    try {
        service.onStart();
    } catch (RuntimeException ex) {
        throw new RuntimeException("Failed to start service " + service.getClass().getName()
                + ": onStart threw an exception", ex); }}Copy the code

This method adds the SystemService object to a List and calls its onStart method to tell SystemService to handle startup itself

startBootPhase

Because services are dependent on each other, Android divides the startup of a service into eight phases: 0-100-480-500-520-550-600-1000, and the startBootPhase method is used to inform each service which phase it is in

public void startBootPhase(@NonNull TimingsTraceAndSlog t, int phase) {
    if (phase <= mCurrentPhase) {
        throw new IllegalArgumentException("Next phase must be larger than previous");
    }
    mCurrentPhase = phase;

    final int serviceLen = mServices.size();
    for (int i = 0; i < serviceLen; i++) {
        final SystemService service = mServices.get(i);
        service.onBootPhase(mCurrentPhase);
    }

    if(phase == SystemService.PHASE_BOOT_COMPLETED) { SystemServerInitThreadPool.shutdown(); }}Copy the code

The onBootPhase method of all systemServices in the Service List is called each time a phase is completed, notifying SystemService of the phase transition. When the phase reaches 1000 (PHASE_BOOT_COMPLETED), Represents all of the services have been ready, closed SystemServerInitThreadPool thread pool

ServiceManager

After the service is created, invokes the ServiceManager. The addService method to add service, use these services to other places

AddService has three overloads and ends up calling:

public static void addService(String name, IBinder service, boolean allowIsolated,
        int dumpPriority) {
    try {
        getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e); }}Copy the code
private static IServiceManager getIServiceManager(a) {
    if(sServiceManager ! =null) {
        return sServiceManager;
    }

    // Find the service manager
    sServiceManager = ServiceManagerNative
            .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
    return sServiceManager;
}
Copy the code
public static IServiceManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }

    // ServiceManager is never local
    return new ServiceManagerProxy(obj);
}
Copy the code
class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
        mServiceManager = IServiceManager.Stub.asInterface(remote);
    }

    public IBinder asBinder(a) {
        returnmRemote; }...public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
            throws RemoteException { mServiceManager.addService(name, service, allowIsolated, dumpPriority); }...private IBinder mRemote;

    private IServiceManager mServiceManager;
}
Copy the code

The ServiceManager is actually a separate process named ServiceManager, which manages all services using the Binder IPC mechanism. We call the addService method which actually calls the Binder Proxy method. He writes a message to /dev/binder, which is received in the Servicemanager process and processes the request

The Binder mechanism will be examined later

Finally call the frameworks/native/CMDS servicemanager/servicemanager. The addService function of CPP

Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
    auto ctx = mAccess->getCallingContext(a); .// Add a service
    auto entry = mNameToService.emplace(name, Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    });

    auto it = mNameToRegistrationCallback.find(name);
    if(it ! = mNameToRegistrationCallback.end()) {
        for (const sp<IServiceCallback>& cb : it->second) {
            entry.first->second.guaranteeClient = true;
            // permission checked in registerForNotifications
            cb->onRegistration(name, binder); }}return Status::ok(a); }Copy the code

As you can see, a Service structure is eventually constructed from the Service name and the passed binder object and stored in the mNameToService Map for later use

About the process

Most services started by SystemServer run in the SystemServer process, but there are some exceptions

The Installer service, for example, forks an Installd process from the init process

Here is its rc file, frameworks/native/CMDS installd/installd. Rc

service installd /system/bin/installd
class main
...
Copy the code

The Installer of Start in the SystemServer process is connected to the Installd process by binder

Source path frameworks/base/services/core/Java/com/android/server/PM/Installer. Java

@Override
public void onStart(a) {
    if (mIsolated) {
        mInstalld = null;
    } else{ connect(); }}private void connect(a) {
    IBinder binder = ServiceManager.getService("installd");
    if(binder ! =null) {
        try {
            binder.linkToDeath(new DeathRecipient() {
                @Override
                public void binderDied(a) {
                    Slog.w(TAG, "installd died; reconnecting"); connect(); }},0);
        } catch (RemoteException e) {
            binder = null; }}if(binder ! =null) {
        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); }}Copy the code

The end of the

SystemServer started a number of services and added them to the ServiceManager, from which we derived the Binder mechanism, which we begin to examine in the next chapter