sm(BpServiceManager(BpBinder(handle= 0))) = defaultServiceManager()
binder =sm->getServcie(String16(kCameraServiceName))
cs =(BpCameraService(BpBinder))
c->mCamera =cs->connect(…); // 返回 BpCamera(BpBinder)
最后c->mCamera指向一个BpCamera(BpBinder)
1. frameworks/base/core/java/android/hardware/camera.java
1.1 Open
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
/**
* Creates a new Camera object to access the first back-facing camera onthe
* device. If the device does not have a back-facing camera, this returns
* null.
* @see #open(int)
*/
public static Camera open() {
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
return null;
}
1.2 Camera Constructor
Camera(int cameraId) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this,looper);
} else {
mEventHandler = null;
}
String packageName = ActivityThread.currentPackageName();
native_setup(newWeakReference<Camera>(this), cameraId, packageName);
}
2. frameworks/base/core/jni/android_hardware_Camera.cpp
// connect tocamera service
static voidandroid_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jstringclientPackageName)
{
// Convert jstring to String16
const char16_t *rawClientName =env->GetStringChars(clientPackageName, NULL);
jsize rawClientNameLen =env->GetStringLength(clientPackageName);
String16 clientName(rawClientName,rawClientNameLen);
env->ReleaseStringChars(clientPackageName,rawClientName);
// 这儿模板实例是Camera
// Camera::connect()返回一个Camera对象
// 因此camera是一个Camera对象
sp<Camera>camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
if (camera == NULL) {
jniThrowRuntimeException(env,"Fail to connect to camera service");
return;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
jniThrowRuntimeException(env,"Camera initialization failed");
return;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
jniThrowRuntimeException(env,"Can't find android/hardware/Camera");
return;
}
// We use a weak reference so the Cameraobject can be garbage collected.
// The reference is only used as a proxyfor callbacks.
// 将camera(本地Camera对象)保存在Java上下文
sp<JNICameraContext>context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);
// save context in opaque field
env->SetIntField(thiz, fields.context,(int)context.get());
}
3. frameworks/av/camera/Camera.cpp
sp<Camera>Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid)
{
// 这儿模板实例是Camera
returnCameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
Notes:
Inframeworks/av/include/camera/CameraBase.cpp
template<typename TCam, typename TCamTraits = CameraTraits<TCam> >
class CameraBase: public IBinder::DeathRecipient
{
typedef CameraBase<TCam> CameraBaseT;
};
4. frameworks/av/camera/CameraBase.cpp
4.1 connect
template<typename TCam, typename TCamTraits>
sp<TCam>CameraBase<TCam, TCamTraits>::connect(int cameraId,
constString16& clientPackageName,
int clientUid)
{
// 上层模板实例是Camera,因此这儿TCam就是 Camera
ALOGV("%s: connect",__FUNCTION__);
//模板实例是一个Camera,因此c是一个Camera对象
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
constsp<ICameraService>& cs = getCameraService();
//这儿getCameraService 返回的是一个BpCameraService对象,并将一个BpBinder
// 对象赋值给BpCameraService对象的成员变量mRemote,
//这些是通过getCameraService调用defaultServiceManager()及interface_cast函数来实现的
if (cs != 0) { // mCamera定义在 CameraBase类中
c->mCamera =cs->connect(cl, cameraId, clientPackageName, clientUid);
// 这里 cs->connect返回的是一个BpCamera对象,因此 c->mCamera保存的是一个BpCamera对象。
// BpCamera也有一个mRemote对象,也指向一个BpBinder对象(看下面BpCameraService::connect,
// 这个BpBinder就是依据reply中得到的BnBinder(BnCameraService)生成的对应的本地接口BpBinder),
// 也就是说在这儿得到Service的response.
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
c.clear();
}
return c;
}
4.2getCameraService
// establishbinder interface to camera service
template<typename TCam, typename TCamTraits>
constsp<ICameraService>& CameraBase<TCam,TCamTraits>::getCameraService()
{
Mutex::Autolock _l(gLock);
if (gCameraService.get() == 0) {
sp<IServiceManager>sm = defaultServiceManager();
// sm是一个BpServiceManager, 并且BpServiceManager的mRemote成员变量
// 将指向一个BpBinder(handle = 0), 0代表 ServiceManager.
sp<IBinder> binder;
do {
//这儿从getService()返回的binder是一个BpBinder对象.服务端返回的
//是一个BnCameraService?之类的BnBinder对象,客户端在checkService中
//将通过readStrongBinder来依据这个BnBinder对象来生成本地接口BpBinder对象。
binder =sm->getService(String16(kCameraServiceName));
if (binder != 0) {
break;
}
ALOGW("CameraService notpublished, waiting...");
usleep(kCameraServicePollDelay);
} while(true);
if (gDeathNotifier == NULL) {
gDeathNotifier = newDeathNotifier();
}
binder->linkToDeath(gDeathNotifier);
// interface_cast函数将生成一个BpCameraService对象,并把binder(BpBinder对象)
//赋值给mRemote成员变量,即gCameraService是一个BpCameraService对象。
gCameraService= interface_cast<ICameraService>(binder);
}
ALOGE_IF(gCameraService == 0, "noCameraService!?");
return gCameraService;
}
首先取得跨进程的IServiceManager,然后取得camera service(这个service在mediaserver启动时注册)。最重要的,把这个返回的binder对象经过interface_cast<ICameraService>处理,生成一个BpCameraService对象,并将binder对象赋值给BpCameraService的成员变量mRemote. Interface_cast在 frameworks/native/include/binder/IInterface.h中实现。
namespaceandroid {
//----------------------------------------------------------------------
class IInterface: public virtual RefBase
{
public:
IInterface();
sp<IBinder> asBinder();
sp<const IBinder> asBinder() const;
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
//----------------------------------------------------------------------
template<typenameINTERFACE>
inlinesp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
//----------------------------------------------------------------------
template<typenameINTERFACE>
classBnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16&_descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
//----------------------------------------------------------------------
template<typenameINTERFACE>
classBpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
//----------------------------------------------------------------------
#defineDECLARE_META_INTERFACE(INTERFACE) \
static const android::String16descriptor; \
static android::sp<I##INTERFACE>asInterface( \
constandroid::sp<android::IBinder>& obj); \
virtual const android::String16&getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
#defineIMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp<I##INTERFACE>I##INTERFACE::asInterface( \
constandroid::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE>intr; \
if (obj != NULL) { \
intr =static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr =new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
#define CHECK_INTERFACE(interface,data, reply) \
if (!data.checkInterface(this)) { returnPERMISSION_DENIED; } \
//----------------------------------------------------------------------
// Nouser-serviceable parts after this...
template<typenameINTERFACE>
inlinesp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor)return this;
return NULL;
}
template<typenameINTERFACE>
inline const String16&BnInterface<INTERFACE>::getInterfaceDescriptor() const
{
return INTERFACE::getInterfaceDescriptor();
}
template<typenameINTERFACE>
IBinder*BnInterface<INTERFACE>::onAsBinder()
{
return this;
}
template<typenameINTERFACE>
inlineBpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
template<typenameINTERFACE>
inline IBinder*BpInterface<INTERFACE>::onAsBinder()
{
return remote();
}
//----------------------------------------------------------------------
}; // namespaceandroid
5. frameworks/av/camera/ICameraService.cpp
5.1 BpCameraService::connect
c->mCamera = cs->connect(cl, cameraId,clientPackageName, clientUid);
由于cs是经过interace_cast得到的BpCameraService,因此实际调用 BpCameraService::connect.
// connect to camera service
virtual sp<ICamera> BpCameraService::connect(constsp<ICameraClient>& cameraClient, int cameraId,
const String16&clientPackageName, int clientUid)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(cameraClient->asBinder());
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
remote()->transact(BnCameraService::CONNECT, data, &reply);
returninterface_cast<ICamera>(reply.readStrongBinder());
// 这里又一次用到了interface_cast,在interface_cast里,
// 将生成一个newBpCamera(binder object),
// 客户端将从reply中得到的服务端CameraClient对象,
// 经readStrongBinder()生成的相应的本地接口BpBinder对象。
// in BpCamera构造函数里,实际上是通过其基类BpRefBase的构造函数,
//(CameraClient继承自BnCameraClient,BnCameraClient继承自BBinder),
// 将这个本地接口(BpBinder)赋值给mRemote成员变量,也就是说BpCamera对象的mRemote成
// 员变量实际上指向从服务器端返回的CameraClient对象向对应的BpBinder本地接口对象
// 这样在BpCamera和 BnCamera之间建立了一一对应的关系。Camera后面的操作,
// 如startPreview等就基于这个对应关系进行binder通讯
// BpRefBase::BpRefBase(const sp<IBinder>& o)
// : mRemote(o.get()), mRefs(NULL), mState(0)
// {
// extendObjectLifetime(OBJECT_LIFETIME_WEAK);
// if (mRemote) {
// mRemote->incStrong(this); // Removed on first IncStrong().
// mRefs =mRemote->createWeak(this); // Held for our entire lifetime.
// }
//}
}
这里remote()函数返回的是mRemote成员变量,它指向一个BpBinder对象。
因此remote()->transact()实际上调用的是BpBinder::transact()
6. frameworks/native/libs/binder/BpBinder.cpp
6.1 BpBinder::transact
status_tBpBinder::transact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will nevercome 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;
}
7. frameworks/native/libs/binder/IPCThreadState.cpp
7.1 IPCThreadState::transact
写数据到binderdriver中
status_tIPCThreadState::transact(int32_t handle,
uint32_tcode, const Parcel& data,
Parcel*reply, uint32_t flags)
{
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_TRANSACTION thr" << (void*)pthread_self() << " / hand "
<< handle << " /code " << TypeCode(code) << ": "
<< indent << data<< dedent << endl;
}
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SENDfrom pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ?"READ REPLY" : "ONE WAY");
err =writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>>CALLING transaction %d", code);
}
#endif
if (reply) {
err =waitForResponse(reply);
} else {
Parcel fakeReply;
err =waitForResponse(&fakeReply);
}
#if 0
if (code == 4) { // relayout
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction %d",code);
}
#endif
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_REPLY thr" << (void*)pthread_self() << " / hand "
<< handle <<": ";
if (reply) alog << indent<< *reply << dedent << endl;
else alog << "(nonerequested)" << endl;
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
7.2 IPCThreadState::writeTransactionData
status_tIPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel&data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.handle =handle; // handle 标识目的端,其中0标识ServiceManager
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size =data.ipcObjectsCount()*sizeof(size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = statusBuffer;
tr.offsets_size = 0;
tr.data.ptr.offsets = NULL;
} else {
return (mLastError = err);
}
// mIn, mOut是连个Parcel对象,发送和接收命令缓冲区。
// 每个IPCThreadState都有一个mIn, mOut;mIn是用来接收从binder设备
//来的数据,而mOut是用来存储发往binder设备的数据。
//写命令到缓冲区
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
7.3 IPCThreadState:: waitForResponse
发送请求与接收响应
status_tIPCThreadState::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 << "ProcessingwaitForResponse 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:
{
ALOG_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));
ALOG_ASSERT(err == NO_ERROR,"Not enough command data for brREPLY");
if (err != NO_ERROR) gotofinish;
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<constsize_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<constuint8_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;
}
7.4 IPCThreadState:: talkWithDriver
IPCThreadState:: talkWithDriver
status_tIPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition()>= mIn.dataSize();
// We don't want to write anything if weare still reading
// from data left in the input buffer andthe 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 unsignedint)mOut.data();
// This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsignedint)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
if (outAvail != 0) {
alog << "Sendingcommands to driver: " << indent;
const void* cmds = (constvoid*)bwr.write_buffer;
const void* end = ((constuint8_t*)cmds)+bwr.write_size;
alog << HexDump(cmds,bwr.write_size) << endl;
while (cmds < end) cmds =printCommand(alog, cmds);
alog << dedent;
}
alog << "Size of receivebuffer: " << bwr.read_size
<< ", needRead: "<< needRead << ", doReceive: " << doReceive<< endl;
}
// Return immediately if there is nothingto 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_LOG_COMMANDS() {
alog << "About toread/write, write size = " << mOut.dataSize() << endl;
}
#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
if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
IF_LOG_COMMANDS() {
alog << "Finishedread/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
IF_LOG_COMMANDS() {
alog << "Our err: "<< (void*)err << ", write consumed: "
<< bwr.write_consumed<< " (of " << mOut.dataSize()
<< "),read consumed: " << bwr.read_consumed << endl;
}
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);
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
alog << "Remaining datasize: " << mOut.dataSize() << endl;
alog << "Receivedcommands from driver: " << indent;
const void* cmds = mIn.data();
const void* end = mIn.data() +mIn.dataSize();
alog << HexDump(cmds,mIn.dataSize()) << endl;
while (cmds < end) cmds =printReturnCommand(alog, cmds);
alog << dedent;
}
return NO_ERROR;
}
return err;
}
7.5 IPCThreadState:: executeCommand
现在假设请求后得到回复响应
status_tIPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
case BR_OK:
break;
case BR_ACQUIRE:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
ALOG_ASSERT(refs->refBase() == obj,
"BR_ACQUIRE: object %pdoes not match cookie %p (expected %p)",
refs, obj,refs->refBase());
obj->incStrong(mProcess.get());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_ACQUIREfrom driver on %p", obj);
obj->printRefs();
}
mOut.writeInt32(BC_ACQUIRE_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_RELEASE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
ALOG_ASSERT(refs->refBase() == obj,
"BR_RELEASE: object %pdoes not match cookie %p (expected %p)",
refs, obj,refs->refBase());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_RELEASEfrom driver on %p", obj);
obj->printRefs();
}
mPendingStrongDerefs.push(obj);
break;
case BR_INCREFS:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
refs->incWeak(mProcess.get());
mOut.writeInt32(BC_INCREFS_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_DECREFS:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
// NOTE: This assertion is not valid,because the object may no
// longer exist (thus the(BBinder*)cast above resulting in a different
// memory address).
//ALOG_ASSERT(refs->refBase() ==obj,
// "BR_DECREFS: object %p does notmatch cookie %p (expected %p)",
// refs, obj, refs->refBase());
mPendingWeakDerefs.push(refs);
break;
case BR_ATTEMPT_ACQUIRE:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
{
const bool success =refs->attemptIncStrong(mProcess.get());
ALOG_ASSERT(success &&refs->refBase() == obj,
"BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected%p)",
refs, obj,refs->refBase());
mOut.writeInt32(BC_ACQUIRE_RESULT);
mOut.writeInt32((int32_t)success);
}
break;
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr,sizeof(tr));
ALOG_ASSERT(result == NO_ERROR,
"Not enough command datafor brTRANSACTION");
if (result != NO_ERROR) break;
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<constsize_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t),freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
int curPrio =getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio >ANDROID_PRIORITY_NORMAL) {
// We have inherited areduced priority from the caller, but do not
// want to run in thatstate in this process. The driver setour
// priority already (thoughnot our scheduling class), so bounce
// it back to the defaultbefore invoking the transaction.
setpriority(PRIO_PROCESS,mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND){
// We want to use theinherited priority from the caller.
// Ensure this thread is inthe background scheduling class,
// since the driver won'tmodify scheduling classes for us.
// The scheduling group isreset to default by the caller
// once this method returnsafter the transaction is complete.
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
//ALOGI(">>>>TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
Parcel reply;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_TRANSACTIONthr " << (void*)pthread_self()
<< " / obj" << tr.target.ptr << " / code "
<< TypeCode(tr.code)<< ": " << indent << buffer
<< dedent <<endl
<< "Data addr ="
<< reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer)
<< ", offsetsaddr="
<<reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
// registered CameraService object, CameraServiceinherit from BBinder
sp<BBinder> b((BBinder*)tr.cookie);
conststatus_t error = b->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR)reply.setError(error);
} else {
const status_t error =the_context_object->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR)reply.setError(error);
}
//ALOGI("<<<<TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);
if ((tr.flags & TF_ONE_WAY) ==0) {
LOG_ONEWAY("Sending replyto %d!", mCallingPid);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sendingreply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_REPLY thr" << (void*)pthread_self() << " / obj "
<< tr.target.ptr<< ": " << indent << reply << dedent <<endl;
}
}
break;
case BR_DEAD_BINDER:
{
BpBinder *proxy =(BpBinder*)mIn.readInt32();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writeInt32((int32_t)proxy);
} break;
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
{
BpBinder *proxy =(BpBinder*)mIn.readInt32();
proxy->getWeakRefs()->decWeak(proxy);
} break;
case BR_FINISHED:
result = TIMED_OUT;
break;
case BR_NOOP:
break;
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
default:
printf("*** BAD COMMAND %dreceived from Binder driver\n", cmd);
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}