16

Binder: addService初探

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzIzNTc5NDY4Nw%3D%3D&%3Bmid=2247485610&%3Bidx=1&%3Bsn=2ef38084699d2fcc5241a6cc57772751
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

MNRNzm3.png!mobile

Binder: ServiceManager的获取 文章中,分析了 ProcessStateIPCThreadState 的创建过程。最后在 defaultServiceManager 中,返回的是持有 BpBinderBpServiceManager 对象。

 int main(int argc __unused, char **argv __unused)
  {
      signal(SIGPIPE, SIG_IGN);
  
      sp<ProcessState> proc(ProcessState::self());
      sp<IServiceManager> sm(defaultServiceManager()); // BpServiceManager
      ALOGI("ServiceManager: %p", sm.get());
      AIcu_initializeIcuOrDie();
      MediaPlayerService::instantiate();
      ResourceManagerService::instantiate();
      registerExtensions();
      ProcessState::self()->startThreadPool();
      IPCThreadState::self()->joinThreadPool();
  }

  void MediaPlayerService::instantiate() {
      defaultServiceManager()->addService(
              String16("media.player"), new MediaPlayerService());
  }

所以在 instantiate 方法中调用的 addService 其实是 BpServiceManager 中的方法,将名称为 media.playerMediaPlayerService 对象进行注册

addService

下面我们直接看 BpServiceManager 中的 addService

virtual status_t addService(const String16& name, const sp<IBinder>& service,
                          bool allowIsolated, int dumpsysPriority) {
  // 封装成Parcel对象
  Parcel data, reply;
  data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
  data.writeString16(name);
  data.writeStrongBinder(service);
  data.writeInt32(allowIsolated ? 1 : 0);
  data.writeInt32(dumpsysPriority);
  // 发送数据到远端
  status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
  return err == NO_ERROR ? reply.readExceptionCode() : err;
}

这里将数据统一封装到 Parcel 对象中,最后通过 remote()transact 方法将数据传输到远端,对应的 codeADD_SERVICE_TRANSACTION

现在我们在来看下 remote() 到底是什么。

它是 BpServiceManager 中的一个方法,这个方法来自于它的父类

class BpServiceManager : public BpInterface<IServiceManager>

public:
  explicit BpServiceManager(const sp<IBinder>& impl) // BpBinder(0)
      : BpInterface<IServiceManager>(impl) {}
 
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote) : BpRefBase(remote)
 
BpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()), mRefs(nullptr), mState(0)

class BpRefBase : public virtual RefBase
{
protected:
  explicit                BpRefBase(const sp<IBinder>& o);
  virtual                 ~BpRefBase();
  virtual void            onFirstRef();
  virtual void            onLastStrongRef(const void* id);
  virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);

  inline  IBinder*        remote()                { return mRemote; }
  inline  IBinder*        remote() const          { return mRemote; }

private:
                          BpRefBase(const BpRefBase& o);
  BpRefBase&              operator=(const BpRefBase& o);

  IBinder* const          mRemote;
  RefBase::weakref_type*  mRefs;
  std::atomic<int32_t>    mState;
};

从上面继承流程可以得到这个 remote() 返回的就是 mRemote ,而 mRemote 其实是最开始的参数 BpBinder(0) 。说明这里调用的是 BpBindertransact 方法

status_t BpBinder::transact(
  uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
  // Once a binder has died, it will never come back to life.
  if (mAlive) {
      status_t status = IPCThreadState::self()->transact(
          mHandle, code, data, reply, flags);
      if (status == DEAD_OBJECT) mAlive = 0;
      return status;
  }

  return DEAD_OBJECT;
}

进入 BpBinder 发现又转调到 IPCThreadStatetransact 方法

status_t IPCThreadState::transact(int32_t handle,
                                uint32_t code, const Parcel& data,
                                Parcel* reply, uint32_t flags)
{

  ...

  // 传输数据
  err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);

  if ((flags & TF_ONE_WAY) == 0) {

      ...
      
      if (reply) {
          // 等待远程数据的返回
          err = waitForResponse(reply);
      } else {
          Parcel fakeReply;
          err = waitForResponse(&fakeReply);
      }

  } else {
      err = waitForResponse(nullptr, nullptr);
  }

  return err;
}

这里主要做的就两件事

  1. writeTransactionData
    Parcel
    cmd
    BC_TRANSACTION
    BC_
    service
    
  2. waitForResponse
    cmd
    BR_REPLY
    BR_
    client
    

今天我们不研究这几个方法,后续文章会专门分析数据的交互。

到这里 MediaPlayerService 已经注册完毕,我们接下最前面的 main 方法继续往下走。

startThreadPool

ProcessState::self()->startThreadPool();

又是 ProcessState 中的方法,进入 startThreadPooll 中看一下。

void ProcessState::startThreadPool()
{
  AutoMutex _l(mLock);
  if (!mThreadPoolStarted) {
      mThreadPoolStarted = true;
      spawnPooledThread(true);
  }
}
 
void ProcessState::spawnPooledThread(bool isMain)
{
  if (mThreadPoolStarted) {
      String8 name = makeBinderThreadName();
      // 开启binder线程池
      sp<Thread> t = new PoolThread(isMain);
      t->run(name.string());
  }
}

spawnPooledThread 方法中创建了 PoolThread 线程池,它继承于 Thread ,最后调用了线程的 run 方法

joinThreadPool

IPCThreadState::self()->joinThreadPool();

继续看 joinThreadPooll 方法, 它在 IPCThreadState

void IPCThreadState::joinThreadPool(bool isMain)
{

  mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

  status_t result;
  do {
      processPendingDerefs();
      // 等待命令行的到来
      result = getAndExecuteCommand();
  } while (result != -ECONNREFUSED && result != -EBADF);

  mOut.writeInt32(BC_EXIT_LOOPER);
  // 与binder驱动通信
  talkWithDriver(false);
}

这里主要的方法是 getAndExecuteCommand() ,它是用来处理接收 service 端发送过来的数据,因为 serviceclient 是可以互相发起数据的交互。这个时候 client 就相当于 service ,它开启轮询不断地监听 service 发过来的数据。最终它会调用 executeCommand 来统一处理。

status_t IPCThreadState::executeCommand(int32_t cmd)
{

  switch ((uint32_t)cmd) {

  ...

  case BR_TRANSACTION_SEC_CTX:
  case BR_TRANSACTION:
      {
          ...

          if (tr.target.ptr) {
              if (reinterpret_cast<RefBase::weakref_type*>(
                      tr.target.ptr)->attemptIncStrong(this)) {
                  // BBinder
                  error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                          &reply, tr.flags);
                  reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
              } else {
                  error = UNKNOWN_TRANSACTION;
              }

          } else {
              error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
          }
          
          ...

          if ((tr.flags & TF_ONE_WAY) == 0) {
              // 向服务端发送回应reply,注意这里的0,特定标识;
              sendReply(reply, 0);
          } else {
              LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
          }

          ...

      }
      break;

  ...

  default:
      ALOGE("*** BAD COMMAND %d received from Binder driver\n", cmd);
      result = UNKNOWN_ERROR;
      break;
  }

  if (result != NO_ERROR) {
      mLastError = result;
  }

  return result;
}

为了简化代码只展示了主要的一部分代码, BR_TRANSACTION 类似于上面所说的 BC_TRANSACTION ,这里代表的是从服务端有数据发送过来,说明服务端主动传输数据。

所以这个时候就与 service 端建立了通信。

至此在 client 端的数据交互流程已经分析完毕,后续我们再来看 binder 传输过程中的 service 端,看它是如何接收与处理数据的。

扫码二维码

获取更多精彩

Android补给站

N7zqQb2.jpg!mobile

Mr2qQnm.gif!mobile

点个 在看 你最好看


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK