Android 平台 Binder 机制 简介
Binder : android 平台的一种IPC机制,在kernel中封装消息规则,在用户空间提供接口对消息规则进一步封装,以达到IPC通信的目的。
Android 平台中的基本组件,Activity,Service,BroadcastReceiver,ContentProvider,都是基于Binder进行IPC通讯。
下面以ContentProvider为例进行说明Binder的通信机制。
Androdid平台一个App可以访问另外一个App中的数据库:
- AMS: ActivityManagerService
- App2: 实现数据库服务的应用
- App1: 访问数据库的应用
- Binder驱动:Binder驱动层支持
- IContentProvider:数据库服务跨进程访问接口
数据库跨进程访问基本流程:
- App2启动之后,会将数据库的IContentProvider接口publish到AMS,即BpBinder
- App1从AMS中得到数据库的IContentProvider接口,将其封装,保存在本地,即BpBinder
- 得到接口之后,就可以通过IContentProvider接口访问App2中的数据,,不必经过AMS
Step 1:App2启动并将数据库publish到AMS
- 应用启动,install provider:
private void handleBindApplication(AppBindData data) {
if (!data.restrictedBackupMode) {
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
}
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<IActivityManager.ContentProviderHolder> results =
new ArrayList<IActivityManager.ContentProviderHolder>();
for (ProviderInfo cpi : providers) {
if (DEBUG_PROVIDER) {
StringBuilder buf = new StringBuilder(128);
buf.append("Pub ");
buf.append(cpi.authority);
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
}
IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
}
}
- 将ContentProvider publish到 AMS
public void publishContentProviders(IApplicationThread caller,
List<ContentProviderHolder> providers) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeTypedList(providers);
mRemote.transact(PUBLISH_CONTENT_PROVIDERS_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
Step 2:App1从AMS中得到数据库的IContentProvider接口
- 获取数据库接口一般通过如下语句:
ContentResolver resolver = context.getContentResolver();
resolver.query(...);
- ContentResolver 的实现位于ContextImpl.java ApplicationContentResolver
private static final class ApplicationContentResolver extends ContentResolver {
@Override
protected IContentProvider acquireProvider(Context context, String auth) {
return mMainThread.acquireProvider(context,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), true);
}
}
- query 流程中会通过 acquiryProvider 得到 IContentProvider 接口:
public ContentProviderHolder getContentProvider(IApplicationThread caller,
String name, int userId, boolean stable) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(name);
data.writeInt(userId);
data.writeInt(stable ? 1 : 0);
mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
ContentProviderHolder cph = null;
if (res != 0) {
cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
}
data.recycle();
reply.recycle();
return cph;
}
Step 3:得到接口之后,通过IContentProvider接口访问App2中的数据库数据
上面大致说了一下IPC通信的基本流程,具体通过Binder传递Binder对象下面进一步说明。
1、服务端Binder对象
服务端的Binder对象,这里是ContentProvider都是继承自Binder,对java层来说。
class Transport extends ContentProviderNative
abstract public class ContentProviderNative extends Binder implements IContentProvider
可以看到这个ContentProvider中的Transport就是一个Binder。
既然是一个Binder,需要了解一下这个Binder对象的初始化过程:
public class Binder implements IBinder{
public Binder() {
init();//这是一个native方法
}
private native final void init();
}
native实现
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
jbh->incStrong((void*)android_os_Binder_init);
env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
这里的 JavaBBinderHolder 在进行进程间通信的时候或调用get方法,得到一个BBinder:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
}
return b;
}
class JavaBBinder : public BBinder
也就是说,我们说的java层的Binder都有一个Native对应的BBinder。
Binder作为服务端,除非died,否则应该一直等待client发来消息,那么这个Binder是如何实现等待呢?
这就涉及到App启动过程中线程池的开启,App都是zygote进行fork出来的,在初始化的时候会开启线程池:
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
void IPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
do {
result = getAndExecuteCommand();
} while (result != -ECONNREFUSED && result != -EBADF);
}
status_t IPCThreadState::getAndExecuteCommand()
{
result = talkWithDriver();
result = executeCommand(cmd);
}
talkWithDriver会利用系统调用ioctl告诉kernel BC_ENTER_LOOPER,就是说我服务端准备好了。
当收到client的消息之后,就调用onTransact,也就是 JavaBBinder的onTransact
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
}
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
res = onTransact(code, data, reply, flags);
}
就调用到Binder的 onTransact,解析命令,执行对应的函数。
2、Client BpBinder 对象
待续。。。
推荐阅读
-
IPC机制系列之四 Android Binder连接池
-
android binder机制---Binder驱动
-
Binder机制简介
-
Android Binder通信机制
-
android binder机制,注册系统服务--服务端servicemanager binder驱动
-
Android Binder机制(三) Binder相关的接口和类
-
Android 平台 Binder 机制 简介
-
Android Binder 机制初步学习 笔记(三)—— Binder 进程通讯库简介
-
[RK3399][Android7.1]通信机制 Binder
-
Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路