Binder死亡通知机制之linkToDeath
一 概述
死亡通知是为了让Bp端(客户端进程)进能知晓Bn端(服务端进程)的生死情况,当Bn端进程死亡后能通知到Bp端。
- 定义:继承IBinder::DeathRecipient类,主要需要实现其binderDied()来进行死亡通告。
- 注册:IBinder->linkToDeath(DeathRecipient recipient)是为了将死亡通知注册到Binder上。
源代码如下:
/**
* Interface for receiving a callback when the process hosting an IBinder
* has gone away.
*
* @see #linkToDeath
*/
public interface DeathRecipient {
public void binderDied();
/**
* @hide
*/
default void binderDied(IBinder who) {
binderDied();
}
}
注册死亡代理对象DeathRecipient 需要实现此interface,代码实例如
- AMS中注册的binder死亡通知
- bindService时也会注册binder死亡通知.
[1. AMS中定义binder死亡通知]
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
final IApplicationThread mAppThread;
AppDeathRecipient(ProcessRecord app, int pid,
IApplicationThread thread) {
if (DEBUG_ALL) Slog.v(
TAG, "New death recipient " + this
+ " for thread " + thread.asBinder());
mApp = app;
mPid = pid;
mAppThread = thread;
}
@Override
public void binderDied() {
if (DEBUG_ALL) Slog.v(
TAG, "Death received in " + this
+ " for thread " + mAppThread.asBinder());
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread, true, null);
}
}
}
[1.1 AMS中注册死亡监听]
final String processName = app.processName;
try {
// 1.1.1 创建死亡代理通知
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
// 1.1.2 注册死亡代理回调,此处的thread即为ActivityThread内部类ApplicationThread binder对象
thread.asBinder().linkToDeath(adr, 0);
app.setDeathRecipient(adr);
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
mProcessList.startProcessLocked(app,
new HostingRecord("link fail", processName),
ZYGOTE_POLICY_FLAG_EMPTY);
return false;
}
在app进程创建完成后调用AMS.attachApplicationLocked方法时,会为app进程创建死亡代理通知并完成注册.
[2. bindService时定义死亡通知]
private final class DeathMonitor implements IBinder.DeathRecipient
{
DeathMonitor(ComponentName name, IBinder service) {
mName = name;
mService = service;
}
public void binderDied() {
death(mName, mService);
}
final ComponentName mName;
final IBinder mService;
}
[2.2 binderService时注册死亡通知]
// 2.2.1 IBinder service 为Bn侧(server端)的Binder的对象
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
if (mForgotten) {
// We unbound before receiving the connection; ignore
// any connection received.
return;
}
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
if (service != null) {
// A new service is being connected... set it all up.
info = new ConnectionInfo();
info.binder = service;
//2.2.2 创建死亡代理对象
info.deathMonitor = new DeathMonitor(name, service);
try {
//2.2.3 绑定死亡代理对象到service侧,如果service进程挂了,则会通知client端.
service.linkToDeath(info.deathMonitor, 0);
//2.2.4 创建connectInfo对象,put到数组中,数组用于记录此app绑定的所有service连接.
// 用于对端service挂后,做清理. 最耳熟能详的即为调用onServiceConnected方法.
mActiveConnections.put(name, info);
} catch (RemoteException e) {
// This service was dead before we got it... just
// don't do anything with it.
mActiveConnections.remove(name);
return;
}
需要注意,这段定义\注册代码发生在client端 LoadedApk.ServiceDispatcher中.也就是使用service端进程
二 linkToDeath机制解析
linkToDeath定义在IBinder接口中,有两个实现类.
[IBinder.java]
/**
* Register the recipient for a notification if this binder
* goes away. If this binder object unexpectedly goes away
* (typically because its hosting process has been killed),
* then the given {@link DeathRecipient}'s
* {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
* will be called.
*
* <p>This will automatically be unlinked when all references to the linked
* binder proxy are dropped.</p>
*
* <p>You will only receive death notifications for remote binders,
* as local binders by definition can't die without you dying as well.</p>
*
* @throws RemoteException if the target IBinder's
* process has already died.
*
* @see #unlinkToDeath
*/
public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
throws RemoteException;
[Binder.java]
/**
* Local implementation is a no-op.
*/
public void linkToDeath(@NonNull DeathRecipient recipient, int flags) {
}
此处可以理解,process A linkTOdeath process A是没有意义的.
[BinderProxy.java]
/**
* Java proxy for a native IBinder object.
* Allocated and constructed by the native javaObjectforIBinder function. Never allocated
* directly from Java code.
*
* @hide
*/
public final class BinderProxy implements IBinder {
注意看,这里类注释明确说明,此类从native层javaObjectforIBinder 方法所创建的binder所对应java层的代理对象,绝不可能直接从java层创建.
/**
* See {@link IBinder#linkToDeath(DeathRecipient, int)}
*/
public native void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
注意这里BinderProxy的linkToDeath调用到native方法.
[frameworks/base/core/jni/android_util_Binder.cpp]
static const JNINativeMethod gBinderProxyMethods[] = {
/* name, signature, funcPtr */
{"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
{"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
{"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
{"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
{"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
{"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
{"getExtension", "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
};
// 这里传递的object即为java层的BinderProxy
static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
jobject recipient, jint flags) // throws RemoteException
{
if (recipient == NULL) {
jniThrowNullPointerException(env, NULL);
return;
}
//1. 见下文
BinderProxyNativeData *nd = getBPNativeData(env, obj);
// 这里推测获取到server端的native binder代理.此处obj就是server端在java层的代理对象BinderProxy.java
IBinder* target = nd->mObject.get();
//打印监听server侧对象binder和死亡代理recipient
LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
//这里判断server端的binder对象不是localBinder时才进入,因此不存在processA监听死亡代理processA的情况
if (!target->localBinder()) {
//这里拿到server端的死亡代理列表.DeathRecipientList
DeathRecipientList* list = nd->mOrgue.get();
// 封装java层死亡代理对象,创建natice层的死亡代理对象jdr
sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
// 将jdr传递到server端的binder侧.重点分析这里的linkToDeath.见下文2
status_t err = target->linkToDeath(jdr, NULL, flags);
if (err != NO_ERROR) {
// Failure adding the death recipient, so clear its reference
// now.
jdr->clearReference();
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
}
}
}
从ams\bindservice等处注册死亡代理方法linktodeath结合上面代码,Binder.java的linktodeath是空实现.接口BinderProxy.java类注释.可以知道java层用的所有的server端的IBinder接口实际的实现类是BinderProxy.java而非Binder.java
[1 frameworks/base/core/jni/android_util_Binder.cpp -> getBPNativeData]
BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
}
注意这里获取mNativeData,这个成员变量即为BinderProxy.java的成员变量mNativeData.
/**
* C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
* native IBinder object, and a DeathRecipientList.
*/
private final long mNativeData;
这个对象保存的是native层的BinderProxyNativeData
[2. native侧 target->linkToDeath]
[frameworks/native/libs/binder/BpBinder.cpp]
// NOLINTNEXTLINE(google-default-arguments)
status_t BpBinder::linkToDeath(
const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
if (isRpcBinder()) {
if (rpcSession()->getMaxIncomingThreads() < 1) {
ALOGE("Cannot register a DeathRecipient without any incoming threads. Need to set max "
"incoming threads to a value greater than 0 before calling linkToDeath.");
return INVALID_OPERATION;
}
} else if constexpr (!kEnableKernelIpc) {
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
return INVALID_OPERATION;
} else {
if (ProcessState::self()->getThreadPoolMaxTotalThreadCount() == 0) {
ALOGW("Linking to death on %s but there are no threads (yet?) listening to incoming "
"transactions. See ProcessState::startThreadPool and "
"ProcessState::setThreadPoolMaxThreadCount. Generally you should setup the "
"binder "
"threadpool before other initialization steps.",
String8(getInterfaceDescriptor()).c_str());
}
}
Obituary ob;
ob.recipient = recipient;
ob.cookie = cookie;
ob.flags = flags;
LOG_ALWAYS_FATAL_IF(recipient == nullptr,
"linkToDeath(): recipient must be non-NULL");
{
AutoMutex _l(mLock);
if (!mObitsSent) {
if (!mObituaries) {
mObituaries = new Vector<Obituary>;
if (!mObituaries) {
return NO_MEMORY;
}
ALOGV("Requesting death notification: %p handle %d\n", this, binderHandle());
if (!isRpcBinder()) {
if constexpr (kEnableKernelIpc) {
getWeakRefs()->incWeak(this);
IPCThreadState* self = IPCThreadState::self();
self->requestDeathNotification(binderHandle(), this);
self->flushCommands();
}
}
}
// 将死亡代理添加到BpBinder.h成员变量Vector<Obituary>* mObituaries中
ssize_t res = mObituaries->add(ob);
return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
}
}
return DEAD_OBJECT;
}
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓
PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
更多推荐
所有评论(0)