Binder学习笔记
main_mediaserver.cpp ------------------------------------------------------------------------- int main(int argc, char** argv) { #ifdef SWP1_AVMS setpriority(PRIO_PROCESS, getpid(), ANDROID_PRIORITY_URGENT_DISPLAY); #endif sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); LOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate(); MediaPlayerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
首先看ProcessState::self(),采用singleton模式,每个进程只有一个process state对象。
ProcessState.cpp singleton pattern ------------------------------------------------------- sp<ProcessState> ProcessState::self() { if (gProcess != NULL) return gProcess;-------------------------------singleton模式 AutoMutex _l(gProcessMutex); if (gProcess == NULL) gProcess = new ProcessState; return gProcess; }ProcessState构造函数。打开/dev/binder设备,并mmap该设备到虚拟地址空间
ProcessState::ProcessState() : mDriverFD(open_driver()) , mVMStart(MAP_FAILED) , mManagesContexts(false) , mBinderContextCheckFunc(NULL) , mBinderContextUserData(NULL) , mThreadPoolStarted(false) , mThreadPoolSeq(1) { ...... if (mDriverFD >= 0) { // XXX Ideally, there should be a specific define for whether we // have mmap (or whether we could possibly have the kernel module // availabla). // mmap the binder, providing a chunk of virtual address space to receive transactions. mVMStart = mmap(0, binder_vm_size, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) { // *sigh* LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n"); close(mDriverFD); mDriverFD = -1; } } ...... }open_driver()打开/dev/binder设备。
static int open_driver() { if (gSingleProcess) { return -1; } int fd = open("/dev/binder", O_RDWR);---------------------------------------------打开/dev/binder设备 if (fd >= 0) { fcntl(fd, F_SETFD, FD_CLOEXEC);-----------------------------------------------FD_CLOEXEC表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程, 如果设置为fcntl(fd, F_SETFD, 0);那么本fd将保持打开状态复制到exec创建的新进程中 int vers; status_t result = ioctl(fd, BINDER_VERSION, &vers);---------------------------获取binder版本 ...... #if defined(HAVE_ANDROID_OS) size_t maxThreads = 15; result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);----------------------设置最大binder thread数量,15个 ...... #endif } ...... return fd; }分析defaultServiceManager(),singleton模式
sp<IServiceManager> defaultServiceManager() { if (gDefaultServiceManager != NULL) return gDefaultServiceManager; { AutoMutex _l(gDefaultServiceManagerLock); if (gDefaultServiceManager == NULL) { gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL));----------------gProcess->getContextObject(); } } return gDefaultServiceManager; }getContextObject()
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) { if (supportsProcesses())====== if (mDriverFD >= 0) { return getStrongProxyForHandle(0); } else { return getContextObject(String16("default"), caller); } }getStrongProxyForHandle()
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { // We need to create a new BpBinder if there isn't currently one, OR we // are unable to acquire a weak reference on this current one. See comment // in getWeakProxyForHandle() for more info about this. IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpBinder(handle);-----------------------------------------------------构造一个BpBinder,handler=0 e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { // This little bit of nastyness is to allow us to add a primary // reference to the remote proxy when this team doesn't have one // but another team is sending the handle to us. result.force_set(b); e->refs->decWeak(this); } } return result; }
BpBinder(handler)
BpBinder::BpBinder(int32_t handle) : mHandle(handle)---------------------------------------------handle = 0 , mAlive(1) , mObitsSent(0) , mObituaries(NULL) { extendObjectLifetime(OBJECT_LIFETIME_WEAK); IPCThreadState::self()->incWeakHandle(handle); }interface_cast
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }IServiceManager.h
class IServiceManager : public IInterface { public: DECLARE_META_INTERFACE(ServiceManager); virtual sp<IBinder> getService( const String16& name) const = 0; virtual sp<IBinder> checkService( const String16& name) const = 0; virtual status_t addService( const String16& name, const sp<IBinder>& service) = 0; virtual Vector<String16> listServices() = 0; enum { GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, CHECK_SERVICE_TRANSACTION, ADD_SERVICE_TRANSACTION, LIST_SERVICES_TRANSACTION, }; };DECLARE_META_INTERFACE(ServiceManager)
#define DECLARE_META_INTERFACE(ServiceManager) \ static const android::String16 descriptor; \ static android::sp<IServiceManager> asInterface( \ const android::sp<android::IBinder>& obj); \ virtual const android::String16& getInterfaceDescriptor() const; \ IServiceManager(); \ virtual ~IServiceManager(); \IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
#define IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager") \ const android::String16 IServiceManager::descriptor("android.os.IServiceManager"); \ const android::String16& \ IServiceManager::getInterfaceDescriptor() const { \ return IServiceManager::descriptor; \ } \ android::sp<IServiceManager> IServiceManager::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<IServiceManager> intr; \ if (obj != NULL) { \ intr = static_cast<IServiceManager*>( \ obj->queryLocalInterface( \ IServiceManager::descriptor).get()); \ if (intr == NULL) { \ intr = new BpServiceManager(obj); \obj = BpBinder(0) } \ } \ return intr; \ } \ IServiceManager::IServiceManager() { } \ IServiceManager::~IServiceManager() { } \ #define CHECK_INTERFACE(interface, data, reply) \ if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \BpServiceManager
BpServiceManager(const sp<IBinder>& impl) : BpInterface<IServiceManager>(impl)-------------------------------BpBinder(0) {}BpInterface
class BpInterface : public IServiceManager, public BpRefBase { public: BpInterface(const sp<IBinder>& remote); protected: virtual IBinder* onAsBinder(); };BpRefBase
BpRefBase::BpRefBase(const sp<IBinder>& o)--------------------------------BpBinder(0) : mRemote(o.get()), mRefs(NULL), mState(0) { extendObjectLifetime(OBJECT_LIFETIME_WEAK); if (mRemote) {--------------------------------------------------------mRemote == BpBinder(0) mRemote->incStrong(this); // Removed on first IncStrong(). mRefs = mRemote->createWeak(this); // Held for our entire lifetime. } }AudioFlinger
AudioFlinger::AudioFlinger() : BnAudioFlinger(), mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1), mBtNrecIsOff(false) {}addService()
virtual status_t addService(const String16& name, const sp<IBinder>& service) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);------------remote() == BpBinder(0) return err == NO_ERROR ? reply.readExceptionCode() : err; }AudioFlinger()AudioFlinger::AudioFlinger(): BnAudioFlinger(), mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1), mBtNrecIsOff(false) {}class BnAudioFlinger : public BnInterface<IAudioFlinger>
template<typename IAudioFlinger> class BnInterface : public IAudioFlinger, public BBinder { public: virtual sp<IInterface> queryLocalInterface(const String16& _descriptor); virtual const String16& getInterfaceDescriptor() const; protected: virtual IBinder* onAsBinder(); };DECLARE_META_INTERFACE(AudioFlinger);
#define DECLARE_META_INTERFACE(AudioFlinger) \ static const android::String16 descriptor; \ static android::sp<IAudioFlinger> asInterface( \ const android::sp<android::IBinder>& obj); \ virtual const android::String16& getInterfaceDescriptor() const; \ IAudioFlinger(); \ virtual ~IAudioFlinger();IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
#define IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger") \ const android::String16 IAudioFlinger::descriptor("android.media.IAudioFlinger"); \ const android::String16& \ IAudioFlinger::getInterfaceDescriptor() const { \ return IAudioFlinger::descriptor; \ } \ android::sp<IAudioFlinger> IAudioFlinger::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<IAudioFlinger> intr; \ if (obj != NULL) { \ intr = static_cast<IAudioFlinger*>( \ obj->queryLocalInterface( \ IAudioFlinger::descriptor).get()); \ if (intr == NULL) { \ intr = new BpAudioFlinger(obj); \ } \ } \ return intr; \ } \ IAudioFlinger::IAudioFlinger() { } \ IAudioFlinger::~IAudioFlinger() { } \BpBinder::transact()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; }IPCThreadStateIPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mMyThreadId(androidGetTid()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { pthread_setspecific(gTLS, this);---------------------设置Thread-specific Data,或TSD clearCaller(); mIn.setDataCapacity(256);----------------------------接收来自Binder设备的数据 mOut.setDataCapacity(256);---------------------------存储发往Binder设备的数据 }
IPCThreadState::self()
IPCThreadState* IPCThreadState::self() { if (gHaveTLS) { restart: const pthread_key_t k = gTLS; IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);-------------读取Thread-specific Data,或TSD if (st) return st; return new IPCThreadState; } if (gShutdown) return NULL; pthread_mutex_lock(&gTLSMutex); if (!gHaveTLS) { if (pthread_key_create(&gTLS, threadDestructor) != 0) {--------------------建立TSD的key,设置相应的destructor pthread_mutex_unlock(&gTLSMutex); return NULL; } gHaveTLS = true; } pthread_mutex_unlock(&gTLSMutex); goto restart; }
IPCThreadState::transact()
status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err = data.errorCheck(); flags |= TF_ACCEPT_FDS; if (err == NO_ERROR) { LOG_ONEWAY(">>>> SEND from 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);-----------BC_XX应用程序向binder设备发送消息的消息码,binder设备回复消息码为BR_XX } if (err != NO_ERROR) { if (reply) reply->setError(err); return (mLastError = err); } if ((flags & TF_ONE_WAY) == 0) { if (reply) { err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } } else { err = waitForResponse(NULL, NULL); } return err; }IPCThreadState::writeTransactionData()
status_t IPCThreadState::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; 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); } mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr)); return NO_ERROR; }IPCThreadState::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(bool doReceive)
status_t IPCThreadState::talkWithDriver(bool doReceive) { 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; bwr.read_buffer = 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 (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else err = -errno; } 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; }IPCThreadState::executeCommand(int32_t cmd)
status_t IPCThreadState::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(); obj->incStrong(mProcess.get());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(); 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). 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()); mOut.writeInt32(BC_ACQUIRE_RESULT); mOut.writeInt32((int32_t)success); } break; case BR_TRANSACTION: { binder_transaction_data tr; result = mIn.read(&tr, sizeof(tr));if (result != NO_ERROR) break; Parcel buffer; buffer.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); 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 a reduced priority from the caller, but do not // want to run in that state in this process. The driver set our // priority already (though not our scheduling class), so bounce // it back to the default before invoking the transaction. setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL); } } else { if (curPrio >= ANDROID_PRIORITY_BACKGROUND) { // We want to use the inherited priority from the caller. // Ensure this thread is in the background scheduling class, // since the driver won't modify scheduling classes for us. // The scheduling group is reset to default by the caller // once this method returns after the transaction is complete. androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_BG_NONINTERACT); } } Parcel reply; if (tr.target.ptr) { sp<BBinder> b((BBinder*)tr.cookie); const status_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); } if ((tr.flags & TF_ONE_WAY) == 0) { sendReply(reply, 0); } else { LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); } mCallingPid = origPid; mCallingUid = origUid; } 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 %d received from Binder driver\n", cmd); result = UNKNOWN_ERROR; break; } if (result != NO_ERROR) { mLastError = result; } return result; }BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
status_t BBinder::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); break; } if (reply != NULL) { reply->setDataPosition(0); } return err; }BnAudioFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
status_t BnAudioFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case CREATE_TRACK: { CHECK_INTERFACE(IAudioFlinger, data, reply); pid_t pid = data.readInt32(); int streamType = data.readInt32(); uint32_t sampleRate = data.readInt32(); int format = data.readInt32(); int channelCount = data.readInt32(); size_t bufferCount = data.readInt32(); uint32_t flags = data.readInt32(); sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder()); int output = data.readInt32(); int sessionId = data.readInt32(); status_t status; sp<IAudioTrack> track = createTrack(pid, streamType, sampleRate, format, channelCount, bufferCount, flags, buffer, output, &sessionId, &status); reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(track->asBinder()); return NO_ERROR; } break; case OPEN_RECORD: { CHECK_INTERFACE(IAudioFlinger, data, reply); pid_t pid = data.readInt32(); int input = data.readInt32(); uint32_t sampleRate = data.readInt32(); int format = data.readInt32(); int channelCount = data.readInt32(); size_t bufferCount = data.readInt32(); uint32_t flags = data.readInt32(); int sessionId = data.readInt32(); status_t status; sp<IAudioRecord> record = openRecord(pid, input, sampleRate, format, channelCount, bufferCount, flags, &sessionId, &status); reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(record->asBinder()); return NO_ERROR; } break; case SAMPLE_RATE: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( sampleRate(data.readInt32()) ); return NO_ERROR; } break; case CHANNEL_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( channelCount(data.readInt32()) ); return NO_ERROR; } break; case FORMAT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( format(data.readInt32()) ); return NO_ERROR; } break; case FRAME_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( frameCount(data.readInt32()) ); return NO_ERROR; } break; case LATENCY: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( latency(data.readInt32()) ); return NO_ERROR; } break; case SET_MASTER_VOLUME: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( setMasterVolume(data.readFloat()) ); return NO_ERROR; } break; case SET_MASTER_MUTE: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( setMasterMute(data.readInt32()) ); return NO_ERROR; } break; case MASTER_VOLUME: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeFloat( masterVolume() ); return NO_ERROR; } break; case MASTER_MUTE: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( masterMute() ); return NO_ERROR; } break; case SET_STREAM_VOLUME: { CHECK_INTERFACE(IAudioFlinger, data, reply); int stream = data.readInt32(); float volume = data.readFloat(); int output = data.readInt32(); reply->writeInt32( setStreamVolume(stream, volume, output) ); return NO_ERROR; } break; case SET_STREAM_MUTE: { CHECK_INTERFACE(IAudioFlinger, data, reply); int stream = data.readInt32(); reply->writeInt32( setStreamMute(stream, data.readInt32()) ); return NO_ERROR; } break; case STREAM_VOLUME: { CHECK_INTERFACE(IAudioFlinger, data, reply); int stream = data.readInt32(); int output = data.readInt32(); reply->writeFloat( streamVolume(stream, output) ); return NO_ERROR; } break; case STREAM_MUTE: { CHECK_INTERFACE(IAudioFlinger, data, reply); int stream = data.readInt32(); reply->writeInt32( streamMute(stream) ); return NO_ERROR; } break; case SET_MODE: { CHECK_INTERFACE(IAudioFlinger, data, reply); int mode = data.readInt32(); reply->writeInt32( setMode(mode) ); return NO_ERROR; } break; case SET_MIC_MUTE: { CHECK_INTERFACE(IAudioFlinger, data, reply); int state = data.readInt32(); reply->writeInt32( setMicMute(state) ); return NO_ERROR; } break; case GET_MIC_MUTE: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( getMicMute() ); return NO_ERROR; } break; case SET_PARAMETERS: { CHECK_INTERFACE(IAudioFlinger, data, reply); int ioHandle = data.readInt32(); String8 keyValuePairs(data.readString8()); reply->writeInt32(setParameters(ioHandle, keyValuePairs)); return NO_ERROR; } break; case GET_PARAMETERS: { CHECK_INTERFACE(IAudioFlinger, data, reply); int ioHandle = data.readInt32(); String8 keys(data.readString8()); reply->writeString8(getParameters(ioHandle, keys)); return NO_ERROR; } break; case REGISTER_CLIENT: { CHECK_INTERFACE(IAudioFlinger, data, reply); sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder()); registerClient(client); return NO_ERROR; } break; case GET_INPUTBUFFERSIZE: { CHECK_INTERFACE(IAudioFlinger, data, reply); uint32_t sampleRate = data.readInt32(); int format = data.readInt32(); int channelCount = data.readInt32(); reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) ); return NO_ERROR; } break; case OPEN_OUTPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); uint32_t devices = data.readInt32(); uint32_t samplingRate = data.readInt32(); uint32_t format = data.readInt32(); uint32_t channels = data.readInt32(); uint32_t latency = data.readInt32(); uint32_t flags = data.readInt32(); int output = openOutput(&devices, &samplingRate, &format, &channels, &latency, flags); LOGV("OPEN_OUTPUT output, %p", output); reply->writeInt32(output); reply->writeInt32(devices); reply->writeInt32(samplingRate); reply->writeInt32(format); reply->writeInt32(channels); reply->writeInt32(latency); return NO_ERROR; } break; case OPEN_DUPLICATE_OUTPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); int output1 = data.readInt32(); int output2 = data.readInt32(); reply->writeInt32(openDuplicateOutput(output1, output2)); return NO_ERROR; } break; case CLOSE_OUTPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32(closeOutput(data.readInt32())); return NO_ERROR; } break; case SUSPEND_OUTPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32(suspendOutput(data.readInt32())); return NO_ERROR; } break; case RESTORE_OUTPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32(restoreOutput(data.readInt32())); return NO_ERROR; } break; case OPEN_INPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); uint32_t devices = data.readInt32(); uint32_t samplingRate = data.readInt32(); uint32_t format = data.readInt32(); uint32_t channels = data.readInt32(); uint32_t acoutics = data.readInt32(); int input = openInput(&devices, &samplingRate, &format, &channels, acoutics); reply->writeInt32(input); reply->writeInt32(devices); reply->writeInt32(samplingRate); reply->writeInt32(format); reply->writeInt32(channels); return NO_ERROR; } break; case CLOSE_INPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32(closeInput(data.readInt32())); return NO_ERROR; } break; case SET_STREAM_OUTPUT: { CHECK_INTERFACE(IAudioFlinger, data, reply); uint32_t stream = data.readInt32(); int output = data.readInt32(); reply->writeInt32(setStreamOutput(stream, output)); return NO_ERROR; } break; case SET_VOICE_VOLUME: { CHECK_INTERFACE(IAudioFlinger, data, reply); float volume = data.readFloat(); reply->writeInt32( setVoiceVolume(volume) ); return NO_ERROR; } break; case GET_RENDER_POSITION: { CHECK_INTERFACE(IAudioFlinger, data, reply); int output = data.readInt32(); uint32_t halFrames; uint32_t dspFrames; status_t status = getRenderPosition(&halFrames, &dspFrames, output); reply->writeInt32(status); if (status == NO_ERROR) { reply->writeInt32(halFrames); reply->writeInt32(dspFrames); } return NO_ERROR; } case GET_INPUT_FRAMES_LOST: { CHECK_INTERFACE(IAudioFlinger, data, reply); int ioHandle = data.readInt32(); reply->writeInt32(getInputFramesLost(ioHandle)); return NO_ERROR; } break; case NEW_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32(newAudioSessionId()); return NO_ERROR; } break; case ACQUIRE_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); int audioSession = data.readInt32(); acquireAudioSessionId(audioSession); return NO_ERROR; } break; case RELEASE_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); int audioSession = data.readInt32(); releaseAudioSessionId(audioSession); return NO_ERROR; } break; case QUERY_NUM_EFFECTS: { CHECK_INTERFACE(IAudioFlinger, data, reply); uint32_t numEffects; status_t status = queryNumberEffects(&numEffects); reply->writeInt32(status); if (status == NO_ERROR) { reply->writeInt32((int32_t)numEffects); } return NO_ERROR; } case QUERY_EFFECT: { CHECK_INTERFACE(IAudioFlinger, data, reply); effect_descriptor_t desc; status_t status = queryEffect(data.readInt32(), &desc); reply->writeInt32(status); if (status == NO_ERROR) { reply->write(&desc, sizeof(effect_descriptor_t)); } return NO_ERROR; } case GET_EFFECT_DESCRIPTOR: { CHECK_INTERFACE(IAudioFlinger, data, reply); effect_uuid_t uuid; data.read(&uuid, sizeof(effect_uuid_t)); effect_descriptor_t desc; status_t status = getEffectDescriptor(&uuid, &desc); reply->writeInt32(status); if (status == NO_ERROR) { reply->write(&desc, sizeof(effect_descriptor_t)); } return NO_ERROR; } case CREATE_EFFECT: { CHECK_INTERFACE(IAudioFlinger, data, reply); pid_t pid = data.readInt32(); effect_descriptor_t desc; data.read(&desc, sizeof(effect_descriptor_t)); sp<IEffectClient> client = interface_cast<IEffectClient>(data.readStrongBinder()); int32_t priority = data.readInt32(); int output = data.readInt32(); int sessionId = data.readInt32(); status_t status; int id; int enabled; sp<IEffect> effect = createEffect(pid, &desc, client, priority, output, sessionId, &status, &id, &enabled); reply->writeInt32(status); reply->writeInt32(id); reply->writeInt32(enabled); reply->writeStrongBinder(effect->asBinder()); reply->write(&desc, sizeof(effect_descriptor_t)); return NO_ERROR; } break; case MOVE_EFFECTS: { CHECK_INTERFACE(IAudioFlinger, data, reply); int session = data.readInt32(); int srcOutput = data.readInt32(); int dstOutput = data.readInt32(); reply->writeInt32(moveEffects(session, srcOutput, dstOutput)); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }status_t AudioFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
status_t AudioFlinger::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { return BnAudioFlinger::onTransact(code, data, reply, flags); }ProcessState::startThreadPool()
void ProcessState::startThreadPool() { AutoMutex _l(mLock); if (!mThreadPoolStarted) { mThreadPoolStarted = true; spawnPooledThread(true); } }ProcessState::spawnPooledThread(bool isMain)
void ProcessState::spawnPooledThread(bool isMain) { if (mThreadPoolStarted) { int32_t s = android_atomic_add(1, &mThreadPoolSeq); char buf[32]; sprintf(buf, "Binder Thread #%d", s); LOGV("Spawning new pooled thread, name=%s\n", buf); sp<Thread> t = new PoolThread(isMain); t->run(buf); } }class PoolThread : public Threadclass PoolThread : public Thread { public: PoolThread(bool isMain) : mIsMain(isMain) { } protected: virtual bool threadLoop() { IPCThreadState::self()->joinThreadPool(mIsMain); return false; } const bool mIsMain; };IPCThreadState::joinThreadPool(bool isMain)void IPCThreadState::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 a thread that was in the background // scheduling group, so first we will make sure it is in the default/foreground // one to avoid performing an initial transaction in the background. androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT); status_t result; do { int32_t cmd; // When we've cleared the incoming command 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 be processed, 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 << "Processing top-level Command: " << getReturnString(cmd) << endl; } result = executeCommand(cmd); } // After executing the command, ensure that the thread is returned to the // default cgroup before rejoining the pool. The driver takes care of // restoring the priority, but doesn't do anything with cgroups so we // need to take care of that here in userspace. Note that we do make // sure to go in the foreground after executing a transaction, but // there are other callbacks into user code that could have changed // our group so we want to make absolutely sure it is put back. androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT); // Let this thread exit the thread pool if it is no longer // needed and it is not the main process 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); }以上是Binder在C++层的处理流程,从BpBinder到BnBinder,消息从IXXService的remote()->transact(code)------>BpBinder::transact(code)------>IPCThreadState::self()->transact(code)------>IPCThreadState::writeTransactionData(code,...)------>IPCThreadState::waitForResponse(Parcel *reply,......)------>IPCThreadState::executeCommand(int32_t code)------>不断地调用talkWithDriver(),获取/dev/binder设备返回的值------>BBinder::transact()------>BBinder::onTransact()------>XXService::onTransact()