源码解读Binder机制三(Clent 端如何获取 Service实例)

上文的篇幅很长,介绍了 ServiceManager 的启动流程,以 SurfaceFlinger 为例,介绍了它的简单启动流程和如何将自身添加到 ServiceManager 中。这篇了解下 Clent 端如何获取 Service。

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);
    }

在 Activity 中我们调用 getSystemService,传入 Service 的名字,它会调到 getBaseContext().getSystemService(name);

getBaseContext() 在 ContextWrapper 中

ContextWrapper中
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
   
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    
    public Context getBaseContext() {
        return mBase;
    }

通过 attachBaseContext 将 Context 传入,这里需要 Activity 启动流程,这里不说这些,我们直接看下 Context 的实现类 ContextImpl 中的 getSystemService

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

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

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

    static abstract interface ServiceFetcher<T> {
        T getService(ContextImpl ctx);
    }

其中 SystemServiceRegistry 里面的 SYSTEM_SERVICE_FETCHERS 相当于一个缓存,其存放的是 <String,ServiceFetcher> 键值对,String 表示服务名字,ServiceFetcher 持有服务对象或者是代理对象。

在 registerService 中将 serviceName put 到 SYSTEM_SERVICE_NAMES 中,将 serviceFetcher put 到 SYSTEM_SERVICE_FETCHERS 中。

    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);
    }

    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();

当然在 SystemServiceRegistry 类中,有个静态代码块,注册了很多 SystemService 启动的 Service。这里就是调用了 registerService 方法,并且实现了缓存。

static {
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});

        registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
                new CachedServiceFetcher<CaptioningManager>() {
            @Override
            public CaptioningManager createService(ContextImpl ctx) {
                return new CaptioningManager(ctx);
            }});

        //很多
    }

当然原理也是通过 binder 去注册到 ServiceManager 中的,这里不在赘述,继续 getService

我们看一个 ServiceFetcher 实现类 CachedServiceFetcher

        @Override
        @SuppressWarnings("unchecked")
        public final T getService(ContextImpl ctx) {
            final Object[] cache = ctx.mServiceCache;
            synchronized (cache) {
                // Fetch or create the service.
                Object service = cache[mCacheIndex];
                if (service == null) {
                    try {
                        service = createService(ctx);
                        cache[mCacheIndex] = service;
                    } catch (ServiceNotFoundException e) {
                        onServiceNotFound(e);
                    }
                }
                return (T)service;
            }
        }

由以上的代码,我们可以看到返回服务对象的两种方法,一种是通过 new 或者 getInstance 直接返回服务对象,比如 ACCESIBILITY_SERVICE;而另一种是通过 IBinder 返回服务的代理对象,比如 ACCOUNT_SERVICE。第一种的服务我们就不再跟踪了。我们要研究的是第二种服务代理的对象,因为通过代码可以看出这种服务的对象本身不是在这里创建的,是通过 ServiceManager.getService 方法获取的,所以我们继续看下 ServiceManager.getService 方法。我们以 AlarmManager 为例。

        registerService(Context.ALARM_SERVICE, AlarmManager.class,
                new CachedServiceFetcher<AlarmManager>() {
            @Override
            public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);
                IAlarmManager service = IAlarmManager.Stub.asInterface(b);
                return new AlarmManager(service, ctx);
            }});

调用 ServiceManager.getServiceOrThrow 方法返回 IBinder 类型的 b 对象,将 b 转为 IAlarmManager 类型,传入 AlarmManager 构造方法中返回 AlarmManager 对象。

ServiceManager.getServiceOrThrow

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

调用 getService 返回 binder

    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;
    }
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

缓存中取,没有 Binder.allowBlocking(getIServiceManager().getService(name)) 获取。

allowBlocking()

    public static IBinder allowBlocking(IBinder binder) {
        try {
            if (binder instanceof BinderProxy) {
                ((BinderProxy) binder).mWarnOnBlocking = false;
            } else if (binder != null
                    && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
                Log.w(TAG, "Unable to allow blocking on interface " + binder);
            }
        } catch (RemoteException ignored) {
        }
        return binder;
    }

这里判断返回的是代理对象还是自身对象,如果是代理对象将 mWarnOnBlocking 置为false。不是则检查 descriptor。

    public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

queryLocalInterface 在第一篇中已经分析出来结论了,这里暂且假设不在同一进程,这里返回为 null。自然这个方法不会运行了,因为上面已经判断是否是 BinderProxy 了。

getIServiceManager()

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

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

获取 sServiceManager 也是需要 allowBlocking() 方法。

BinderInternal.getContextObject()

    public static final native IBinder getContextObject();

实则调用到了 ProcessState::getContextObject

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

上篇已经提到了,返回一个 BpBinder。之后再 allowBlocking 中返回 BinderProxy

ServiceManagerNative.asInterface()

    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);
    }

这里不多分析了,不懂得话看第一篇。这里创建一个 ServiceManagerProxy 类型的代理对象。

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

这样就拿到 ServiceManager 的代理对象了。它的 getService 方法,

    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;
    }

综上 Java 层的 ServiceManager 是一个 Aidl 示例,其他的系统服务也是如此通过 binder 获取。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值