美文网首页
Binder死亡通知机制之linkToDeath

Binder死亡通知机制之linkToDeath

作者: 小城哇哇 | 来源:发表于2023-07-23 16:35 被阅读0次

    一 概述

    死亡通知是为了让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;
    }
    
    

    相关文章

      网友评论

          本文标题:Binder死亡通知机制之linkToDeath

          本文链接:https://www.haomeiwen.com/subject/rpofpdtx.html