Service源碼淺析二

Service源碼淺析一
Service源碼淺析二
Service源碼淺析三
Service源碼淺析四

咱們帶著這幾個(gè)問題繼續(xù)分析Service的代碼:

  1. binderDied和onServiceDisconnected是否會(huì)同時(shí)觸發(fā)?有先后順序嗎?
  2. Service AIDL進(jìn)程間通信服務(wù)端和客戶端分別運(yùn)行在哪個(gè)線程?

Stop Service

public abstract boolean stopService(Intent service);

ContextImpl

    @Override
    public boolean stopService(Intent service) {
        warnIfCallingFromSystemProcess();
        return stopServiceCommon(service, mUser);
    }

    private boolean stopServiceCommon(Intent service, UserHandle user) {
        // // Keep this in sync with ActivityManagerLocal.stopSdkSandboxService
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            int res = ActivityManager.getService().stopService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to stop service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

接下來就到了ActivityManagerService,它會(huì)調(diào)用ActiveServices中的方法stopServiceLocked,然后是bringDownServiceLocked,剩下的流程就和unbind Service中一樣了,執(zhí)行ActivityThread中的一些列操作。

linkToDeath

    public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
            throws RemoteException;

linkToDeath是IBinder方法,它接受一個(gè)DeathRecipient作為參數(shù)。

    public interface DeathRecipient {
        public void binderDied();

        /**
         * The function called when the process hosting an IBinder
         * has gone away.
         *
         * This callback will be called from any binder thread like any other binder
         * transaction. If the process receiving this notification is multithreaded
         * then synchronization may be required because other threads may be executing
         * at the same time.
         *
         * No locks are held in libbinder when {@link binderDied} is called.
         *
         * There is no need to call {@link unlinkToDeath} in the binderDied callback.
         * The binder is already dead so {@link unlinkToDeath} is a no-op.
         * It will be unlinked when the last local reference of that binder proxy is
         * dropped.
         *
         * @param who The IBinder that has become invalid
         */
        default void binderDied(@NonNull IBinder who) {
            binderDied();
        }
    }

IBinder的實(shí)現(xiàn)類是Binder

    /**
     * Local implementation is a no-op.
     */
    public void linkToDeath(@NonNull DeathRecipient recipient, int flags) {
    }

Binder的linkToDeath方法實(shí)現(xiàn)也是空的,那它是在哪實(shí)現(xiàn)的呢?
其實(shí)它的實(shí)現(xiàn)類是BinderProxy,它是IBinder native類的Java層代理

    public void linkToDeath(DeathRecipient recipient, int flags)
            throws RemoteException {
        linkToDeathNative(recipient, flags);
        mDeathRecipients.add(recipient);
    }

    private native void linkToDeathNative(DeathRecipient recipient, int flags)
            throws RemoteException;

linkToDeathNative是native方法,它的實(shí)現(xiàn)在哪呢?
native實(shí)現(xiàn)在

frameworks/platform_frameworks_base/core/jni/android_util_Binder.cpp

static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
        jobject recipient, jint flags) // throws RemoteException
{
    if (recipient == NULL) {
        jniThrowNullPointerException(env, NULL);
        return;
    }

    BinderProxyNativeData *nd = getBPNativeData(env, obj);
    IBinder* target = nd->mObject.get();

    LOG_DEATH_FREEZE("linkToDeath: binder=%p recipient=%p\n", target, recipient);

    if (!target->localBinder()) {
        sp<DeathRecipientList> list = nd->mOrgue;
        sp<JavaDeathRecipient> jdr = sp<JavaDeathRecipient>::make(env, recipient, list);
        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*/);
        }
    }
}

target->linkToDeath最后追到

frameworks/native/libs/binder/BpBinder.cpp

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");

    {
        RpcMutexUniqueLock _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();
                    }
                }
            }
            ssize_t res = mObituaries->add(ob);
            return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
        }
    }

    return DEAD_OBJECT;
}

追到這里還是一臉懵,服務(wù)進(jìn)程掛了是怎么通知客戶端的?
其實(shí)它是通過binder驅(qū)動(dòng)直接通知客戶端的

+----------------+       +---------------+       +----------------+
| 服務(wù)端進(jìn)程死亡  | ----> | Binder驅(qū)動(dòng)    | ----> | 客戶端進(jìn)程      |
+----------------+       +---------------+       +----------------+
                                |
                                v
                        +-----------------+
                        | 死亡通知工作項(xiàng)  |
                        | (BINDER_WORK_  |
                        |  DEAD_BINDER)  |
                        +-----------------+

Binder驅(qū)動(dòng)可以感知服務(wù)端進(jìn)程死亡,然后回調(diào)客戶端注冊(cè)的Java層方法。
咱們?cè)诳碽indService時(shí)應(yīng)該注意到,傳入的ServiceConnection經(jīng)過LoadedApk包裝之后變成了ServiceDispatcher,服務(wù)綁定之后會(huì)通過doConnected觸發(fā)ServiceConnection#onServiceConnected

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;
                    info.deathMonitor = new DeathMonitor(name, service);
                    try {
                        service.linkToDeath(info.deathMonitor, 0);
                        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;
                    }

                } else {
                    // The named service is being disconnected... clean up.
                    mActiveConnections.remove(name);
                }

                if (old != null) {
                    old.binder.unlinkToDeath(old.deathMonitor, 0);
                }
            }

            // If there was an old service, it is now disconnected.
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            if (dead) {
                mConnection.onBindingDied(name);
            } else {
                // If there is a new viable service, it is now connected.
                if (service != null) {
                    mConnection.onServiceConnected(name, service);
                } else {
                    // The binding machinery worked, but the remote returned null from onBind().
                    mConnection.onNullBinding(name);
                }
            }
        }

這個(gè)方法中還藏了一步,它悄悄的給服務(wù)端注冊(cè)了另一個(gè)死亡監(jiān)聽DeathMonitor

        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;
        }

最后會(huì)通過主線程回調(diào)onServiceDisconnected,感覺太雞賊了。

        public void doDeath(ComponentName name, IBinder service) {
            synchronized (this) {
                ConnectionInfo old = mActiveConnections.get(name);
                if (old == null || old.binder != service) {
                    // Death for someone different than who we last
                    // reported...  just ignore it.
                    return;
                }
                mActiveConnections.remove(name);
                old.binder.unlinkToDeath(old.deathMonitor, 0);
            }

            mConnection.onServiceDisconnected(name);
        }

也就是說服務(wù)端進(jìn)程死亡之后,客戶自己注冊(cè)的死亡監(jiān)聽可以收到回調(diào),這里注冊(cè)的監(jiān)聽也可以收到回調(diào),所以咱們開頭的第一個(gè)問題就有答案了

    1. binderDied和onServiceDisconnected是否會(huì)同時(shí)觸發(fā)?有先后順序嗎?
      不會(huì)同時(shí)觸發(fā),應(yīng)該是先在Binder線程觸發(fā)binderDied,再在主線程觸發(fā)onServiceDisconnected

目前咱們就剩下第2個(gè)問題了

    1. Service AIDL進(jìn)程間通信服務(wù)端和客戶端分別運(yùn)行在哪個(gè)線程?
      先說答案,以客戶端調(diào)用服務(wù)端為例,客戶端側(cè)的邏輯運(yùn)行在客戶端側(cè)的調(diào)用進(jìn)程,服務(wù)端的邏輯運(yùn)行在Binder線程池的線程中,服務(wù)端調(diào)用客戶端同理。

這里涉及Binder通信的原理,可以參考[Binder 一]Binder淺析
咱們先來回顧一下AIDL進(jìn)程通信的步驟:

  1. 創(chuàng)建 .aidl 文件
    咱們創(chuàng)建一個(gè)簡(jiǎn)單的AIDL文件
interface IRemoteService {
    int getPid();
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}
  1. 實(shí)現(xiàn)接口
private val binder = object : IRemoteService.Stub() {
        override fun getPid(): Int {
            return Process.myPid()
        }

        override fun basicTypes(
            anInt: Int,
            aLong: Long,
            aBoolean: Boolean,
            aFloat: Float,
            aDouble: Double,
            aString: String?
        ) {
        }

    }
  1. 向客戶端公開該接口
    override fun onBind(intent: Intent?): IBinder {
        return binder
    }

客戶端綁定服務(wù)端成功之后會(huì)回調(diào)onServiceConnected,這個(gè)咱們?cè)谏弦黄呀?jīng)跟過流程了。

private val mConnection = object : ServiceConnection {

        override fun onServiceConnected(className: ComponentName, service: IBinder) {
            // This is called when the connection with the service is
            // established, giving us the service object we can use to
            // interact with the service.  We are communicating with our
            // service through an IDL interface, so get a client-side
            // representation of that from the raw service object.
            mService = IRemoteService.Stub.asInterface(service)
        }

        override fun onServiceDisconnected(className: ComponentName) {
            // This is called when the connection with the service is
            // unexpectedly disconnected&mdash;that is, its process crashed.
            mService = null
        }
    }

首先,咱們?cè)?build/generated/aidl_source_output_dir下找到編譯器為我們自動(dòng)生成的IRemoteService.java類文件。


AIDL方法調(diào)用.png

從上圖中可以看到asInterface是Stub的方法

/**
     * Cast an IBinder object into an com.example.serverdemo.IRemoteService interface,
     * generating a proxy if needed.
     */
    public static com.example.serverdemo.IRemoteService asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.example.serverdemo.IRemoteService))) {
        return ((com.example.serverdemo.IRemoteService)iin);
      }
      return new com.example.serverdemo.IRemoteService.Stub.Proxy(obj);
    }

該方法會(huì)返回服務(wù)端的接口對(duì)象,如果客戶端和服務(wù)端在同一個(gè)進(jìn)程,則返回Stub對(duì)象本身,如果不在同一進(jìn)程,則返回Proxy對(duì)象。

/**
     * Use information supplied to {@link #attachInterface attachInterface()}
     * to return the associated {@link IInterface} if it matches the requested
     * descriptor.
     */
    public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
        if (mDescriptor != null && mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

可以看到queryLocalInterface返回的是attachInterface中的接口,attachInterface是在Stub構(gòu)造方法中調(diào)用的。

public static abstract class Stub extends android.os.Binder implements com.example.serverdemo.IRemoteService
  {
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
}

跨進(jìn)程情況下返回的是Proxy對(duì)象,

private static class Proxy implements com.example.serverdemo.IRemoteService
    {
      private android.os.IBinder mRemote;
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }
}

Proxy實(shí)現(xiàn)了IRemoteService,并持有服務(wù)端傳過來的IBinder對(duì)象,并通過這個(gè)對(duì)象調(diào)用對(duì)應(yīng)的方法

@Override public int getPid() throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        int _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          boolean _status = mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);
          _reply.readException();
          _result = _reply.readInt();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }

以調(diào)用getPid方法為例,會(huì)觸發(fā)mRemote.transact,這里發(fā)生了進(jìn)程通信,從客戶端進(jìn)程進(jìn)入服務(wù)端進(jìn)程,方法transact的實(shí)現(xiàn)在Binder類中,接下來都是在服務(wù)端進(jìn)程發(fā)生的。

    /**
     * Default implementation rewinds the parcels and calls onTransact. On
     * the remote side, transact calls into the binder to do the IPC.
     */
    public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);

        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }

會(huì)調(diào)用到服務(wù)端Stub對(duì)象的onTransact方法。

    @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
    {
      java.lang.String descriptor = DESCRIPTOR;
      if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
        data.enforceInterface(descriptor);
      }
      switch (code)
      {
        case INTERFACE_TRANSACTION:
        {
          reply.writeString(descriptor);
          return true;
        }
      }
      switch (code)
      {
        case TRANSACTION_getPid:
        {
          int _result = this.getPid();
          reply.writeNoException();
          reply.writeInt(_result);
          break;
        }
        case TRANSACTION_basicTypes:
        {
          int _arg0;
          _arg0 = data.readInt();
          long _arg1;
          _arg1 = data.readLong();
          boolean _arg2;
          _arg2 = (0!=data.readInt());
          float _arg3;
          _arg3 = data.readFloat();
          double _arg4;
          _arg4 = data.readDouble();
          java.lang.String _arg5;
          _arg5 = data.readString();
          this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
          reply.writeNoException();
          break;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
      return true;
    }

然后會(huì)觸發(fā)自定義Binder對(duì)象的getPid方法,并返回結(jié)果,這個(gè)大體流程就走下來了,但是mRemote.transact是怎么調(diào)到服務(wù)端進(jìn)程的,這塊還得深究,本篇文章到此結(jié)束。

參考:

  1. Android中AIDL的工作原理
  2. Android 接口定義語言 (AIDL)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容