Service源码浅析二

Service源码浅析一
Service源码浅析二
Service源码浅析三
Service源码浅析四

咱们带着这几个问题继续分析Service的代码:

  1. binderDied和onServiceDisconnected是否会同时触发?有先后顺序吗?
  2. Service AIDL进程间通信服务端和客户端分别运行在哪个线程?

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,它会调用ActiveServices中的方法stopServiceLocked,然后是bringDownServiceLocked,剩下的流程就和unbind Service中一样了,执行ActivityThread中的一些列操作。

linkToDeath

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

linkToDeath是IBinder方法,它接受一个DeathRecipient作为参数。

    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的实现类是Binder

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

Binder的linkToDeath方法实现也是空的,那它是在哪实现的呢?
其实它的实现类是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方法,它的实现在哪呢?
native实现在

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

追到这里还是一脸懵,服务进程挂了是怎么通知客户端的?
其实它是通过binder驱动直接通知客户端的

+----------------+       +---------------+       +----------------+
| 服务端进程死亡  | ----> | Binder驱动    | ----> | 客户端进程      |
+----------------+       +---------------+       +----------------+
                                |
                                v
                        +-----------------+
                        | 死亡通知工作项  |
                        | (BINDER_WORK_  |
                        |  DEAD_BINDER)  |
                        +-----------------+

Binder驱动可以感知服务端进程死亡,然后回调客户端注册的Java层方法。
咱们在看bindService时应该注意到,传入的ServiceConnection经过LoadedApk包装之后变成了ServiceDispatcher,服务绑定之后会通过doConnected触发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);
                }
            }
        }

这个方法中还藏了一步,它悄悄的给服务端注册了另一个死亡监听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;
        }

最后会通过主线程回调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);
        }

也就是说服务端进程死亡之后,客户自己注册的死亡监听可以收到回调,这里注册的监听也可以收到回调,所以咱们开头的第一个问题就有答案了

    1. binderDied和onServiceDisconnected是否会同时触发?有先后顺序吗?
      不会同时触发,应该是先在Binder线程触发binderDied,再在主线程触发onServiceDisconnected

目前咱们就剩下第2个问题了

    1. Service AIDL进程间通信服务端和客户端分别运行在哪个线程?
      先说答案,以客户端调用服务端为例,客户端侧的逻辑运行在客户端侧的调用进程,服务端的逻辑运行在Binder线程池的线程中,服务端调用客户端同理。

这里涉及Binder通信的原理,可以参考[Binder 一]Binder浅析
咱们先来回顾一下AIDL进程通信的步骤:

  1. 创建 .aidl 文件
    咱们创建一个简单的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. 实现接口
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
    }

客户端绑定服务端成功之后会回调onServiceConnected,这个咱们在上一篇已经跟过流程了。

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

首先,咱们在 build/generated/aidl_source_output_dir下找到编译器为我们自动生成的IRemoteService.java类文件。


AIDL方法调用.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);
    }

该方法会返回服务端的接口对象,如果客户端和服务端在同一个进程,则返回Stub对象本身,如果不在同一进程,则返回Proxy对象。

/**
     * 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构造方法中调用的。

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

跨进程情况下返回的是Proxy对象,

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

Proxy实现了IRemoteService,并持有服务端传过来的IBinder对象,并通过这个对象调用对应的方法

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

以调用getPid方法为例,会触发mRemote.transact,这里发生了进程通信,从客户端进程进入服务端进程,方法transact的实现在Binder类中,接下来都是在服务端进程发生的。

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

会调用到服务端Stub对象的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;
    }

然后会触发自定义Binder对象的getPid方法,并返回结果,这个大体流程就走下来了,但是mRemote.transact是怎么调到服务端进程的,这块还得深究,本篇文章到此结束。

参考:

  1. Android中AIDL的工作原理
  2. Android 接口定义语言 (AIDL)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容