您好,登錄后才能下訂單哦!
今天小編給大家分享一下如何連接建立后的client和Service通信的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
這里以CameraService::connect()為例進行說明。
@Camera.cpp
sp<Camera> Camera::connect()
{
LOGV("connect");
sp<Camera> c = new Camera();
const sp<ICameraService>& cs = getCameraService();
if (cs != 0) {
c->mCamera = cs->connect(c);//這條語句將進入BpCameraService::connect()
}
return c;
}
@ICameraService.cpp
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(cameraClient->asBinder());
remote()->transact(BnCameraService::CONNECT, data, &reply);
return interface_cast<ICamera>(reply.readStrongBinder());
}
這里remote是我們的CameraService映射的一個BpBinder對象
virtual sp<ICamera> ICameraService:: connect()會調用到BpBinder::transact()
à IPCThreadState::self()->transact(),并寫入binder driver中,
Binder driver最終會喚醒media_server進程中的在IPCThreadState::joinThreadPool()中運行的讀線程。
void IPCThreadState::joinThreadPool(bool isMain)
{ …
do {
…
result = talkWithDriver();
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) continue;
cmd = mIn.readInt32();
result = executeCommand(cmd);
} while (result != -ECONNREFUSED && result != -EBADF);
…
}
這一次,talkWithDriver()函數會返回BpCameraService:: connect ()生成的數據包,并調用executeCommand()函數執行命令。在本例中,命令為BR_TRANSACTION。
status_t IPCThreadState::executeCommand(int32_t cmd)
{
......
switch(cmd){
......
case BR_TRANSACTION:
{
binder_transaction_data tr;
......
Parcel reply;
......
if (tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, 0);
}
…
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
sendReply(reply, 0);
}
...
}
break;
......
} // end of switch
...
}
if(tr.target.ptr)為真的分支部分是最重要的。它從binder內核驅動中獲取到一個地址并轉換為BBinder類型的指針(該指針在執行IServiceManager::addService()函數時放入binder內核驅動)。記住,CameraService繼承自BBinder。該指針實際上與CameraService實例是同一個指針。于是接下來的transact()函數將調用到CaermaService::onTransact(),再調用到BnCameraService::onTransact()虛函數。
@CameraService.cpp
status_t CameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case BnCameraService::CONNECT:
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int self_pid = getpid();
if (pid != self_pid) {
// we're called from a different process, do the real check
if (!checkCallingPermission(
String16("android.permission.CAMERA")))
{
const int uid = ipc->getCallingUid();
LOGE("Permission Denial: "
"can't use the camera pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
}
}
break;
}
status_t err = BnCameraService::onTransact(code, data, reply, flags);
return err;
}
@ICameraService.cpp
status_t BnCameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case CONNECT: {
CHECK_INTERFACE(ICameraService, data, reply);
sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
sp<ICamera> camera = connect(cameraClient); //真正的處理函數
reply->writeStrongBinder(camera->asBinder());
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
至此完成了一次從client到service的函數調用過程。
注意在這個函數中,系統將調用CameraService::connect()
以上就是“如何連接建立后的client和Service通信”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。