Android system service acquisition and registration process

Outline:

  • Obtaining System Services
  • Registration system Services
    • Standalone process services
    • Services for independent processes
  • conclusion
  • The resources

This article is about 1.9K words, about 8 minutes to read.

Android source code based on 8.0.

Preview the overall process

Start analyzing!

Obtaining System Services

In daily development, you can use context.getSystemService () to get system services in your own application:

//ContextImpl.java
public Object getSystemService(String name) {
    //SystemServiceRegistry is a registry of system services used to centrally manage system services
    return SystemServiceRegistry.getSystemService(this, name);
}

//SystemServiceRegistry.java
public static Object getSystemService(ContextImpl ctx, String name) {
    // Fetch ServiceFetcher from the HashMap based on the service nameServiceFetcher<? > fetcher = SYSTEM_SERVICE_FETCHERS.get(name);// Pass in the context, using ServiceFetcher to get the system service
    returnfetcher ! =null ? fetcher.getService(ctx) : null;
}
Copy the code

ServiceFetcher is an abstract interface implemented by the abstract class CachedServiceFetcher.

//CachedServiceFetcher.java
public final T getService(ContextImpl ctx) {
    // Each context CTX has a system service cache
    final Object[] cache = ctx.mServiceCache;
    synchronized (cache) {
        // Get the system service from the cache
        Object service = cache[mCacheIndex];
        if (service == null) {
            // If there is none in the cache, create one
            service = createService(ctx);
            // Cache
            cache[mCacheIndex] = service;
        }
        return(T)service; }}CreateService is an abstract method
public abstract T createService(ContextImpl ctx);
Copy the code

In SystemServiceRegistry, there is a static block of code that “registers the service”, which implements the logic of the abstract method createService(). For example, the power service PowerManager,

//SystemServiceRegistry.java
registerService(
    Context.POWER_SERVICE, PowerManager.class,
    new CachedServiceFetcher<PowerManager>() {
        @Override
        public PowerManager createService(ContextImpl ctx){
            //ServiceManager obtains Binder objects for system services based on service names
            IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
            // Convert the Binder on the server to the AIDL interface type object IPowerManager required by the client
            IPowerManager service = IPowerManager.Stub.asInterface(b);
            // Use the PowerManager class package layer to facilitate external use
            return new PowerManager(ctx.getOuterContext(),
                                    service, 
                                    ctx.mMainThread.getHandler());
        }});
Copy the code

AIDL can help generate classes for binder communication. IPowerManager is defined in iPowerManager.aidl. Binder internal details are not covered in this article.

The ServiceManager’s getServiceOrThrow() function calls getService(),

//ServiceManager.java
public static IBinder getService(String name) {
    / / cache
    IBinder service = sCache.get(name);
    if(service ! =null) {
        return service;
    } else {
        // If you can't get it, sCache is not stored, that is, sCache is just preset some services stored during startup
        //getService() gets the Binder object of the system service with allowBlocking
        return Binder.allowBlocking(getIServiceManager().getService(name));
    }
    return null;
}

private static IServiceManager getIServiceManager(a) {
    if(sServiceManager ! =null) {
        return sServiceManager;
    }
    // Binder cross-process communication:
    / / BinderInternal getContextObject IBinder () get system level context, can be used to locate the service
    //asInterface converts IBinder to IServiceManager
    sServiceManager = ServiceManagerNative
        .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
    return sServiceManager;
}
Copy the code

As you can see, our application processes communicate with binder across processes to get the IServiceManager object (essentially BpServiceManager) of the ServiceManager process, The system service can then be obtained via IServiceManager object’s getService.

public interface IServiceManager extends IInterface{
    // Get the system service from IServiceManager. If the service does not exist, it blocks for up to 5 seconds until the service is published and registered
    public IBinder getService(String name);
}
Copy the code

Look at the IServiceManager implementation. In the IServiceManager. CPP file, there is a BpServiceManager class.

//class BpServiceManager : public BpInterface<IServiceManager>
// The BpInterface here is the internal detail of binder, which is not quite understood

virtual sp<IBinder> getService(const String16& name) const
{
    unsigned n;
    // If not, sleep for 1 second and block for 5 seconds at most
    for (n = 0; n < 5; n++){
        if (n > 0) {
            // Sleep for 1 second and fetch it later
            sleep(1);
        }
        sp<IBinder> svc = checkService(name);
        // The system service is obtained
        if(svc ! =NULL) return svc;
    }
    return NULL;
}

// Return to binder of the system service
virtual sp<IBinder> checkService( const String16& name) const
{
    // Binder uses Parcelable to serialize data
    Parcel data, reply;
    data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
    data.writeString16(name);
    // Remote () gets BpBinder, transact sends the request
    remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
    return reply.readStrongBinder();//Binder
}
Copy the code

Let’s review the process of obtaining system services:

  1. The application process calls getSystemService
  2. Communicate with binder across processes to get the BpServiceManager object of the ServiceManager process
  3. Obtain system services from BpServiceManager

Registration system Services

System services can be divided into two broad categories:

The ServiceManager, SurfaceFlinger, etc., which have separate processes, are created by fork when init starts.

Two independent process AMS, PMS, WMS, etc., they in init process fork out Zygote process, Zygote process fork out SystemServer process create.

Standalone process services

A system service for a standalone process starts when the init process parses init.rc, such as SurfaceFlinger. Take a look at its startup configuration file, SurfaceFlinger.

Note: frameworks/native/services following a series of services, but ServiceManager service on the frameworks/native/CMDS/ServiceManager directory.

//frameworks/native/services/surfaceflinger/surfaceflinger.rc
service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
Copy the code

Service in the form of services to start the process, is surfaceflinger process name/system/bin/surfaceflinger is the path of the executable program, the program’s main entrance function in main_surfaceflinger. CPP,

int main(int.char* *) {
    //ProcessState starts binder mechanism (binder driver open, memory mapped, buffer allocated)
    sp<ProcessState> ps(ProcessState::self());
    // Start the binder thread
    ps->startThreadPool();

    // Initialize surfaceFlinger
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();
    flinger->init();

    // Publish to register surfaceFlinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

    // Run surfaceFlinger in the current thread
    flinger->run();
    return 0;
}
Copy the code

Take a look at the implementation of defaultServiceManager() in iservicemanager.cpp,

sp<IServiceManager> defaultServiceManager(a)
{
    // If there is a value, return it directly
    if(gDefaultServiceManager ! =NULL) return gDefaultServiceManager;

    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
            IServiceManager (BpServiceManager)
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            // If IServiceManager is still null, it will sleep for 1 second and fetch again until it finishes the loop
            if (gDefaultServiceManager == NULL)
                sleep(1); }}return gDefaultServiceManager;
}
Copy the code

The SurfaceFlinger process and the ServiceManager process are both started by the init process. It is possible that the SurfaceFlinger process obtains IServiceManager before the ServiceManager has been registered. Therefore, the SurfaceFlinger process will sleep while retrieving IServiceManager. End the loop.

After you get IServiceManager, run sm->addService. There is a BpServiceManager class in the iservicemanager.cpp file.

//class BpServiceManager : public BpInterface<IServiceManager>
// The BpInterface here is the internal detail of binder, which is not quite understood

// Register system services (binder)
virtual status_t addService(const String16& name, const sp<IBinder>& service,
                            bool allowIsolated)
{
    // Binder uses Parcelable to serialize data
    Parcel data, reply;
    data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
    data.writeString16(name);
    data.writeStrongBinder(service);//Binder
    data.writeInt32(allowIsolated ? 1 : 0);
    // Remote () gets BpBinder, transact sends the request
    status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
    return err == NO_ERROR ? reply.readExceptionCode() : err;
}
Copy the code

To sort it out:

  1. Rc configuration forks out new processes to start system services for multiple independent processes, such as SurfaceFlinger
  2. Execute SurfaceFlinger’s executable to find the BpServiceManager object for the ServiceManager process
  3. AddService registers the service through BpServiceManager

Services for independent processes

SystemServer uses the SystemServiceManager class (SSM) to start system services, such as AMS.

//SystemServer.java
private void startBootstrapServices(a) {
    //AMS is created and started by SSM
    mActivityManagerService = mSystemServiceManager
        // Create and start the AMS service
        .startService(ActivityManagerService.Lifecycle.class)
        // Obtain AMS service with binder
        .getService();

    / / AMS registration
    mActivityManagerService.setSystemProcess();
}
Copy the code

See ActivityManagerService,

//ActivityManagerService.java
public void setSystemProcess(a) {
    / / AMS registration
    ServiceManager.addService(Context.ACTIVITY_SERVICE, this.true);
}
Copy the code

Call the ServiceManager. The addService () to register,

//ServiceManager.java
public static void addService(String name, IBinder service, boolean allowIsolated) {
    // As before, communicate with binder across processes to get the BpServiceManager object of the ServiceManager process
    // Call BpServiceManager addService
    getIServiceManager().addService(name, service, allowIsolated);
}
Copy the code

Visible, whether SystemServer process to start the service, or the init process starts running in a separate process service, is go BpServiceManager ServiceManager process. Eventually the addService centrally registered.

conclusion

To sum up, both system services of independent processes such as SurfaceFlinger started by init process and system services of independent processes such as AMS started by SystemServer process are registered and obtained in ServiceManager process. Android’s Binder mechanism is used for cross-process communication.

But Hardy doesn’t use Binder much in his work, so he’ll leave the details behind for later.

Review again

Series of articles:

  • Graphic | Android launch

The resources

  • Csdn-servicemanager client agent: BpServiceManager

More sexy articles, pay attention to the original technology public account: Halliday EI