相關(guān)文章鏈接:
1. Android Framework - 學(xué)習(xí)啟動篇
2. Android Binder 驅(qū)動 - Media 服務(wù)的添加過程
3. Android Binder 驅(qū)動 - 啟動 ServiceManager 進(jìn)程
4. Android Binder 驅(qū)動 - 內(nèi)核驅(qū)動層源碼分析
5. Android Binder 驅(qū)動 - 從驅(qū)動層來分析服務(wù)的添加過程
6. Android Binder 驅(qū)動 - 從 Java 層來跟蹤服務(wù)的查找過程
7. Android 四大組件 - 進(jìn)程的 fork 創(chuàng)建過程
相關(guān)源碼文件:
/frameworks/base/core/java/android/app/ContextImpl.java
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/frameworks/base/core/jni/android_util_Binder.cpp
/frameworks/base/core/jni/android_os_Parcel.cpp
/frameworks/native/libs/binder/Parcel.cpp
/drivers/staging/android/binder.c
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
/frameworks/base/core/java/android/app/ActivityThread.java
1. 代碼示例
本文主要從 bindService 的跨進(jìn)程通信與數(shù)據(jù)交互來入手分析雅宾,關(guān)于其具體的創(chuàng)建和綁定流程坷备,大家可以看看之前的內(nèi)容秽晚。aidl 一直都是一個晦澀難懂的內(nèi)容,筆者在幾年前也曾反復(fù)嘗試去了解其原理,其過程至今想想仍然是心有余悸趁桃,因此建議大家如果是剛?cè)胧?Android 其垄,只需要了解開發(fā)套路就可以了。但還是倡導(dǎo)大家笋颤,等有了一定技術(shù)沉淀之后,要嘗試著去理解其內(nèi)部實(shí)現(xiàn)原理内地。我們先來看一個簡單的示例代碼
// 客戶端
public class MainActivity extends AppCompatActivity {
// 客戶端一定要獲取aidl的實(shí)例
private UserAidl mUserAidl;
private ServiceConnection mServiceConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 鏈接好了 service就是服務(wù)端給我們的 IBinder
mUserAidl = UserAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// 斷開鏈接
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MessageService.class);
bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
}
public void testClick(View view) {
try {
Log.e("TAG","userName = "+mUserAidl.getUserName());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
// 服務(wù)端
public class MessageService extends Service {
@Override
public IBinder onBind(Intent intent) {
// 綁定
return mBinder;
}
private final UserAidl.Stub mBinder = new UserAidl.Stub()
{
@Override
public String getUserName() throws RemoteException {
return "Darren@163.com";
}
@Override
public String getUserPassword() throws RemoteException {
return "19940223";
}
};
}
2. Binder 對象初始化
服務(wù)端返回的是 Aidl.Stub 服務(wù)對象伴澄,這個對象是我們自定義 aidl 后,編譯器幫我們自動生成的一個對象阱缓,該對象繼承自 Binder.java 對象非凌,子類在構(gòu)建對象時默認(rèn)會執(zhí)行父類的構(gòu)造函數(shù),也就是說會執(zhí)行 Binder.java 的構(gòu)造函數(shù):
public Binder() {
// 調(diào)用初始化方法
init();
}
// 調(diào)用 native 方法
private native final void init();
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
...
env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
由上面的源碼可以看出荆针,Stub 對象在構(gòu)建的時候敞嗡,會對應(yīng)綁定 native 層的一個 JavaBBinderHolder 對象颁糟,至于為什么要創(chuàng)建 native 層對象,是因?yàn)榭邕M(jìn)程通信的核心是要基于 binder 驅(qū)動喉悴。
3. Stub 對象傳遞
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
...
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess();
// 像 AMS 發(fā)起 bind 請求
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
}
由于 ServiceConnection 是一個普通對象棱貌,并不能用來做跨進(jìn)程傳遞,所以在 bindService 的源碼底層箕肃,系統(tǒng)幫我包裝了一個可以跨進(jìn)程傳遞的 IServiceConnection 對象婚脱,該對象是一個 Stub 對象。
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags, String callingPackage, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(token);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
// asBinder 返回的是 connection 自身
data.writeStrongBinder(connection.asBinder());
data.writeInt(flags);
data.writeString(callingPackage);
data.writeInt(userId);
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
// 返回的其實(shí)是一個 JavaBBinder
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
...
return NULL;
}
// 這個之前的文章有講就不再貼代碼了
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
上面會調(diào)用 writeStrongBinder 方法將 IServiceConnection 對象寫入到 Parcel 內(nèi)存中勺像,其實(shí)也就是將 native 層的 JavaBBinder 對象寫入到 native 層的 Parcel 中障贸,關(guān)于 flatten_binder 方法的實(shí)現(xiàn)原理大家可以參考之前的文章。
4. 客戶端驅(qū)動層處理過程
我們向 ServiceManager 查詢到的 AMS 對象吟宦,其實(shí)是一個 BindProxy.java 對象篮洁,對應(yīng) native 層的 BpBinder 對象,也就是說 mRemote.transact 最后會調(diào)用 BpBinder.cpp 的 transact 方法督函。
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
if (reply) {
...
} else {
if (tr->target.handle) {
struct binder_ref *ref;
// 找到 AMS 目標(biāo)進(jìn)程的 binder_node 和 binder_proc
ref = binder_get_ref(proc, tr->target.handle);
target_node = ref->node;
} else {
...
}
...
}
...
off_end = (void *)offp + tr->offsets_size;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
...
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
switch (fp->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
struct binder_ref *ref;
// 先通過 fp->binder 從自己進(jìn)程找 binder_node
struct binder_node *node = binder_get_node(proc, fp->binder);
// 剛開始第一次是找不到的
if (node == NULL) {
// 把他添加到當(dāng)前進(jìn)程
node = binder_new_node(proc, fp->binder, fp->cookie);
...
}
// 添加到目標(biāo)進(jìn)程
ref = binder_get_ref_for_node(target_proc, node);
if (ref == NULL) {
return_error = BR_FAILED_REPLY;
goto err_binder_get_ref_for_node_failed;
}
// 替換 type 和 handle 值
if (fp->type == BINDER_TYPE_BINDER)
fp->type = BINDER_TYPE_HANDLE;
else
fp->type = BINDER_TYPE_WEAK_HANDLE;
fp->handle = ref->desc;
} break;
...
}
}
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
// 喚醒目標(biāo)進(jìn)程的等待隊(duì)列
if (target_wait)
wake_up_interruptible(target_wait);
return;
}
5. AMS 服務(wù)端處理 bind 過程
AMS 接收到 bindService 請求后會去讀取 IServiceConnection 對象嘀粱,注意這里讀取到的 IServiceConnection 其實(shí)已經(jīng)是本地的一個 BpBinder 了,只不過我們可以通過 BpBinder 對象回調(diào)到客戶端的 onServiceConnected 綁定方法辰狡。
case BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
int fl = data.readInt();
String callingPackage = data.readString();
int userId = data.readInt();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
int res = bindService(app, token, service, resolvedType, conn, fl, callingPackage, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
}
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
}
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
6. 進(jìn)程循環(huán)等待處理請求
服務(wù)端處理客戶端的請求锋叨,肯定會有一個等待執(zhí)行處理的過程,但整個交互邏輯流程分析下來宛篇,并沒有發(fā)現(xiàn)服務(wù)端有等待的過程娃磺。那服務(wù)端到底是怎樣進(jìn)入等待的呢?這個得追溯到 Zygote 創(chuàng)建進(jìn)程的流程去叫倍。
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv, classLoader);
}
private static final native void nativeZygoteInit();
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
virtual void onZygoteInit()
{
// 初始化 binder 驅(qū)動
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
// 啟動一個線程進(jìn)入循環(huán)處理客戶端 binder 請求
proc->startThreadPool();
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
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)
{
...
status_t result;
do {
...
// 進(jìn)入 binder 驅(qū)動的 wait 隊(duì)列上進(jìn)行等待
result = getAndExecuteCommand();
...
} while (result != -ECONNREFUSED && result != -EBADF);
...
}