图解ServiceManager的获取服务过程(上)

概述

网上有很多关于ServiceManagerBinder的文章,但是老感觉理解起来不是那么顺畅,笔者基于Android 8.1系统源代码,从最简单的获取服务开始了解Binder进程间通信,由于篇幅原因,这里分开两部分来了解,上部分主要集中在Java层,下部分主要集中在Native层

获取ServiceManager服务

我们以获取网络连接管理为例:

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.isActiveNetworkMetered();

上面的代码,大家应该都是非常熟悉了,那么我们是如何获取到这个ConnectivityManager的呢?换句话说,获取服务的这个过程经历了哪些步骤呢?

笔者表达能力很一般,为了防止大家云里雾里,我提前先把这段用一个简单的时序图来整理一下:

过程分析

注意:我们在Activity中调用getService的时候实际是调用父类ContextThemeWrapper中的方法:

@Override
public Object getSystemService(String name) {
    if (LAYOUT_INFLATER_SERVICE.equals(name)) {
        if (mInflater == null) {
            mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
        }
        return mInflater;
    }
    return getBaseContext().getSystemService(name);
}

getBaseContext()返回的实际是ContextImpl,它是抽象类Context的子类实现ContextImpl的实际调用如下:

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

我们发现是通过SystemServiceRegistry.getSystemService(this, name);返回我们目标的服务,还得继续往下跟踪,找到系统源代码frameworks/base/core/java/android/app/SystemServiceRegistry.java,我保留了几个比较关键的属性和方法

final class SystemServiceRegistry {

    private static final String TAG = "SystemServiceRegistry";

    ......

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

    private static int sServiceCacheSize;

    // Not instantiable.
    private SystemServiceRegistry() { }

    static {

        ......

        registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
                new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
            @Override
            public ConnectivityManager createService(Context context) throws ServiceNotFoundException {
                IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
                return new ConnectivityManager(context, service);
            }});

        ......    
    }

    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
    
    static abstract interface ServiceFetcher<T> {
        T getService(ContextImpl ctx);
    }

    ......
}

可以看到,SystemServiceRegistry这个类在static块中完成了各种系统服务的注册,当我们获取服务的时候,其实是通过ServiceFetcher匹配对应的服务名,即通过ServiceManager.getServiceOrThrow这个方法返回我们目标的Manager

进入ServiceManager

接着我们来看frameworks/base/core/java/android/os/ServiceManager.java的源码:

......

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

    // Find the service manager
    sServiceManager = ServiceManagerNative
            .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
    return sServiceManager;
}

......

public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(getIServiceManager().getService(name));
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
    final IBinder binder = getService(name);
    if (binder != null) {
        return binder;
    } else {
        throw new ServiceNotFoundException(name);
    }
}

通过上面的几段内容,我们已经跟踪到了ServiceManager中来了,下面是获取服务的方法:

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

    // Find the service manager
    sServiceManager = ServiceManagerNative
            .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
    return sServiceManager;
}

frameworks/base/core/java/android/os/IServiceManager.java

public interface IServiceManager extends IInterface
{
    ......
    
    public IBinder getService(String name) throws RemoteException;

    ......
    
    public void addService(String name, IBinder service, boolean allowIsolated)
                throws RemoteException;

    ......
}

这里就是frameworks/base/core/java/android/os/ServiceManagerNative.java的具体实现:


public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
    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);
    }

    public ServiceManagerNative()
    {
        attachInterface(this, descriptor);
    }

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
    {
        try {
            switch (code) {
            case IServiceManager.GET_SERVICE_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String name = data.readString();
                IBinder service = getService(name);
                reply.writeStrongBinder(service);
                return true;
            }
            ......
            case IServiceManager.ADD_SERVICE_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String name = data.readString();
                IBinder service = data.readStrongBinder();
                boolean allowIsolated = data.readInt() != 0;
                addService(name, service, allowIsolated);
                return true;
            }
            case IServiceManager.LIST_SERVICES_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String[] list = listServices();
                reply.writeStringArray(list);
                return true;
            }
			......
            }
        } catch (RemoteException e) {
        }

        return false;
    }

    public IBinder asBinder()
    {
        return this;
    }
}

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }

    public IBinder asBinder() {
        return mRemote;
    }

    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
    ......
    private IBinder mRemote;
}

可以看到,我们最终还是调用到下层的ServiceManagerNative类中,我们重点看这个getService的实现,主要包含以下三部分:

1. 将所需参数通过Parcel打包
2. 利用IBinder的transact将请求发送出去,而不用去理会open,mmap以及一堆的Binder协议中的命令,这个IBinder一定会在内部使用ProcessStateIPCThreadState来与Binder驱动通信
3. 获取返回结果

下面这个关键方法就封装了对远程Binder驱动操作的一些通信协议,避免我们直接使用Binder协议进行通信

mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

思考

通过上面的过程分析我们对获取服务的过程已经有一个基本的认识了,那么我们思考一下:

要知道我们获取服务最终还是通过Binder驱动来进行通信,但是它毕竟不像我们调用同步方法那样直接返回,也没有一个回调方法,那么Android系统是如何保证同步获取服务的呢?

因为涉及到进程间通信,结果并不会立即获取,所以Binder驱动一定要先将调用者线程挂起,直到有结果才会唤起调用者,这样处理的好处就是调用者可以像进程内函数调用一样去编写,而不用考虑同步异步的问题。

笔者会在下节native层中进行分析

小结

可以看到,我们在Activity中调用getService获取服务,最终是通过ServiceManager发起调用,然后通过ServiceManagerNative返回的ServiceManagerProxy代理类,实现与Binder驱动的通信,返回对应的服务,笔者这里只是跟踪了Java层获取服务的过程,下一节内容会以更多图文的形式来分析Native层获取服务的过程。

参考

《Android系统源代码情景分析》
《深入理解android内核设计思想 第2版》

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值