Android系统进程间通信(IPC)机制Binder中的Client获(4)

结构体binder_transaction_data在上一篇文章Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析已经介绍过,这里不再累述,这个结构体是用来描述要传输的参数的内容的。这里着重描述一下将要传输的参数tr里面的内容,handle = 0,code =  CHECK_SERVICE_TRANSACTION,cmd = BC_TRANSACTION,data里面的数据分别为:

writeInt32(IPCThreadState::self()->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);   writeString16("Android.os.IServiceManager");   writeString16("media.player");         这是在BpServiceManager::checkService函数里面写进去的,其中前两个是RPC头,Service Manager在收到这个请求时会验证这两个参数是否正确,这点前面也提到了。IPCThread->getStrictModePolicy默认返回0,STRICT_MODE_PENALTY_GATHER定义为:

 

// Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER    #define STRICT_MODE_PENALTY_GATHER 0x100  

       我们不关心这个参数的含义,这不会影响我们分析下面的源代码,有兴趣的读者可以研究一下。这里要注意的是,要传输的参数不包含有Binder对象,因此tr.offsets_size = 0。要传输的参数最后写入到IPCThreadState的成员变量mOut中,包括cmd和tr两个数据。

回到IPCThread::transact函数中,由于(flags & TF_ONE_WAY) == 0为true,即这是一个同步请求,并且reply  != NULL,最终调用:

 

err = waitForResponse(reply);  

进入到waitForResponse函数中:

 

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)   {       int32_t cmd;       int32_t err;          while (1) {           if ((err=talkWithDriver()) < NO_ERROR) break;           err = mIn.errorCheck();           if (err < NO_ERROR) break;           if (mIn.dataAvail() == 0) continue;                      cmd = mIn.readInt32();                      IF_LOG_COMMANDS() {               alog << "Processing waitForResponse Command: "                   << getReturnString(cmd) << endl;           }              switch (cmd) {           case BR_TRANSACTION_COMPLETE:               if (!reply && !acquireResult) goto finish;               break;                      case BR_DEAD_REPLY:               err = DEAD_OBJECT;               goto finish;              case BR_FAILED_REPLY:               err = FAILED_TRANSACTION;               goto finish;                      case BR_ACQUIRE_RESULT:               {                   LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");                   const int32_t result = mIn.readInt32();                   if (!acquireResult) continue;                   *acquireResult = result ? NO_ERROR : INVALID_OPERATION;               }               goto finish;                      case BR_REPLY:               {                   binder_transaction_data tr;                   err = mIn.read(&tr, sizeof(tr));                   LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");                   if (err != NO_ERROR) goto finish;                      if (reply) {                       if ((tr.flags & TF_STATUS_CODE) == 0) {                           reply->ipcSetDataReference(                               reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),                               tr.data_size,                               reinterpret_cast<const size_t*>(tr.data.ptr.offsets),                               tr.offsets_size/sizeof(size_t),                               freeBuffer, this);                       } else {                           err = *static_cast<const status_t*>(tr.data.ptr.buffer);                           freeBuffer(NULL,                               reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),                               tr.data_size,                               reinterpret_cast<const size_t*>(tr.data.ptr.offsets),                               tr.offsets_size/sizeof(size_t), this);                       }                   } else {                       freeBuffer(NULL,                           reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),                           tr.data_size,                           reinterpret_cast<const size_t*>(tr.data.ptr.offsets),                           tr.offsets_size/sizeof(size_t), this);                       continue;                   }               }               goto finish;              default:               err = executeCommand(cmd);               if (err != NO_ERROR) goto finish;               break;           }       }      finish:       if (err != NO_ERROR) {           if (acquireResult) *acquireResult = err;           if (reply) reply->setError(err);           mLastError = err;       }              return err;   }  

这个函数通过IPCThreadState::talkWithDriver与驱动程序进行交互:

 

status_t IPCThreadState::talkWithDriver(bool doReceive)   {       LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");          binder_write_read bwr;          // Is the read buffer empty?        const bool needRead = mIn.dataPosition() >= mIn.dataSize();          // We don't want to write anything if we are still reading        // from data left in the input buffer and the caller        // has requested to read the next data.        const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;          bwr.write_size = outAvail;       bwr.write_buffer = (long unsigned int)mOut.data();          // This is what we'll read.        if (doReceive && needRead) {           bwr.read_size = mIn.dataCapacity();           bwr.read_buffer = (long unsigned int)mIn.data();       } else {           bwr.read_size = 0;       }          ......          // Return immediately if there is nothing to do.        if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;          bwr.write_consumed = 0;       bwr.read_consumed = 0;       status_t err;       do {           ......   #if defined(HAVE_ANDROID_OS)            if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)               err = NO_ERROR;           else               err = -errno;   #else            err = INVALID_OPERATION;   #endif            ......       } while (err == -EINTR);          ......          if (err >= NO_ERROR) {           if (bwr.write_consumed > 0) {               if (bwr.write_consumed < (ssize_t)mOut.dataSize())                   mOut.remove(0, bwr.write_consumed);               else                   mOut.setDataSize(0);           }           if (bwr.read_consumed > 0) {               mIn.setDataSize(bwr.read_consumed);               mIn.setDataPosition(0);           }              ......              return NO_ERROR;       }          return err;   }  

        这里的needRead为true,因此,bwr.read_size大于0;outAvail也大于0,因此,bwr.write_size也大于0。函数最后通过:

 

ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwjjgs.html