Android系统服务调用分析2

333 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情

三.系统服务实现

      本文拿EthernetManager来举例,看一下对应的EthernetService的内部逻辑是如何实现的:

public final class EthernetService extends SystemService {

    private static final String TAG = "EthernetService";
    final EthernetServiceImpl mImpl;

    public EthernetService(Context context) {
        super(context);
        mImpl = new EthernetServiceImpl(context);
    }

    @Override
    public void onStart() {
        Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);
        //公开Binder
        publishBinderService(Context.ETHERNET_SERVICE, mImpl);
    }
}

      在构造方法中创建EthernetServiceImpl()实例,然后在onStart()中执行publishBinderService(),该方法是父类SystemService.java的方法,实现如下:

protected final void publishBinderService(String name, IBinder service) {
    publishBinderService(name, service, false);
}

protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated) {
    //最终会通过ServiceManager.addService来注册Binder
    ServiceManager.addService(name, service, allowIsolated);
}

      通过以上可以看到,在EthernetService启动时,会执行publishBinderService()来将EthernetServiceImpl来作为实名的Binder来暴露出来,在publishBinderService()内部会通过ServiceManager.addService()将实名Binder统一给ServiceManager来管理。

public class EthernetServiceImpl extends IEthernetManager.Stub {
    //实现IEthernetManager里面的方法
    IpConfiguration getConfiguration() {
    }

    void setConfiguration(in IpConfiguration config) {
    }

    boolean isAvailable(){
    }

    void addListener(in IEthernetServiceListener listener){
   }
}

      EthernetServiceImpl继承IEthernetManager.Stub,来实现IEthernetManager.aidl的方法,供远端的Client来最终调用。

interface IEthernetManager
{
    IpConfiguration getConfiguration();
    void setConfiguration(in IpConfiguration config);
    boolean isAvailable();
    void addListener(in IEthernetServiceListener listener);
}

四.系统服务启动

      要想获取IEthernetManager的Binder,必须要先把Binder公开出来,该Binder公开是在EthernetService启动后执行的,那么需要有个地方来启动EthernetService,该启动入口是在哪的?在SystemServer.java中:

    private void run() {
        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        }
        ......
    }

      在SystemServer启动的时候,去在main()中调用run()方法,然后在run()中会去启动系统的一些公共service,该service在startOtherServices()中启动的:

private static final String ETHERNET_SERVICE_CLASS ="com.android.server.ethernet.EthernetService";
private void startOtherServices() {
    ......
    //其他service
    ......
    if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
        mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
        traceBeginAndSlog("StartEthernet");
        mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
        traceEnd();
     }
    ....
    //其他service
    ......
}

      EthernetService是在startOtherServices()通过SystemServiceManager.startService()去启动的,传入对应的系统服务类名,看一下SystemServiceManager内部startService的实现逻辑:

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

      先通过传入的字符串找到对应的类,然后传入类名调用startService():

    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();
            .......
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } 
            .......
            startService(service);
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

      通过反射找到构造方法,然后通过newInstance()来创造了实例,然后传入该实例调用startService():

    public void startService(@NonNull final SystemService service) {
        // Register it.
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();
        }
        ......
    }

      调用service的onStart()方法,即调用了EthernetService的onStart()方法,将Binder暴露出来供调用;注意:SystemService是一个抽象类,不是Service。
简单总结一下:系统服务首先通过SystemServer内部调用SystemServiceManager来进行启动,启动后会将自己注册到ServiceManager作为实名服务,系统服务对应的Manager在SystemServiceRegistry内部注册时就通过ServiceManager来获取到该服务,从而供上层应用使用;当使用系统服务时,首先通过 Context 类的 getSystemService方法获取到服务对应的Manager,Manager会通过对应服务公开的Binder最终与服务进行通信,然后来执行上层的逻辑。

五.系统服务实现及使用流程

      1.创建xx.aidl文件,加入系统服务能提供的方法;
2.创建类文件来实现xx.Stub,来实现服务提供的方法;
3.将实现xx.Stub的类对象Binder通过ServiceManager.addService()注册【SystemServer作为入口触发】;
4.创建服务对应的Manager,封装对应服务提供方法的方法来供app调用;
5.SystemServiceProxy通过registerService来注册对应的服务【Manager与对应的服务建立联系】;
6.app通过getSystemService()来获取对应服务的Manager,然后调用方法;

六.其他

      系统服务是供上层app来使用的,在rom定制化开发时,如果使用某个服务的应用很多时,比如数据上报,那么可以将数据上报作为一个系统服务来跟后台进行交互;
系统服务暴露对应的门面类Manager供应用来调用,这样的话系统服务只跟Manager打交道就行了,不需要跟所有的应用来维持关系。