从Context说到Binder

前情提要

当我们在Android项目中,希望使用系统服务时,可以通过ContextgetSystemService ()方法来获得。例如,当我们想要判断当前网络状态是否可用,可以通过下面的代码实现:

public static boolean isNetworkAvailable(@NonNull Context context) {
    // 获取系统服务(核心代码)
    ConnectivityManager cm = (ConnectivityManager)context
                            .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo info = cm.getActiveNetworkInfo();
            if (info != null &&
                info.isConnected() &&
                info.getState() == NetworkInfo.State.CONNECTED) {
                // 当前网络可用
                return true;
            }
        }
        // 当前网络不可用
        return false;
    }复制代码

上面的代码相对来说,还是比较简单的;核心代码就是通过getSystemService ()获取一个系统服务,后续只需调用ConnectivityManager提供的相关方法。下面我们将从getSystemService ()开始追溯,看看这个方法里面到底做了什么,竟有这样的魔力?

一. Context.getSystemService()

getSystemService()定义在\frameworks\base\core\java\android\content\Context.java文件中,方法声明如下:

public abstract Object getSystemService(@ServiceName @NonNull String name);复制代码

那么,该方法具体是在哪里实现的呢?

除了Activity中的getSystemService ()有所区别之外,其余所有的Context调用getSystemService ()时,最终都会调用ContextWrapper中的getSystemService ()

对此有疑问的小伙伴,可以参考我的另一篇文章:彻底理解Android中的Context

1.1 Activity.getSystemService()

方法定义在\frameworks\base\core\java\android\app\Activity.java中,声明如下:

@Override
public Object getSystemService(@ServiceName @NonNull String name) {
    // getBaseContext()获取的其实就是ContextWrapper中的成员变量mBase
    if (getBaseContext() == null) {
        throw new IllegalStateException(
        "System services not available to Activities before onCreate()");
    }
​
    if (WINDOW_SERVICE.equals(name)) { // 如果获取的是WindowManager,直接返回
        return mWindowManager;
    } else if (SEARCH_SERVICE.equals(name)) { // 如果获取的是SearchManager,直接返回
        ensureSearchManager();
        return mSearchManager;
    }
​
    // 调用父类的方法
    return super.getSystemService(name);
}复制代码

从上面方法可以看出:

  • 当在Activity中的onCreate()生命周期之前调用getSystemService ()时,会抛出异常!因为,ContextWrapper中的成员变量mBase是在attach()方法中初始化的;

  • 当获取的是WindowManager或者SearchManager时,直接返回;

  • 最终调用父类ContextThemeWrapper中的getSystemService ()方法;

1.1.1 ContextThemeWrapper.getSystemService()

方法定义在\frameworks\base\core\java\android\view\ContextThemeWrapper.java中,声明如下:

@Override 
public Object getSystemService(String name) {
    if (LAYOUT_INFLATER_SERVICE.equals(name)) { //如果获取的是LayoutInflater,直接返回
        if (mInflater == null) {
            mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
        }
        return mInflater;
    }
    return getBaseContext().getSystemService(name);
}复制代码

从上面的方法可以看出:

  • 作进一步校验,如果获取的是LayoutInflater,直接返回;

  • 调用getBaseContext()getSystemService ()方法,其实最终就是调用ContextWrapper中的成员变量mBasegetSystemService ()方法;

小结:

Activity中的getSystemService ()方法,最终会调用到ContextWrapper中的成员变量mBasegetSystemService ()方法;

1.2 ContextWrapper.getSystemService()

方法定义在\frameworks\base\core\java\android\content\ContextWrapper.java中,声明如下:

@Override
public Object getSystemService(String name) {
    return mBase.getSystemService(name);
}复制代码

由此我们发现:

  • 通过Context调用getSystemService ()时,最终都会调用到ContextWrapper中的成员变量mBasegetSystemService()方法;

  • mBase其实就是ContextImpl的实例;详见[彻底理解Android中的Context]。

1.3 ContextImpl.getSystemService()

方法定义在\frameworks\base\core\java\android\app\ContextImpl.java中,声明如下:

@Override
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}复制代码
1.3.1 SystemServiceRegistry.getSystemService()

方法定义在\frameworks\base\core\java\android\app\SystemServiceRegistry.java中,声明如下:

public static Object getSystemService(ContextImpl ctx, String name) {
    ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    // 最终调用ServiceFetcher的getService()方法
    return fetcher != null ? fetcher.getService(ctx) : null;
}复制代码

在该方法中,通过你传递过来的“name”,获取一个ServiceFetcher对象,最终调用的是ServiceFetcher中的getService()方法;

1.3.2 SystemServiceRegistry.SYSTEM_SERVICE_FETCHERS

SYSTEM_SERVICE_FETCHERS的定义如下:

private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();复制代码
1.3.3 SystemServiceRegistry.registerService()

通过搜索发现,该集合只在一个地方有存储元素的操作;代码如下:

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);
}复制代码

该方法把serviceName作为键,serviceFetcher作为值存储到集合当中。

1.3.4 SystemServiceRegistry.ServiceFetcher

ServiceFetcher其实是一个泛型接口,定义在SystemServiceRegistry类的内部,声明如下:

 static abstract interface ServiceFetcher<T> {
    T getService(ContextImpl ctx);
 }复制代码

接着搜索该方法的调用,发现该方法在静态代码块中被调用了很多次,用来注册不同的系统服务。我们以前面的Context.CONNECTIVITY_SERVICE为例,代码如下:

static {
    ...
    registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
                    new StaticOuterContextServiceFetcher<ConnectivityManager>() {
                @Override
                public ConnectivityManager createService(Context context) {
                    // 终于发现跟Binder的身影了...泪崩...不容易呀
                    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                    IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
                    return new ConnectivityManager(context, service);
                }});
     ...
}复制代码

在该方法的调用中:

  • serviceName就是Context.CONNECTIVITY_SERVICE

  • serviceClass就是ConnectivityManager.class

  • serviceFetcher就是StaticOuterContextServiceFetcher的一个匿名内部类。

1.3.5 SystemServiceRegistry.StaticOuterContextServiceFetcher

该类定义在SystemServiceRegistry类的内部,声明如下:

static abstract class StaticOuterContextServiceFetcher<T> implements ServiceFetcher<T> {
    private T mCachedInstance;
​
    @Override
    public final T getService(ContextImpl ctx) {
        synchronized (StaticOuterContextServiceFetcher.this) {
            // 首次调用时,mCachedInstance = null;会调用createService().
            if (mCachedInstance == null) {
                mCachedInstance = createService(ctx.getOuterContext());
            }
            return mCachedInstance;
        }
    }
​
    public abstract T createService(Context applicationContext);
}复制代码

由[1.3.1]可知,Context.getSystemService()最终返回的是ServiceFetchergetService()方法的返回值。而getService()返回的又是createService()方法的返回值;在本例中createService()的实现如下:

@Override
public ConnectivityManager createService(Context context) {
    // IPC通信。通过getService()最终获取了指向目标Binder服务端的代理对象BinderProxy。
    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
    // IConnectivityManager是一个aidl文件,定义在\frameworks\base\core\java\android\net目录下
    IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
    return new ConnectivityManager(context, service);
}复制代码

追溯到这里,我们已然来到了一个重要拐点:再继续下去,就下探到Binder的领域啦;是否到此为止了呢?

你想拥有什么你就去追求什么!

在这里,我准备先抛出结论。不想继续下去的小伙伴可以就近下车啦!

Context.getSystemService()小结
  • 通过Context.getSystemService()方法的层层调用,最终会走到ContextImpl.getSystemService ()方法之中;

  • ContextImpl.getSystemService ()方法中,经过层层调用,最终返回的是ServiceFetcher接口中getService()方法的返回值;

  • 虽然,根据系统服务的不同,ServiceFetcher.getService()的返回值形式上有所差异;但是,底层都会调用到ServiceManager.getService()方法,最终会触发IPC(Inter-Process Communication )机制,返回一个指向目标Binder服务端的代理对象BinderProxy

  • 后续所有的调用都是通过这个BinderProxy来实现的;

二. ServiceManager.getService()

to be continued...


转载于:https://juejin.im/post/5af2b051f265da0b9f40456e

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值