一 概述

死亡通知是为了让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,代码实例如

  1. AMS中注册的binder死亡通知
  2. 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开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
图片

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐