Android_SystemService(使用系统服务)

系统服务

主要关注以下几个方面:

  • 如何使用系统服务
  • 系统服务的发布
  • 系统服务的注册原理

先画个图表来简单的概括一下

Android系统利用ServiceManager来统一管理系统服务;这样对于service端来说,只要将自身注册到Servicemanager中,就可以安心等待被调用,对于client端来说,需要调用某个服务时,只要在Servicemanager来查询是否有所需的服务,然后远程调用,免去了到处找服务的必要,很方便.

我们先从如何使用系统服务开始

上代码:

    @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

一般使用系统服务时,通过Context的getSystemService()方法,传入服务的名称,然后这个方法会返回这个服务的接口对象,这个方法的实现原理具体是怎么养的呢?我们接下来追一追源码:这里首先调用了SystemServiceRegistry的getSystemService()方法,根据这个SystemServiceRegistry的注解,我们知道他是管理所有的系统服务的类.

/**
 * Manages all of the system services that can be returned by {@link Context#getSystemService}.
 * Used by {@link ContextImpl}.
 */
final class SystemServiceRegistry {
    ...
}
    /**
     * Gets a system service from a given context.
     */
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

在getSystemService()方法中,通过服务的名称拿到服务对应的feacher,然后再调用ServiceFether的getServicemanager()方法来获取系统服务的接口对象;这个SYSTEM_SERVICE_FETCHERS是什么呢?

private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();

根据定义,我们看到这个SYSTEM_SERVICE_FETCHERS是一个HashMap,就是说我们是根据服务的名称在这个HashMap中查找ServiceFetcher.再来看看getService()方法中做了什么:

 public final T getService(ContextImpl ctx) {
    final Object[] cache = ctx.mServiceCache;
    final int[] gates = ctx.mServiceInitializationStateArray;

    for (;;) {
        boolean doInitialize = false;
        synchronized (cache) {
            // Return it if we already have a cached instance.
            T service = (T) cache[mCacheIndex];
            if (service != null || ...) {
                return service;
            }
            ...
        }
        ...
        if (doInitialize) {
            // Only the first thread gets here.
            T service = null;
            @ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
            try {
                // This thread is the first one to get here. Instantiate the service
                // *without* the cache lock held.
                service = createService(ctx);
                newState = ContextImpl.STATE_READY;

            } catch (ServiceNotFoundException e) {
                onServiceNotFound(e);

            } finally {
                synchronized (cache) {
                    cache[mCacheIndex] = service;
                    gates[mCacheIndex] = newState;
                    cache.notifyAll();
                }
            }
            return service;
        }
        ...
    }
    ...
}

  在getService()方法中,首先看这个cache,这个cache是什么呢?我们看定义:

// The system service cache for the system services that are cached per-ContextImpl.
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();

可以看出,mServiceCache是一个数组,这个每个context都有一个mServiceCache,有多少个Context就有多少个mServiceCache;

然后进入for循环,根据mCacheIndex来获取一个service,这个service就是我们要的服务接口对象,当service为空,也就是说我们cache中还没有service,此时就需要创建新的service对象了,并且要保证只会创建一次,创建完成后讲将service塞到cache中,下次获取service时就可以直接从cache获取了,最后返回service.

那么这个createService是怎么实现的呢?继续追代码:

public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;

在这里,createService()是个抽象方法,看来他的具体实现得要根据具体的服务来具体实现;我们就选择RadioManager来看看:

registerService(Context.RADIO_SERVICE, RadioManager.class,
        new CachedServiceFetcher<RadioManager>() {
    @Override
    public RadioManager createService(ContextImpl ctx) throws ServiceNotFoundException {
        return new RadioManager(ctx);
    }});
public RadioManager(@NonNull Context context) throws ServiceNotFoundException {
    mContext = context;
    mService = IRadioService.Stub.asInterface(
            ServiceManager.getServiceOrThrow(Context.RADIO_SERVICE));
}

我们可以看到:先要获取一个IBinder对象,然后封装成IRadioService对象,这是为了可以进程Binder通信。对new 出来的RadioManager对象的操作,最后装移到mServices(IRadioService.Stub对象)上。mServices是怎么获取的呢?

是通过Context.RADIO_SERVICE常量(就是服务的名称)来获取一个IBinder对象,然后将获取到的IBinder传入asInterface()方法中转换成我们所需要的mService ;我们先看看怎么通过Context.RADIO_SERVICE来获取IBinder 的。

    /**
     * Returns a reference to a service with the given name, or throws
     * {@link NullPointerException} if none is found.
     *
     * @hide
     */
    public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
        final IBinder binder = getService(name);
        if (binder != null) {
            return binder;
        } else {
            throw new ServiceNotFoundException(name);
        }
    }
.....
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
...
    private static IBinder rawGetService(String name) throws RemoteException {
        final long start = sStatLogger.getTime();
        ....
        final IBinder binder = getIServiceManager().getService(name);
        ...
}

通过以上代码,再通过各个法发调用关系,我们找到 final IBinder binder = getIServiceManager().getService(name);通过

getIServiceManager方法获得IServiceManager的对象(ServiceManager代理端,可以进行binder通信)。通过Binder通信在ServiceManager中在查找服务并返回。【这里就先不继续,现在只要知道服务的查找是在ServiceManager中实现的,在后面和服务的添加的内容一起讲讲

系统服务发布

         系统服务要向被其他的应用或者服务调用,就得让其他进程找到别切自身具备进程通讯的能力,这些有SystemServiceManager创建并启动的服务,都是继承SystemService,但是并没有实现IBinder,所以不可以进程binder通信,但是绝大部分SystemService都会在onStart()中调用SystemManagerService#publicBinderService(String name, IBinder service, boolean allowIsolated);就是在onStart()中注册Binder服务。

我们看看publicBinderService()方法是怎样的:

/**
* Publish the service so it is accessible to other services and apps.
*/ 
protected final void publishBinderService(String name, IBinder service) {
    publishBinderService(name, service, false);
}
...
protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated, int dumpPriority) {
    ServiceManager.addService(name, service, allowIsolated, dumpPriority);
}
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);
    }
}

从上面的代码可以看到,系统服务最后会调用ServiceManager的addService()方法向ServiceManager注册。在ServiceManager的addService()方法中首先调用getIServiceManager方法获得IServiceManager的对象(ServiceManager代理端,可以进行binder通信)。通过Binder通信在ServiceManager中在服务添加。【这里就先不继续,现在只要知道服务的发乎就是要在ServiceManager中添加,在后面和服务的查找一起讲讲

我们先回来看看怎么获取IServiceManager对象的:

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ServiceManagerProxy(obj);
    }

getIServiceManager()方法主要是获取sServiceManager 【sServiceManager就是IServiceManager的实例】。如果系统中sServiceManager已经存在就直接返回,如果不存在就创建新的sServiceManager。

那我们就看看怎么获取sServiceManager的?首先通过BinderInternal。getContextObject()来过去一个全局上下文,这通常是一般是IServiceManager的实现,然后通过这个上下文获取到一个IBidner对象,最后将IBidner传入ServiceManagerNative.asInterface()方法获得sServiceManager。

我们看看asInterface()方法是怎么通过IBInder来获取到ServiceManager的代理对象的?这里是通过queryLocalInterface()方法请求相应的描述符时返回给定的所有者iInterface,此处即是获取IServiceManager。【因为IServiceManager是实现IInterface的】;如果descripter不存在,那就重新new 一个ServiceManagerProxy。到此,我们就知道怎么获取ServiceManager的代理对象的。

系统服务的查找和添加原理

前面说到查找和发布服务是通过ServiceManage添加的,在ServiceManager的代理对象拿服务后,真正进行服务添加的是在ServiceManager进程中,ServiceManager是拥Binder通信能力的独立服务【主要都是C++在底层实现的】,它在创建的时候就将自己注册成为Binder管理者,主要就是对跨进程服务的管理(添加和查找)【这个涉及到Binder的,比较大,目前我也还没有深入,这里就简单说说,只要知道它是个系统服务的管理者就够了,实际开发中这方面好像也不需要我们来参与什么

ServiceManager在成为系统服务的的管理者后,主要任务也不多,就是系统服务的查找和注册。


int main(int argc, char** argv)
{
    ...
    bs = binder_open(driver, 128*1024); // 打开Binder
    ...
    if (binder_become_context_manager(bs)) { // 把自己注册为Binder管理者
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
    ...
    binder_loop(bs, svcmgr_handler); // 进入loop.
    return 0;
}
int svcmgr_handler(...)
{
    ....
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE: // 查找服务
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
        bio_put_ref(reply, handle);
        return 0;

    case SVC_MGR_ADD_SERVICE: // 添加服务
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        dumpsys_priority = bio_get_uint32(msg);
        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
                           txn->sender_pid))
            return -1;
        break;

    case SVC_MGR_LIST_SERVICES: {
       ...
    default:
        ALOGE("unknown code %d\n", txn->code);
        return -1;
    }
    bio_put_uint32(reply, 0);
    return 0;
}

ServiceManager使用C++实现的,接下来主要看main函数做了什么。它主要做了三件事:

  • 打开Binder
  • 把自己注册为Binder管理者
  • 进入loop监听,使用svcmgr_handler来处理应用请求

我们之前通过向ServiceManager查找和添加服务的操作,最后都是在svcmgr_handler函数中处理的,在svcmgr_handler函数通传进来的请求码确定是要查找还是添加服务,然后进行相应的处理;需要注意的是:这里传入的和返回都是服务的handler,并不是对实际的服务进行操作,这样是的ServiceManager变的很小很轻(内存占用少,操作对象简单)。【这里面就不具体深入,我们知道ServiceManager是怎么个处理流程就好。】

通过追源码,我们知道系统服务的使用,注册和查找的基本流程,但是Android系统服务这一块也是很大的,具体细节还需要具体深入查看源码和和其他资料。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值