Binder核心原理与架构设计
这篇文章主要分析一下Binder, 我们身边可能有很多做好几年Android 开发的 却对Binder 了解不深,着重于应用层面的开发和API的调用。而现实的开发或者面试如果对Binder了解不深的话可以说很难进入高级工程师的行列。 所以说如果真正对系统底层了解比较深入的话 进程间通信是必知必会的, 就让我们开始吧。
简单一句话Binder是什么, 就是IPC (Inter-Process Communication) 就是进程间通信。
本文分析的源码基于Android-28
由于本文涉及可能设计一些底层的源码, 篇幅可能有那么一丢丢长。
本文主要分以下几个部分展开
- 为什么要用多进程
- AIDL类的结构分析
- 系统服务管理器的简单解析
- 总结
- 参考资料
1. 为什么要用多进程
了解IPC之前 , 可能会有人说为什么(毛)要用多进程呢, 大家都在一个进程内,多温馨,多和谐?
要回答这个问题,可以很简单的一句话 世界上的操作系统大家都是多进程的,别问为什么 你也用吧。
我觉得主要原因有以下几点:
- 不够安全.
我们知道C或者C++ 可以进行内存的操作。 我们的Java也可以通过反射进行内存的操作。 所谓的外挂,或者修改器 就是基于此原理做成的。 - 效率不够高。
可以深入的理解为,我们都知道一个进程可以有多个线程, 但是只会有一个主线程。当所有的任务都共享这么一个主线程进行切换的话,那么同一时间只会有一个任务处于主线程执行中。 简单来说 那么就会很卡。卡的亲娘也会不认识了。
这种语言叫做AIDL语言 就是我们常说的接口定义语言(Android Interface Define Language), 这个接口定语言,两端声明的aidl文件 ,包名必须一样。 在自己
这个东西是我们Android中基础里边都会的。
那他们是如何进行通信的呢?
2. AIDL类的结构分析
在底层写了个Binder 驱动, 这是提供给系统中不同进程之间进行通信的。 这就类似于我们常见的快递公司。 例如 如果进程A 在北京, 进程B 在上海 , 那么Binder 就像顺丰快递。 如果进程A需要和进程B进行通信, 则需要借助顺丰发送数据,文件。 就相当于两个进程之间的桥梁。 其实就是类似于常见的C/S 架构 。
所有的AIDL接口 都是继承自 IInterface的, 也就是说所有的aidl都是IInterface的子孙, 我们看一下该类的结构 ,分两部分, 一个是Stub,另一个是Proxy 。
所以我们明白了每个aidl 都是用来和Binder进行通信的接口。
Proxy 负责向Binder 发送数据, Proxy 去连接Binder , 告诉Binder 我要调用B进程中的
所有的Stub 是个静态抽象内部类并且继承自Binder 并且实现了 IInterface 接口
我们定义了一个aidl文件作为两个进程通信约定的接口信息
// BinderLearn.aidl
package com.greencheng.android.parent;
// Declare any non-default types here with import statements
interface BinderLearn {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
/**
* query student score
*/
int queryScore(int stuNo, String name );
/**
* testBinder
*/
void testBinder(String nameforTest);
}
build之后自动生成一个了BinderLearn.java 也不算长, 一起贴出来分析一下。
为了方便阅读格式化了一下。
/*
* This file is auto-generated. DO NOT MODIFY. 文档是自动生成的不要修改 , 我们既然要研究这,当然要修改。
* Original file: /androiddev/bindertest/app/src/main/aidl/com/bindertest/BinderLearn.aidl
*/
package com.bindertest;
// Declare any non-default types here with import statements
/ 这个接口就是继承自IInterface ,换句话说系统中所有的基于binder通信的aidl 类的祖师爷都是IInterface
public interface BinderLearn extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
* 本地端的IPC 实现 , stub class 继承自 Binder类, 实现了其外部类
* 这是一个静态抽象内部类
*/
public static abstract class Stub extends android.os.Binder implements com.bindertest.BinderLearn {
这是一个写死的私有的静态常量 descriptor ,内容就是包含包名的类全路径
private static final java.lang.String DESCRIPTOR = "com.bindertest.BinderLearn";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
把DESCRIPTOR 与Binder 绑定
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.bindertest.BinderLearn interface,
* generating a proxy if needed.
*/
public static com.bindertest.BinderLearn asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
先查询本地的接口信息 , 通过 DESCRIPTOR 来查询
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.bindertest.BinderLearn))) {
/// 强转返回
return ((com.bindertest.BinderLearn) iin);
}
如果本地也没有查出来 就直接返回 Proxy对象
return new com.bindertest.BinderLearn.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
// 当在A进程中Proxy 调用了mRemote.transact 对应的code值 , 在B进程中的Stub 中的onTransact就会被回调。 根据code 类型分别进入要执行的代码。 通过 reply 需要返回的数据信息 , 写回异常。
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_basicTypes: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0 != data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_queryScore: {
校验接口数据
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
java.lang.String _arg1;
_arg1 = data.readString();
/// 读取数据, 调用queryScore方法,并且返回
int _result = this.queryScore(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_testBinder: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
this.testBinder(_arg0);
reply.writeNoException();
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
/**
* 私有静态内部类 实现了 BinderLearn接口 , 实现了aidl中定义的方法。
*/
private static class Proxy implements com.bindertest.BinderLearn {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean) ? (1) : (0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
/// 查询分数
@Override
public int queryScore(int stuNo, java.lang.String name) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
// 发送 Parcel 内部维护了一个池对象 ,
android.os.Parcel _reply = android.os.Parcel.obtain();
/// 回复消息 , 由 Parcel中的池对象生成 。
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(stuNo);
_data.writeString(name);
mRemote.transact 调用发送信息 注意这里的TRANSACTION_queryScore 传递的是需要调用的code int类型 。
mRemote.transact(Stub.TRANSACTION_queryScore, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void testBinder(java.lang.String nameforTest) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(nameforTest);
mRemote.transact 调用发送信息 注意这里的TRANSACTION_testBinder 传递的是需要调用的code int类型 。
mRemote.transact(Stub.TRANSACTION_testBinder, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_queryScore = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_testBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
这里声明的常量值 为First_call_transation + 0 , 1, 2, 就是方法在类中的声明顺序。
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
public int queryScore(int stuNo, java.lang.String name) throws android.os.RemoteException;
public void testBinder(java.lang.String nameforTest) throws android.os.RemoteException;
}
以上是整个自动生成的BinderLearn类
/**
* Convenience method for associating a specific interface with the Binder.
* After calling, queryLocalInterface() will be implemented for you
* to return the given owner IInterface when the corresponding
* descriptor is requested.
*/
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
调用父类Binder类的attachInterface方法, 将 owner和 descriptor 存储为父类的全局变量。
看一下Binder通信的简单流程图:
这里有两个进程, 进程A和进程B,同时声明了BinderLearn.aidl 生成的类结构上边分析清楚了。
与底层注册 进程A和进程B在注册过程中通过构造函数关联和aidl.asInterface 进程底层Binder的注册。
进程A和进程B之间数据通信。 A和B可以看做A是Client, B进程是Server。
进程A和进程B中的Stub 属于接受来自底层Binder引用的调用,在 onTransact中 根据调用方法编号进行处理。 如果需要回调或者返回值,通过底层Binder引用调用进程B的mRemote.XX方法。
3. 系统服务管理器的简单解析
我们知道我们的系统中有很多应用进程, 例如微信、QQ、支付宝、微博、等等这么多的系统进程都是要使用系统提供的Service的, 也就是说是需要跨进程调用的。
稍等一秒钟,我们思考一下,为什么不把每个应用进程需要使用到的Service 放到每个应用进程中呢?
- 假如说微信、QQ、支付宝 在发消息的时候 需要输入法、 这时候如果每个应用进程都打开一个输入法,会很好性能。 如果一个应用使用了很多种系统服务,如果同时都打开的话会造成大量系统资源的浪费。 于是我们静静地思考了一下,嗯、嗯 、确实没有输入法同一个手机里同一时间打开多个的情况(分屏机制除外)。
- 另外再考虑一下,假如说微信、QQ 、支付宝 都打开了输入法, 如果一个进程修改过输入法,导致了另一个进程使用时候的信息泄露的话,会发生系统性风险。
所以说Binder机制的跨进程是Android系统的基石毫不为过。
再来一张两千万的图:
我们看图中以Binder底层机制为基础之上的, 一系列系统级服务,由SystemService进行注册绑定,提供给应用层各个进程使用, 在源码中或者在我们日常开发中 常用的Context.getSystemService(xxxx)。
我们简单看一下Context结构,
Context 是个抽象类,包含了系统中使用的各种方法,包括获取MainLooper, contentResolver, packageManager 等等。
ContextWrapper 继承自Context , 为什么这么设计的呢, 看一下注释
/**
* Proxying implementation of Context that simply delegates all of its calls to
* another Context. Can be subclassed to modify behavior without changing
* the original Context.
在这里这个类做了一个简单的代理 实现的方法和Context 一样 。 只是委托给了其他对象。
*/
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
/**
* Set the base context for this ContextWrapper. All calls will then be
* delegated to the base context. Throws
* IllegalStateException if a base context has already been set.
*
* @param base The new base context for this wrapper.
*/
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
/**
* @return the base context as set by the constructor or setBaseContext
*/
public Context getBaseContext() {
return mBase;
}
}
查一下源码不难发现 真正实现了Context的类是ContextImpl , 看名字就知道这哥们儿就是实现了Context ContextImpl.java 中包含了 ReceiverRestrictedContext 和 ContextImpl类, ReceiverRestrictedContext这个类继承自ContextWrapper , 用于注册广播接收者, 当然其具体的调用囊括在了ContextImpl 的getReceiverRestrictedContext方法中。
在ContextImpl中我们找到了获取系统方法的Context.getSystemService(xxxx),
代码如下:
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
@Override
public String getSystemServiceName(Class<?> serviceClass) {
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
再看一下SystemServiceRegistry中的实现 。
在静态代码块中注册了一系列服务
static{
registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
new CachedServiceFetcher<ActivityManager>() {
@Override
public ActivityManager createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
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);
}});
}
/**
* Creates an array which is used to cache per-Context service instances.
*/
public static Object[] createServiceCache() {
return new Object[sServiceCacheSize];
}
/**
* 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;
}
/**
* Gets the name of the system-level service that is represented by the specified class.
*/
public static String getSystemServiceName(Class<?> serviceClass) {
return SYSTEM_SERVICE_NAMES.get(serviceClass);
}
/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
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);
}
/**
* Base interface for classes that fetch services.
* These objects must only be created during static initialization.
*/
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}
/**
* Override this class when the system service constructor needs a
* ContextImpl and should be cached and retained by that context.
*/
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;
CachedServiceFetcher() {
// Note this class must be instantiated only by the static initializer of the
// outer class (SystemServiceRegistry), which already does the synchronization,
// so bare access to sServiceCacheSize is okay here.
mCacheIndex = sServiceCacheSize++;
}
@Override
@SuppressWarnings("unchecked")
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 || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
return service;
}
// If we get here, there's no cached instance.
// Grr... if gate is STATE_READY, then this means we initialized the service
// once but someone cleared it.
// We start over from STATE_UNINITIALIZED.
if (gates[mCacheIndex] == ContextImpl.STATE_READY) {
gates[mCacheIndex] = ContextImpl.STATE_UNINITIALIZED;
}
// It's possible for multiple threads to get here at the same time, so
// use the "gate" to make sure only the first thread will call createService().
// At this point, the gate must be either UNINITIALIZED or INITIALIZING.
if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
doInitialize = true;
gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
}
}
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;
}
// The other threads will wait for the first thread to call notifyAll(),
// and go back to the top and retry.
synchronized (cache) {
while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
try {
cache.wait();
} catch (InterruptedException e) {
Log.w(TAG, "getService() interrupted");
Thread.currentThread().interrupt();
return null;
}
}
}
}
}
public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
}
private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES = new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>();
private static int sServiceCacheSize;
在SYSTEM_SERVICE_NAMES 和 SYSTEM_SERVICE_FETCHERS 一个是保存了Service Name , 一个 保存了ServiceFetchers。
我们看一下 CachedServiceFetcher , 这个类就是实现了ServiceFetcher接口,
在getService 方法中会循环在Cache中找到对应的service index 找到对应的Service。 当然如果没有找到的话 就调用createService 。
这个实现就为代码结构留足了空间。 不同的Service 有不同的create方式。
举个栗子
new CachedServiceFetcher<ActivityManager>() {
@Override
public ActivityManager createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}}
不解释,是不是很简单。
对了 创建系统Service缓存的方法是这个
/**
* Creates an array which is used to cache per-Context service instances.
*/
public static Object[] createServiceCache() {
return new Object[sServiceCacheSize];
}
调用时机在ContextImpl
// The system service cache for the system services that are cached per-ContextImpl.
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
想了一会儿, 是不是感觉少了点什么,系统的一系列Service通过SystemService 注册到了binder驱动中,并且缓存在了数组中。 那么SystemService是如何被注册的呢?
/**
* Basic interface for finding and publishing system services.
*
* An implementation of this interface is usually published as the
* global context object, which can be retrieved via
* BinderNative.getContextObject(). An easy way to retrieve this
* is with the static method BnServiceManager.getDefault().
*
* @hide
*/
public interface IServiceManager extends IInterface
{
/**
* Retrieve an existing service called @a name from the
* service manager. Blocks for a few seconds waiting for it to be
* published if it does not already exist.
*/
IBinder getService(String name) throws RemoteException;
/**
* Retrieve an existing service called @a name from the
* service manager. Non-blocking.
*/
IBinder checkService(String name) throws RemoteException;
/**
* Place a new @a service called @a name into the service
* manager.
*/
void addService(String name, IBinder service, boolean allowIsolated, int dumpFlags)
throws RemoteException;
/**
* Return a list of all currently running services.
*/
String[] listServices(int dumpFlags) throws RemoteException;
/**
* Assign a permission controller to the service manager. After set, this
* interface is checked before any services are added.
*/
void setPermissionController(IPermissionController controller)
throws RemoteException;
static final String descriptor = "android.os.IServiceManager";
}
哎呀 我去 这不就是aidl 定义的那个最根儿上的接口吗? 由于篇幅限制精简的 。
我们找到了这个接口的Stub 类 ServiceManagerNative 继承自Binder 实现了 IServiceManager ,当然里边也有Proxy哥们儿。
/**
* Native implementation of the service manager. Most clients will only
* care about getDefault() and possibly asInterface().
* @hide
*/
public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
/**
* Cast a Binder object into a service manager interface, generating
* a proxy if needed.
*/
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.CHECK_SERVICE_TRANSACTION: {
data.enforceInterface(IServiceManager.descriptor);
String name = data.readString();
IBinder service = checkService(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;
int dumpPriority = data.readInt();
addService(name, service, allowIsolated, dumpPriority);
return true;
}
case IServiceManager.LIST_SERVICES_TRANSACTION: {
data.enforceInterface(IServiceManager.descriptor);
int dumpPriority = data.readInt();
String[] list = listServices(dumpPriority);
reply.writeStringArray(list);
return true;
}
case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: {
data.enforceInterface(IServiceManager.descriptor);
IPermissionController controller =
IPermissionController.Stub.asInterface(
data.readStrongBinder());
setPermissionController(controller);
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;
}
public IBinder checkService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
data.writeInt(dumpPriority);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
public String[] listServices(int dumpPriority) throws RemoteException {
ArrayList<String> services = new ArrayList<String>();
int n = 0;
while (true) {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeInt(n);
data.writeInt(dumpPriority);
n++;
try {
boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0);
if (!res) {
break;
}
} catch (RuntimeException e) {
// The result code that is returned by the C++ code can
// cause the call to throw an exception back instead of
// returning a nice result... so eat it here and go on.
break;
}
services.add(reply.readString());
reply.recycle();
data.recycle();
}
String[] array = new String[services.size()];
services.toArray(array);
return array;
}
public void setPermissionController(IPermissionController controller)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeStrongBinder(controller.asBinder());
mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
private IBinder mRemote;
}
这里的方法就不再一一看了,我们大概明白了SystemService 这哥们儿也是个AIDL 进程间通信 ,也是通过了Binder驱动注册在系统内的。 这也为SystemService管理系统的一系列service 提供了基础。
-
从ServiceManagerNative,可以看到,它也是一个抽象类,继承Binder,实现IServiceManager接口。于是它必然会实现asInterface()、asBinder()等Binder所需要的接口方法。但因为它本质上只是起到Proxy作用,作为一个抽象类,它并不可能被实例化,除非有一个非抽象类继承它并实现它所缺少的方法。这种实现在代码层面上没有意义,我们从后面的分析servicemanager的Native实现时也可以看得出来,于是我们虽然看到了onTransact()实现,但实际上它不起作用。
-
这是整个ServiceManagerNative类实现的最有意义的一行。虽然这一行与其他基于IBinder实现的远程类没什么不同,但这一行提供了Proxy接口,这个Proxy接口,则是其他System Service所需要的访问接口。在ServiceManagerNative类的asInterface()方法里,我们会创建并返回一个Proxy对象ServiceManagerPoxy。
-
ServiceManagerProxy对象里实现就没什么特殊之处了。跟会通过Binder访问到Remote Service的其他远程方法一样,会将本地需要调用的方法,将方法名与参数打包,将得到的命令通过Binder发送出去,然后再等着远程执行的返回。
/**
* Private and debugging Binder APIs.
*
* @see IBinder
*/
public class BinderInternal {
private static final String TAG = "BinderInternal";
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
* 获取系统全局的global Context
*/
public static final native IBinder getContextObject();
}
public final class ServiceManager {
private static final String TAG = "ServiceManager";
private static IServiceManager sServiceManager;
private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager =ServiceManagerNative.asInterface(BinderInternal.getContextObject());
/// 通过ServiceManagerNative
return sServiceManager;
}
}
通过BinderInternal.getContextObject() 获取IBinder , 同时ServiceManagerNative 调用 asInterface 创建sServiceManager。 同时ServiceManager 对于系统中的各种服务,统一由SystemService 进行统一管理。当然其中包含了输入法。
4. 总结
网上的大神很多,按理来说实在轮不到我来写Binder这样偏底层的文章。 也实在不敢班门弄斧,但是学的东西比较多,比较杂,如果长时间不整理一下,不总结一下 就会还回去了。 如果有写不对的地方,欢迎大家批评指正。
5. 参考资料
- 任玉刚的Android开发艺术探索 Binder 相关章节
- Android系统源码
- 罗升阳blog
由于篇幅限制,我们下篇见。