8. frameworks/native/libs/binder/Binder.cpp
由于上述b->transact()中b的实际对象是CameraService(CameraService inherit from BBinder),因此调用 BBinder::transact() ===〉CameraService::onTransact()
因为CameraService没有重写BBinder::transact,所以b->transact()实际调用的就是BBinder::transact
status_tBBinder::transact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply,flags);
//因为CameraService重写了onTransact,
//因此调用CameraService::onTransact()
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
9. frameworks/av/services/camera/libcameraservice/CameraService.cpp
status_tCameraService::onTransact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags) {
// Permission checks
switch (code) {
case BnCameraService::CONNECT:
case BnCameraService::CONNECT_PRO:
const int pid = getCallingPid();
const int self_pid = getpid();
if (pid != self_pid) {
// we're called from adifferent process, do the real check
if (!checkCallingPermission(
String16("android.permission.CAMERA"))){
const int uid =getCallingUid();
ALOGE("PermissionDenial: "
"can't use thecamera pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
}
}
break;
}
returnBnCameraService::onTransact(code, data, reply, flags);
}
10. frameworks/av/ camera/ICameraService.cpp
10.1 BnCameraService::onTransact
status_tBnCameraService::onTransact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
switch(code) {
case GET_NUMBER_OF_CAMERAS: {
CHECK_INTERFACE(ICameraService,data, reply);
reply->writeInt32(getNumberOfCameras());
return NO_ERROR;
} break;
case GET_CAMERA_INFO: {
CHECK_INTERFACE(ICameraService,data, reply);
CameraInfo cameraInfo;
memset(&cameraInfo, 0,sizeof(cameraInfo));
status_t result = getCameraInfo(data.readInt32(),&cameraInfo);
reply->writeInt32(cameraInfo.facing);
reply->writeInt32(cameraInfo.orientation);
reply->writeInt32(result);
return NO_ERROR;
} break;
case CONNECT: {
CHECK_INTERFACE(ICameraService, data,reply);
sp<ICameraClient>cameraClient =
interface_cast<ICameraClient>(data.readStrongBinder());
int32_t cameraId =data.readInt32();
const String16 clientName =data.readString16();
int32_t clientUid =data.readInt32();
sp<ICamera> camera = connect(cameraClient, cameraId,
clientName, clientUid); //真正的处理函数
// connect返回一个CameraClient对象,也就是camera是一个CameraClient对象,
//并作为reply的binder对象返回给客户端
reply->writeStrongBinder(camera->asBinder());
return NO_ERROR;
} break;
case CONNECT_PRO: {
CHECK_INTERFACE(ICameraService,data, reply);
sp<IProCameraCallbacks>cameraClient = interface_cast<IProCameraCallbacks>(data.readStrongBinder());
int32_t cameraId =data.readInt32();
const String16 clientName =data.readString16();
int32_t clientUid =data.readInt32();
sp<IProCameraUser> camera =connect(cameraClient, cameraId,
clientName, clientUid);
reply->writeStrongBinder(camera->asBinder());
return NO_ERROR;
} break;
case ADD_LISTENER: {
CHECK_INTERFACE(ICameraService,data, reply);
sp<ICameraServiceListener>listener =
interface_cast<ICameraServiceListener>(data.readStrongBinder());
reply->writeInt32(addListener(listener));
return NO_ERROR;
} break;
case REMOVE_LISTENER: {
CHECK_INTERFACE(ICameraService,data, reply);
sp<ICameraServiceListener>listener =
interface_cast<ICameraServiceListener>(data.readStrongBinder());
reply->writeInt32(removeListener(listener));
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code,data, reply, flags);
}
}
11. frameworks/av/ services/camera/libcameraservice/CameraService.cpp
仍然由于b->transact()中b的实际对象是CameraService,且connect虚拟方法已经被CameraService改写,因此上述sp<ICamera> camera = connect(cameraClient,cameraId,
clientName, clientUid); //真正的处理函数 实际调用的是CameraService的connect函数
11.1 CameraService::connect
sp<ICamera>CameraService::connect(
const sp<ICameraClient>&cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid) {
String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d\"%s\", id %d)", callingPid,
clientName8.string(), cameraId);
if (!validateConnect(cameraId,/*inout*/clientUid)) {
return NULL;
}
//这里由于是在CameraService内部,而Client是CameraService的一个内部内
//因此这儿 sp<Client>client等价于sp<CameraService::Client> client;
sp<Client> client;
{
Mutex::Autolock lock(mServiceLock);
if (!canConnectUnsafe(cameraId,clientPackageName,
cameraClient->asBinder(),
/*out*/client)) {
return NULL;
} else if (client.get() != NULL) {
return client;
}
int facing = -1;
int deviceVersion =getDeviceVersion(cameraId, &facing);
// If there are other non-exclusiveusers of the camera,
// this will tear them down before we can reuse the camera
if (isValidCameraId(cameraId)) {
// transition from PRESENT ->NOT_AVAILABLE
updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
cameraId);
}
// class CameraClient : public CameraService::Client
// clas CameraService::Client : public BnCamera, publicBasicClient
// class BnCamera: public BnInterface<ICamera>
// class BnInterface : public INTERFACE, public BBinder
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
client = new CameraClient(this,cameraClient,
clientPackageName,cameraId,
facing, callingPid,clientUid, getpid());
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
case CAMERA_DEVICE_API_VERSION_3_0:
client =new Camera2Client(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(),
deviceVersion);
break;
case -1:
ALOGE("Invalid camera id%d", cameraId);
return NULL;
default:
ALOGE("Unknown camera deviceHAL version: %d", deviceVersion);
return NULL;
}
if (!connectFinishUnsafe(client,client->asBinder())) {
// this is probably notrecoverable.. maybe the client can try again
// OK: we can only get here if wewere originally in PRESENT state
updateStatus(ICameraServiceListener::STATUS_PRESENT,cameraId);
return NULL;
}
mClient[cameraId] = client;
LOG1("CameraService::connect X (id%d, this pid is %d)", cameraId,
getpid());
}
// important: release the mutex here so theclient can call back
// into the service from its destructor (can be at the end of the call)
return client; // 返回一个CameraClient 或 Camera2Client对象
}
IPCThreadState::joinThreadPool
从设备中读出数据并执行相应命令
voidIPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID%d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
mOut.writeInt32(isMain ? BC_ENTER_LOOPER :BC_REGISTER_LOOPER);
// This thread may have been spawned by athread that was in the background
//scheduling group, so first we will make sure it is in the foreground
// one to avoid performing an initialtransaction in the background.
set_sched_policy(mMyThreadId,SP_FOREGROUND);
status_t result;
do {
int32_t cmd;
// When we've cleared the incomingcommand queue, process any pending derefs
if (mIn.dataPosition() >=mIn.dataSize()) {
size_t numPending =mPendingWeakDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
RefBase::weakref_type* refs= mPendingWeakDerefs[i];
refs->decWeak(mProcess.get());
}
mPendingWeakDerefs.clear();
}
numPending =mPendingStrongDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i <numPending; i++) {
BBinder* obj =mPendingStrongDerefs[i];
obj->decStrong(mProcess.get());
}
mPendingStrongDerefs.clear();
}
}
// now get the next command to beprocessed, waiting if necessary
result =talkWithDriver(); //读出写入的数据包
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t))continue;
cmd =mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processingtop-level Command: "
<<getReturnString(cmd) << endl;
}
result = executeCommand(cmd); // 执行命令
} else if (result != TIMED_OUT&& result != -ECONNREFUSED && result != -EBADF) {
ALOGE("talkWithDriver(fd=%d)returned unexpected error %d, aborting",
mProcess->mDriverFD,result);
abort();
}
// After executing the command, ensurethat the thread is returned to the
// foreground cgroup before rejoiningthe pool. The driver takes care of
// restoring the priority, but doesn'tdo anything with cgroups so we
// need to take care of that here inuserspace. Note that we do make
// sure to go in the foreground afterexecuting a transaction, but
// there are other callbacks into usercode that could have changed
// our group so we want to makeabsolutely sure it is put back.
set_sched_policy(mMyThreadId,SP_FOREGROUND);
// Let this thread exit the thread poolif it is no longer
// needed and it is not the mainprocess thread.
if(result == TIMED_OUT &&!isMain) {
break;
}
} while (result != -ECONNREFUSED &&result != -EBADF);
LOG_THREADPOOL("**** THREAD %p (PID%d) IS LEAVING THE THREAD POOL err=%p\n",
(void*)pthread_self(), getpid(),(void*)result);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}