深入了解MediaServer-1
来源:互联网 发布:php高级工程师是什么 编辑:程序博客网 时间:2024/06/05 11:10
http://blog.csdn.net/myarrow/article/details/7048488
1.mediaserver位于main_mediaserver.cpp,其源码如下:
- int main(int argc, char** argv)
- {
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
- LOGI("ServiceManager: %p", sm.get());
- AudioFlinger::instantiate(); //音频系统的mixer and resampler
- MediaPlayerService::instantiate(); //创建一个player,并进行AV播放
- CameraService::instantiate(); // 摄像和照相的服务
- AudioPolicyService::instantiate(); //音频策略的服务
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- }
此程序的进程名为:/system/bin/mediaserver
- void AudioFlinger::instantiate() {
- defaultServiceManager()->addService(
- String16("media.audio_flinger"), new AudioFlinger());
- }
- void MediaPlayerService::instantiate() {
- defaultServiceManager()->addService(
- String16("media.player"), new MediaPlayerService());
- }
- void CameraService::instantiate() {
- defaultServiceManager()->addService(
- String16("media.camera"), new CameraService());
- }
- void AudioPolicyService::instantiate() {
- defaultServiceManager()->addService(
- String16("media.audio_policy"), new AudioPolicyService());
- }
查看系统已经注册的media类Service,其结果如下:
# service list | busybox grep media
5 audio: [android.media.IAudioService]
63 media.audio_policy: [android.media.IAudioPolicyService]
64 media.camera: [android.hardware.ICameraService]
65 media.player: [android.media.IMediaPlayerService]
66 media.audio_flinger: [android.media.IAudioFlinger]
2. 独一无二的ProcessState
ProcessState是一个单实例,每个进程只有一个实例。ProcessState::self()功能为打开/dev/binder设备,设置线程池中最大线程数,通过mmap把Binder Driver为其分配的内在映射到用户空间,以便把发送方的数据从发送方的用户空间直接copy到接收方的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).
- #if !defined(HAVE_WIN32_IPC)
- // 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;
- }
- #else
- mDriverFD = -1;
- #endif
- }
- if (mDriverFD < 0) {
- // Need to run without the driver, starting our own thread pool.
- }
- }
3. 神奇的 defaultServiceManager
defaultServiceManager在IServiceManager.cpp中实现,其功能是获得一个IServiceManager对象。通过这个对象,就可以与进程/system/bin/servicemanager进行通信。
(defaultServiceManager实际返回的是BpServiceManager,它的remote对象是BpBinder,传入的那个handle参数是0。)
- sp<IServiceManager> defaultServiceManager()
- {
- if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
- {
- AutoMutex _l(gDefaultServiceManagerLock);
- if (gDefaultServiceManager == NULL) {
- gDefaultServiceManager = <span style="color: rgb(255, 0, 0);">interface_cast</span><IServiceManager>(
- ProcessState::self()->getContextObject(NULL));
- }
- }
- return gDefaultServiceManager;
- }
ProcessState::self()->getContextObject(NULL)-> getStrongProxyForHandle(0)-> new BpBinder(handle) // handle值为0, 0在binder系统中代表ServiceManger所对应的BBinder.
即:gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0))
它创建了两个关键对象:
1)BpBinder对象,其handle为0
2)BpServiceManager对象,其mRemote值为1)中创建的BpBinder对象。
BpServiceManager实现了IServiceManager中定义的业务逻辑,又有一个成员BpBinder作为其通信代理。
3.1 如何把BpBinder转换为IServiceManager呢?
- template<typename INTERFACE>
- inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
- {
- return INTERFACE::asInterface(obj);
- }
- 即:
- inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
- {
- <span style="color: rgb(51, 51, 255);">return IServiceManager::asInterface(obj);
- </span>}
3.2 ServiceManager所提供的服务
- //IServiceManager.h
- class IServiceManager : public IInterface
- {
- public:
- <span style="color: rgb(51, 51, 255);">DECLARE_META_INTERFACE(ServiceManager);
- </span>
- /**
- * Retrieve an existing service, blocking for a few seconds
- * if it doesn't yet exist.
- */
- virtual sp<IBinder> getService( const String16& name) const = 0;
- /**
- * Retrieve an existing service, non-blocking.
- */
- virtual sp<IBinder> checkService( const String16& name) const = 0;
- /**
- * Register a service.
- */
- virtual status_t addService( const String16& name,
- const sp<IBinder>& service) = 0;
- /**
- * Return list of all existing services.
- */
- virtual Vector<String16> listServices() = 0;
- enum {
- GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
- CHECK_SERVICE_TRANSACTION,
- ADD_SERVICE_TRANSACTION,
- LIST_SERVICES_TRANSACTION,
- };
- }
3.3 如何把业务与Binder通信连接起来
- //IInterface.h
- #define DECLARE_META_INTERFACE(INTERFACE) \
- static const String16 descriptor; \
- static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj); \
- virtual const String16& getInterfaceDescriptor() const; \
- I##INTERFACE(); \
- virtual ~I##INTERFACE(); \
替换后得到:
- static const String16 descriptor;
- static sp<IServiceManager> <span style="color: rgb(51, 51, 255);">asInterface</span>(const sp<IBinder>& obj);
- virtual const String16& getInterfaceDescriptor() const;
- IServiceManager();
- virtual ~IServiceManager();
asInterface是如何实现的?
- // IServiceManager.cpp
- IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
- //IInterface.h
- #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
- const String16 I##INTERFACE::descriptor(NAME); \
- const String16& I##INTERFACE::getInterfaceDescriptor() const { \
- return I##INTERFACE::descriptor; \
- } \
- sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj) \
- { \
- 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() { } \
替换后为:
- const String16 IServiceManager::descriptor("android.os.IServiceManager");
- const String16& IServiceManagerE::getInterfaceDescriptor() const {
- return IServiceManager::descriptor;
- }
- sp<IServiceManager> IServiceManager::<span style="color: rgb(255, 0, 0);">asInterface</span>(const sp<IBinder>& obj)
- {
- sp<IServiceManager> intr;
- if (obj != NULL) {
- intr = static_cast<IServiceManager*>(
- obj->queryLocalInterface(
- IServiceManager::descriptor).get());
- if (intr == NULL) {
- <span style="color: rgb(51, 51, 255);">intr = new BpServiceManager(obj);</span>
- }
- }
- return intr;
- }
- IServiceManager::IServiceManager() { }
- IServiceManager::~IServiceManager() { }
如何把BpBinder转换为IServiceManager的答案为:intr = new BpServiceManager(obj);
其原理为:interface_cast并不是一个指针转换,而是把BpBinder做为一个参数,创建了一个新的BpServiceManager.
3.3.1 IServiceManager家族图谱
转自:http://book.51cto.com/art/201109/293428.htm
1)IServiceManager,BpServiceManager和BnServiceManager都与业务逻辑相关。
2)class BnServiceManager : public BnInterface<IServiceManager>
BnServiceManager同时从IServiceManager和BBinder派生,表示它可以直接参与Binder通信。
3)class BpServiceManager : public BpInterface<IServiceManager>
BpServiceManager同时从IServiceManager和BpRefBase派生。
BpRefBase中有一个成员变量:IBinder* const mRemote;
注:以上关系较复杂,但ServiceManger并没有使用以上派生关系,而是直接打开Binder设备并与之交互。
4)BpRefBase的成员变量mRemote的值就是传进去的BpBinder,使用它就可以与BBinder进行通信了。
5)intr = new BpServiceManager(obj);详细过程如下:
- BpServiceManager(const sp<IBinder>& impl)
- : BpInterface<IServiceManager>(impl)
- {
- }
- template<typename INTERFACE>
- inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
- : BpRefBase(remote)
- {
- }
- BpRefBase::BpRefBase(const sp<IBinder>& o)
- : <span style="color: rgb(255, 0, 0);">mRemote(o.get()), </span>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.
- }
- }
o.get(),这个是sp类的获取实际数据指针的一个方法,它返回的是sp<xxxx>中xxx* 类型的指针。
3.4 ProcessState & IPCThreadState
ProcessState负责打开BinderDriver,准备好与Binder Driver通信;而IPCThreadState负责通过Binder Driver而进行跨进程的实际数据的读写。例如,client进程的程序调用BpBinder的IBinder中的transact()函数,此transact()函数则调用IPCThreadState中的transact()函数调用Binder Driver的ioctl()函数进行数据的传输。
IPCThreadState::transact->IPCThreadState::waitForResponse-> IPCThreadState::talkWithDriver->ioctl
- 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;
- }
4. 注册一个Service
以MediaPlayerService为例分析注册过程。
- void MediaPlayerService::instantiate() {
- defaultServiceManager()->addService(
- String16("media.player"), new MediaPlayerService());
- }
- MediaPlayerService::MediaPlayerService()
- {
- LOGV("MediaPlayerService created");
- mNextConnId = 1;
- mRatio = -1;
- mCrvs = -1;
- mLeft = -1;
- mTop =-1;
- mWidth =-1;
- mHeight =-1;
- }
- 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);
- return err == NO_ERROR ? reply.readInt32() : err;
- }
remote()返回的就是BpServiceManager中保存的BpBinder。
MediaPlayerService 从BnMediaPlayerService派生,其家族关系如下:
- class MediaPlayerService : public BnMediaPlayerService //业务逻辑和通信
- class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
- class BnInterface : public IMediaPlayerService, public BBinder
- //IMediaPlayerService:负责业务逻辑
- //BBinder:负责通信
- class MediaPlayerService : public BnMediaPlayerService
- {
- class Client;
- class MediaConfigClient;
- class AudioOutput : public MediaPlayerBase::AudioSink
- {
- ...
- };
- class AudioCache : public MediaPlayerBase::AudioSink
- {
- ...
- };
- public:
- static void instantiate();
- // IMediaPlayerService interface
- virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid);
- void removeMediaRecorderClient(wp<MediaRecorderClient> client);
- virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
- // House keeping for media player clients
- virtual sp<IMediaPlayer> create(
- pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- const KeyedVector<String8, String8> *headers);
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
- virtual sp<IMediaConfig> createMediaConfig(pid_t pid);
- virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
- virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
- virtual sp<IMemory> snoop();
- virtual sp<IOMX> getOMX();
- private:
- class Client : public BnMediaPlayer {
- virtual status_t prepareAsync();
- virtual status_t start();
- virtual status_t stop();
- virtual status_t pause();
- virtual status_t isPlaying(bool* state);
- virtual status_t seekTo(int msec);
- virtual status_t getCurrentPosition(int* msec);
- virtual status_t getDuration(int* msec);
- virtual status_t reset();
- virtual status_t setAudioStreamType(int type);
- virtual status_t setLooping(int loop);
- virtual status_t setVolume(float leftVolume, float rightVolume);
- virtual status_t invoke(const Parcel& request, Parcel *reply);
- virtual status_t setMetadataFilter(const Parcel& filter);
- virtual status_t getMetadata(bool update_only,
- bool apply_filter,
- Parcel *reply);
- sp<MediaPlayerBase> createPlayer(player_type playerType);
- status_t setDataSource(
- const char *url,
- const KeyedVector<String8, String8> *headers);
- status_t setDataSource(int fd, int64_t offset, int64_t length);
- static void notify(void* cookie, int msg, int ext1, int ext2);
- private:
- friend class MediaPlayerService;
- sp<MediaPlayerBase> getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; }
- };
- class MediaConfigClient: public BnMediaConfig
- {
- ...
- };
- // ----------------------------------------------------------------------------
- MediaPlayerService();
- virtual ~MediaPlayerService();
- mutable Mutex mLock;
- SortedVector< wp<Client> > mClients;
- SortedVector< wp<MediaRecorderClient> > mMediaRecorderClients;
- int32_t mNextConnId;
- sp<IOMX> mOMX;
- int32_t mRatio;
- int32_t mCrvs;
- int32_t mLeft;
- int32_t mTop;
- int32_t mWidth;
- int32_t mHeight;
- }
4.1 addService
- void MediaPlayerService::instantiate() {
- defaultServiceManager()->addService(
- String16("media.player"), new MediaPlayerService());
- }
创建一个新的Service—BnMediaPlayerService,想把它告诉ServiceManager。然后调用BpServiceManger的addService来向ServiceManager中增加一个Service.其它进程可通过字符串"media.player"来向ServiceManger查询到此服务。
addService是调用的BpServiceManager的函数。
- virtual status_t addService(const String16& name, const sp<IBinder>& service)
- {
- Parcel data, reply;
- //data是发送到BnServiceManager的命令包
- //看见没?先把Interface名字写进去,也就是什么android.os.IServiceManager
- data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
- //再把新service的名字写进去 叫media.player
- data.writeString16(name);
- //把新服务service—>就是MediaPlayerService写到命令中
- data.writeStrongBinder(service); <span style="color: rgb(255, 0, 0);">//把MediaPlayerService写入flat_binder_object中
- </span> //调用remote的transact函数
- status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
- return err == NO_ERROR ? reply.readInt32() : err;
- }
remote()返回的是前面创建的BpBinder(0).
- status_t BpBinder::transact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- //注意啊,这里的mHandle为0,code是ADD_SERVICE_TRANSACTION,data是命令包
- //reply是回复包,flags=0
- status_t status = IPCThreadState::self()->transact(
- mHandle, code, data, reply, flags);
- if (status == DEAD_OBJECT) mAlive = 0;
- return status;
- }
- ...
- }
- 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_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(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
- (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
- err = <span style="color: rgb(255, 0, 0);">writeTransactionData</span>(BC_TRANSACTION, flags, handle, code, data, NULL);//把要发送的数据写入binder_transaction_data中
- }
- 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 = <span style="color: rgb(255, 0, 0);">waitForResponse</span>(&fakeReply);
- }
- 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 << "(none requested)" << endl;
- }
- } else {
- err = waitForResponse(NULL, NULL);
- }
- return err;
- }
- status_t IPCThreadState::<span style="color: rgb(255, 0, 0);">writeTransactionData</span>(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;
- 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;
- }
上面的代码把数据封装成binder_transaction_data,然后写到mOut中。mOut是一个命令buffer,也是一个Parcel.
- status_t IPCThreadState::<span style="color: rgb(255, 0, 0);">waitForResponse</span>(Parcel *reply, status_t *acquireResult)
- {
- int32_t cmd;
- int32_t err;
- while (1) {
- if ((err=<span style="color: rgb(255, 0, 0);">talkWithDriver</span>()) < NO_ERROR) break; //发送数据到ServiceManager
- 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;
- }
- status_t IPCThreadState::talkWithDriver(bool doReceive)
- {
- LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");
- <span style="color: rgb(255, 0, 0);">binder_write_read bwr;
- </span>
- // 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;
- <span style="color: rgb(51, 51, 255);"> bwr.write_size = outAvail;
- bwr.write_buffer = (long unsigned int)mOut.data();</span>
- // This is what we'll read.
- if (doReceive && needRead) {
- <span style="color: rgb(51, 51, 255);"> bwr.read_size = mIn.dataCapacity();
- bwr.read_buffer = (long unsigned int)mIn.data();
- </span> } else {
- bwr.read_size = 0;
- }
- IF_LOG_COMMANDS() {
- TextOutput::Bundle _b(alog);
- if (outAvail != 0) {
- alog << "Sending commands to driver: " << indent;
- const void* cmds = (const void*)bwr.write_buffer;
- const void* end = ((const uint8_t*)cmds)+bwr.write_size;
- alog << HexDump(cmds, bwr.write_size) << endl;
- while (cmds < end) cmds = printCommand(alog, cmds);
- alog << dedent;
- }
- alog << "Size of receive buffer: " << bwr.read_size
- << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
- }
- // 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 { //<span style="color: red;">中间东西太复杂了,就是把<span lang="EN-US">mOut发送</span>数据和<span lang="EN-US">mIn</span>接收数据的处理后赋值给<span lang="EN-US">bwr</span></span>
- IF_LOG_COMMANDS() {
- alog << "About to read/write, write size = " << mOut.dataSize() << endl;
- }
- #if defined(HAVE_ANDROID_OS)
- <span style="color: rgb(255, 0, 0);"> <span style="font-size: 13px;"><strong>if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)</strong>
- </span></span> err = NO_ERROR;
- else
- err = -errno;
- #else
- err = INVALID_OPERATION;
- #endif
- IF_LOG_COMMANDS() {
- alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
- }
- } while (err == -EINTR);
- <span style="color: red;">//</span><span style="color: red;">到这里,回复数据就在<span lang="EN-US">bwr</span>中了,<span lang="EN-US">bwr</span>接收回复数据的<span lang="EN-US">buffer</span>就是<span lang="EN-US">mIn</span>提供的<span lang="EN-US"><o:p></o:p></span></span>
- 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 data size: " << mOut.dataSize() << endl;
- alog << "Received commands 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;
- }
至此发送addService到ServiceManager就已经结束了。BpServiceManager发送了一个addService命令到BnServiceManager,然后收到回复。
问题:MediaPlayerService是一个BnMediaPlayerService,那么它是不是应该等着
BpMediaPlayerService来和他交互呢?但是我们没看见MediaPlayerService有打开binder设备的操作啊!
深入了解mediaserver-2
http://blog.csdn.net/myarrow/article/details/7050746
4.2 BnServiceManager<servicemanager进程>
上面说了,defaultServiceManager返回的是一个BpServiceManager,通过它可以把命令请求发送到binder设备,而且handle的值为0。那么,系统的另外一端肯定有个接收命令的,那又是谁呢?
很可惜啊,BnServiceManager不存在,但确实有一个程序完成了BnServiceManager的工作,那就是/system/bin/servicemanager进程.虽然service_manager没有从BnServiceManager中派生,但是它肯定完成了BnServiceManager的功能。
- //service_manager.c
- int main(int argc, char **argv)
- {
- struct binder_state *bs;
- void *svcmgr = BINDER_SERVICE_MANAGER;
- bs = binder_open(128*1024);
- if (binder_become_context_manager(bs)) {
- LOGE("cannot become context manager (%s)\n", strerror(errno));
- return -1;
- }
- svcmgr_handle = svcmgr;
- <span style="color: rgb(255, 0, 0);"> binder_loop(bs, svcmgr_handler);
- </span> return 0;
- }
- void binder_loop(struct binder_state *bs, binder_handler func)
- {
- int res;
- struct binder_write_read bwr;
- unsigned readbuf[32];
- bwr.write_size = 0;
- bwr.write_consumed = 0;
- bwr.write_buffer = 0;
- readbuf[0] = BC_ENTER_LOOPER;
- binder_write(bs, readbuf, sizeof(unsigned));
- for (;;) {
- bwr.read_size = sizeof(readbuf);
- bwr.read_consumed = 0;
- bwr.read_buffer = (unsigned) readbuf;
- <span style="color: rgb(255, 0, 0);">res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
- </span>
- if (res < 0) {
- LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
- break;
- }
- <span style="color: rgb(255, 0, 0);">res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
- </span> if (res == 0) {
- LOGE("binder_loop: unexpected reply?!\n");
- break;
- }
- if (res < 0) {
- LOGE("binder_loop: io error %d %s\n", res, strerror(errno));
- break;
- }
- }
- }
- int svcmgr_handler(struct binder_state *bs,
- struct binder_txn *txn,
- struct binder_io *msg,
- struct binder_io *reply)
- {
- struct svcinfo *si;
- uint16_t *s;
- unsigned len;
- void *ptr;
- // LOGI("target=%p code=%d pid=%d uid=%d\n",
- // txn->target, txn->code, txn->sender_pid, txn->sender_euid);
- if (txn->target != svcmgr_handle)
- return -1;
- s = bio_get_string16(msg, &len);
- if ((len != (sizeof(svcmgr_id) / 2)) ||
- memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
- fprintf(stderr,"invalid id %s\n", str8(s));
- return -1;
- }
- switch(txn->code) {
- case SVC_MGR_GET_SERVICE:
- case SVC_MGR_CHECK_SERVICE:
- s = bio_get_string16(msg, &len);
- ptr = do_find_service(bs, s, len);
- if (!ptr)
- break;
- bio_put_ref(reply, ptr);
- return 0;
- case SVC_MGR_ADD_SERVICE:
- s = bio_get_string16(msg, &len);
- ptr = bio_get_ref(msg);
- if (do_add_service(bs, s, len, ptr, txn->sender_euid)) <span style="color: rgb(255, 0, 0);">//add a service to svclist
- </span> return -1;
- break;
- case SVC_MGR_LIST_SERVICES: {
- unsigned n = bio_get_uint32(msg);
- si = svclist;
- while ((n-- > 0) && si)
- si = si->next;
- if (si) {
- bio_put_string16(reply, si->name);
- return 0;
- }
- return -1;
- }
- default:
- LOGE("unknown code %d\n", txn->code);
- return -1;
- }
- bio_put_uint32(reply, 0);
- return 0;
- }
5. MediaPlayerService等待请求
/system/bin/mediaserver在ProcessState::Self()中打开了binder,其looper又在哪儿呢?
- //main_mediaserver.cpp
- int main(int argc, char** argv)
- {
- 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();
- }
5.1 startThreadPool
- void ProcessState::startThreadPool()
- {
- AutoMutex _l(mLock);
- if (!mThreadPoolStarted) {
- mThreadPoolStarted = true;
- spawnPooledThread(true);
- }
- }
- 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);
- <span style="color: rgb(255, 0, 0);">//创建线程池,然后run起来,和java的Thread何其像也。
- </span> sp<Thread> t = new PoolThread(isMain);
- t->run(buf);
- }
- }
- class PoolThread : public Thread
- {
- public:
- PoolThread(bool isMain)
- : mIsMain(isMain)
- {
- }
- protected:
- virtual bool threadLoop()
- {
- IPCThreadState::self()->joinThreadPool(mIsMain);
- return false;
- }
- const bool mIsMain;
- };
- <span style="font-size: 18px; color: rgb(255, 0, 0);">//还没有创建线程
- </span>status_t Thread::run(const char* name, int32_t priority, size_t stack)
- {
- Mutex::Autolock _l(mLock);
- if (mRunning) {
- // thread already started
- return INVALID_OPERATION;
- }
- // reset status and exitPending to their default value, so we can
- // try again after an error happened (either below, or in readyToRun())
- mStatus = NO_ERROR;
- mExitPending = false;
- mThread = thread_id_t(-1);
- // hold a strong reference on ourself
- mHoldSelf = this;
- mRunning = true;
- bool res;
- if (mCanCallJava) {
- <span style="color: rgb(255, 0, 0);">//name为android:unnamed_thread
- </span> res = createThreadEtc<span style="color: rgb(255, 0, 0);">(_threadLoop</span>,
- this, name, priority, stack, &mThread);
- } else {
- res = androidCreateRawThreadEtc(_<span style="color: rgb(255, 0, 0);">threadLoop</span>,
- this, name, priority, stack, &mThread);
- }
- if (res == false) {
- mStatus = UNKNOWN_ERROR; // something happened!
- mRunning = false;
- mThread = thread_id_t(-1);
- mHoldSelf.clear(); // "this" may have gone away after this.
- return UNKNOWN_ERROR;
- }
- // Do not refer to mStatus here: The thread is already running (may, in fact
- // already have exited with a valid mStatus result). The NO_ERROR indication
- // here merely indicates successfully starting the thread and does not
- // imply successful termination/execution.
- return NO_ERROR;
- }
- int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
- void *userData,
- const char* threadName,
- int32_t threadPriority,
- size_t threadStackSize,
- android_thread_id_t *threadId)
- {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- #ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */
- if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
- // We could avoid the trampoline if there was a way to get to the
- // android_thread_id_t (pid) from pthread_t
- thread_data_t* t = new thread_data_t;
- t->priority = threadPriority;
- t->threadName = threadName ? strdup(threadName) : NULL;
- t->entryFunction = entryFunction;
- t->userData = userData;
- entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
- userData = t;
- }
- #endif
- if (threadStackSize) {
- pthread_attr_setstacksize(&attr, threadStackSize);
- }
- errno = 0;
- pthread_t thread;
- <span style="color: rgb(255, 0, 0);">//终于看到了熟悉的线程创建,入口函数为:_threadLoop
- </span> int result = pthread_create(&thread, &attr,
- (android_pthread_entry)entryFunction, userData);
- if (result != 0) {
- LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
- "(android threadPriority=%d)",
- entryFunction, result, errno, threadPriority);
- return 0;
- }
- if (threadId != NULL) {
- *threadId = (android_thread_id_t)thread; // XXX: this is not portable
- }
- return 1;
- }
新开的线程的入口函数为:_threadLoop
- <span style="color: rgb(255, 0, 0);">int Thread::_threadLoop(void* user)
- </span>{
- Thread* const self = static_cast<Thread*>(user);
- sp<Thread> strong(self->mHoldSelf);
- wp<Thread> weak(strong);
- self->mHoldSelf.clear();
- #if HAVE_ANDROID_OS
- // this is very useful for debugging with gdb
- self->mTid = gettid();
- #endif
- bool first = true;
- do {
- bool result;
- if (first) {
- first = false;
- self->mStatus = self->readyToRun();
- result = (self->mStatus == NO_ERROR);
- if (result && !self->mExitPending) {
- // Binder threads (and maybe others) rely on threadLoop
- // running at least once after a successful ::readyToRun()
- // (unless, of course, the thread has already been asked to exit
- // at that point).
- // This is because threads are essentially used like this:
- // (new ThreadSubclass())->run();
- // The caller therefore does not retain a strong reference to
- // the thread and the thread would simply disappear after the
- // successful ::readyToRun() call instead of entering the
- // threadLoop at least once.
- result = self->threadLoop(); <span style="color: rgb(255, 0, 0);">//调用自己的<span lang="EN-US">threadLoop</span>
- </span> }
- } else {
- result = self->threadLoop();
- }
- if (result == false || self->mExitPending) {
- self->mExitPending = true;
- self->mLock.lock();
- self->mRunning = false;
- self->mThreadExitedCondition.broadcast();
- self->mLock.unlock();
- break;
- }
- // Release our strong reference, to let a chance to the thread
- // to die a peaceful death.
- strong.clear();
- // And immediately, re-acquire a strong reference for the next loop
- strong = weak.promote();
- } while(strong != 0);
- return 0;
- }
PoolThread::threadLoop
- class PoolThread : public Thread
- {
- public:
- PoolThread(bool isMain)
- : mIsMain(isMain)
- {
- }
- protected:
- <span style="color: rgb(255, 0, 0);">virtual bool threadLoop()</span>
- { ////mIsMain为true。 而且注意,这是一个新的线程,所以必然会创建一个新的IPCThreadState对象(记得线程本地存储吗?TLS)
- <span style="color: rgb(255, 0, 0);">IPCThreadState::self()->joinThreadPool(mIsMain);
- </span> return false;
- }
- const bool mIsMain;
- };
主线程和工作线程都调用了joinThreadPool
- void IPCThreadState::joinThreadPool(bool isMain)
- {
- LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
- <span style="color: rgb(255, 0, 0);">mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
- </span>
- // 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
- <span style="color: rgb(255, 0, 0);">result = talkWithDriver();
- </span> 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;
- }
- <span style="color: rgb(255, 0, 0);">result = executeCommand(cmd);
- </span> }
- // 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);
- }
有loop了,但是有两个线程都执行了这个啊!这里有两个消息循环?
看看executeCommand
- 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();
- LOG_ASSERT(refs->refBase() == obj,
- "BR_ACQUIRE: object %p does not match cookie %p (expected %p)",
- refs, obj, refs->refBase());
- obj->incStrong(mProcess.get());
- IF_LOG_REMOTEREFS() {
- LOG_REMOTEREFS("BR_ACQUIRE from 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();
- LOG_ASSERT(refs->refBase() == obj,
- "BR_RELEASE: object %p does not match cookie %p (expected %p)",
- refs, obj, refs->refBase());
- IF_LOG_REMOTEREFS() {
- LOG_REMOTEREFS("BR_RELEASE from 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).
- //LOG_ASSERT(refs->refBase() == obj,
- // "BR_DECREFS: object %p does not match 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());
- LOG_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;
- <span style="color: rgb(255, 0, 0);">case BR_TRANSACTION:
- </span> {
- binder_transaction_data tr;
- result = mIn.read(&tr, sizeof(tr));
- LOG_ASSERT(result == NO_ERROR,
- "Not enough command data for brTRANSACTION");
- 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);
- }
- }
- //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
- Parcel reply;
- IF_LOG_TRANSACTIONS() {
- TextOutput::Bundle _b(alog);
- alog << "BR_TRANSACTION thr " << (void*)pthread_self()
- << " / obj " << tr.target.ptr << " / code "
- << TypeCode(tr.code) << ": " << indent << buffer
- << dedent << endl
- << "Data addr = "
- << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
- << ", offsets addr="
- << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
- }
- <span style="color: rgb(255, 0, 0);"> if (tr.target.ptr) {
- sp<BBinder> b((BBinder*)tr.cookie); <span style="color: rgb(51, 51, 255);">//这里用的是<span lang="EN-US">BBinder</span>。
- </span> const status_t error = b->transact(tr.code, buffer, &reply, 0);
- if (error < NO_ERROR) reply.setError(error);
- } else {
- const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);
- if (error < NO_ERROR) reply.setError(error);
- }
- </span>
- //LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
- // mCallingPid, origPid, origUid);
- if ((tr.flags & TF_ONE_WAY) == 0) {
- LOG_ONEWAY("Sending reply to %d!", mCallingPid);
- sendReply(reply, 0);
- } else {
- LOG_ONEWAY("NOT sending reply 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 %d received from Binder driver\n", cmd);
- result = UNKNOWN_ERROR;
- break;
- }
- if (result != NO_ERROR) {
- mLastError = result;
- }
- return result;
- }
BBinder的transact函数如下:
- 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); <span style="color: rgb(255, 0, 0);">//调用自己的onTransact,实际调用BnMediaPlayerService::onTransact
- </span> break;
- }
- if (reply != NULL) {
- reply->setDataPosition(0);
- }
- return err;
- }
BnMediaPlayerService从BBinder派生,所以会调用到它的onTransact函数,终于水落石出了,让我们看看BnMediaPlayerServcice的onTransact函数。
- status_t BnMediaPlayerService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- <span style="color: rgb(255, 0, 0);"> // BnMediaPlayerService从BBinder和IMediaPlayerService派生
- // 所有IMediaPlayerService提供的函数都通过命令类型来区分
- </span>
- switch(code) {
- case CREATE_URL: {
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
- pid_t pid = data.readInt32();
- sp<IMediaPlayerClient> client =
- interface_cast<IMediaPlayerClient>(data.readStrongBinder());
- const char* url = data.readCString();
- KeyedVector<String8, String8> headers;
- int32_t numHeaders = data.readInt32();
- for (int i = 0; i < numHeaders; ++i) {
- String8 key = data.readString8();
- String8 value = data.readString8();
- headers.add(key, value);
- }
- <span style="color: rgb(255, 0, 0);">//create是一个虚函数,由MediaPlayerService来实现,见MediaPlayerService::create
- </span> <span style="color: rgb(255, 0, 0);">//MediaPlayerService.cpp
- </span> sp<IMediaPlayer> player = create(
- pid, client, url, numHeaders > 0 ? &headers : NULL);
- reply->writeStrongBinder(player->asBinder());
- return NO_ERROR;
- } break;
- ...
- }
- }
其实,到这里,我们就明白了。BnXXX的onTransact函数收取命令,然后派发到派生类XXX的对应函数,由他们完成实际的工作。
说明:
这里有点特殊,startThreadPool和joinThreadPool完后确实有两个线程,主线程和工作线程,而且都在做消息循环。为什么要这么做呢?他们参数isMain都是true。不知道google搞什么。难道是怕一个线程工作量太多,所以搞两个线程来工作?这种解释应该也是合理的。
网上有人测试过把最后一句屏蔽掉,也能正常工作。但是难道主线程退出了,程序还能不退出吗?这个...管它的,反正知道有两个线程在那处理就行了。
深入了解mediaserver-3
http://blog.csdn.net/myarrow/article/details/7050974
6. MediaPlayer如何与MediaPlayerService交互
6.1 MeidaPlayerService根据MediaPlayer的请求,创建对应的MeidaPlayer
- //MediaPlayerService.cpp
- static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
- notify_callback_f notifyFunc)
- {
- sp<MediaPlayerBase> p;
- switch (playerType) {
- case XX_PLAYER:
- LOGV("Create XXPlayer");
- p = new XXPlayerService();
- break;
- #ifndef NO_OPENCORE
- case PV_PLAYER:
- LOGV(" create PVPlayer");
- p = new PVPlayer();
- break;
- #endif
- case SONIVOX_PLAYER:
- LOGV(" create MidiFile");
- p = new MidiFile();
- break;
- case VORBIS_PLAYER:
- LOGV(" create VorbisPlayer");
- p = new VorbisPlayer();
- break;
- #if BUILD_WITH_FULL_STAGEFRIGHT
- case STAGEFRIGHT_PLAYER:
- LOGV(" create StagefrightPlayer");
- p = new StagefrightPlayer;
- break;
- #endif
- case TEST_PLAYER:
- LOGV("Create Test Player stub");
- p = new TestPlayerStub();
- break;
- }
- if (p != NULL) {
- if (p->initCheck() == NO_ERROR) {
- p->setNotifyCallback(cookie, notifyFunc);
- } else {
- p.clear();
- }
- }
- if (p == NULL) {
- LOGE("Failed to create player object");
- }
- return p;
- }
- class MediaPlayer : public BnMediaPlayerClient,
- public virtual IMediaDeathNotifier
- =============================================================
- class IMediaPlayerClient: public IInterface
- {
- public:
- DECLARE_META_INTERFACE(MediaPlayerClient);
- virtual void notify(int msg, int ext1, int ext2) = 0;
- };
- class BnMediaPlayerClient: public BnInterface<IMediaPlayerClient>
- {
- public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
- };
- =============================================================
- class IMediaDeathNotifier: virtual public RefBase
- {
- public:
- IMediaDeathNotifier() { addObitRecipient(this); }
- virtual ~IMediaDeathNotifier() { removeObitRecipient(this); }
- virtual void died() = 0;
- //establish binder interface to MediaPlayerService
- static const sp<IMediaPlayerService>& getMediaPlayerService();
- private:
- IMediaDeathNotifier &operator=(const IMediaDeathNotifier &);
- IMediaDeathNotifier(const IMediaDeathNotifier &);
- static void addObitRecipient(const wp<IMediaDeathNotifier>& recipient);
- static void removeObitRecipient(const wp<IMediaDeathNotifier>& recipient);
- class DeathNotifier: public IBinder::DeathRecipient
- {
- public:
- DeathNotifier() {}
- virtual ~DeathNotifier();
- virtual void binderDied(const wp<IBinder>& who);
- };
- friend class DeathNotifier;
- static Mutex sServiceLock;
- static sp<IMediaPlayerService> sMediaPlayerService;
- static sp<DeathNotifier> sDeathNotifier;
- static SortedVector< wp<IMediaDeathNotifier> > sObitRecipients;
- }
6.2 通过ServiceManager获取BpMediaPlayerService
- const sp<IMediaPlayerService>& IMediaDeathNotifier::getMediaPlayerService()
- {
- LOGV("getMediaPlayerService");
- Mutex::Autolock _l(sServiceLock);
- if (sMediaPlayerService.get() == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16("media.player"));
- if (binder != 0) {
- break;
- }
- LOGW("Media player service not published, waiting...");
- usleep(500000); // 0.5 s
- } while(true);
- if (sDeathNotifier == NULL) {
- sDeathNotifier = new DeathNotifier();
- }
- binder->linkToDeath(sDeathNotifier);
- // sMediaPlayerService中保存的为BpMediaPlayerService
- sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
- }
- LOGE_IF(sMediaPlayerService == 0, "no media player service!?");
- return sMediaPlayerService;
- }
6.3 获取mPlayer(IMediaPlayer,实质为BpMediaPlayer)
- status_t MediaPlayer::setDataSource(
- const char *url, const KeyedVector<String8, String8> *headers)
- {
- LOGV("setDataSource(%s)", url);
- status_t err = BAD_VALUE;
- if (url != NULL) {
- //service实质上是BpMediaPlayerService
- const sp<IMediaPlayerService>& service(getMediaPlayerService());
- if (service != 0) {
- // Player实质上是BpMediaPlayer
- sp<IMediaPlayer> player(service->create(getpid(), this, url, headers));
- //把BpMediaPlayer赋值给成员变量mPlayer,如果以前的mPlayer有效,则Disconnect以前的Player
- err = setDataSource(player);
- }
- }
- return err;
- }
BpMediaPlayerService::create (Client端)
- class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
- {
- public:
- BpMediaPlayerService(const sp<IBinder>& impl)
- : BpInterface<IMediaPlayerService>(impl)
- {
- }
- virtual sp<IMediaPlayer> create(
- pid_t pid, const sp<IMediaPlayerClient>& client,
- const char* url, const KeyedVector<String8, String8> *headers) {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
- data.writeInt32(pid);
- data.writeStrongBinder(client->asBinder());
- data.writeCString(url);
- if (headers == NULL) {
- data.writeInt32(0);
- } else {
- // serialize the headers
- data.writeInt32(headers->size());
- for (size_t i = 0; i < headers->size(); ++i) {
- data.writeString8(headers->keyAt(i));
- data.writeString8(headers->valueAt(i));
- }
- }
- remote()->transact(CREATE_URL, data, &reply); //传递到BnMediaPlayerSerivce执行
- return interface_cast<IMediaPlayer>(reply.readStrongBinder()); //返回BpMediaPlayer
- }
- }
在BnMediaPlayerService处理CREATE_URL(Server端)
- status_t BnMediaPlayerService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- switch(code) {
- case CREATE_URL: { //收到上面的CREATE_URL并进行处理
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
- pid_t pid = data.readInt32();
- sp<IMediaPlayerClient> client = //实质保存的为BpMediaPlayerClient,用于向MediaPlayer发通知消息,它为Client,MediaPlayer为Sever
- interface_cast<IMediaPlayerClient>(data.readStrongBinder());
- const char* url = data.readCString();
- KeyedVector<String8, String8> headers;
- int32_t numHeaders = data.readInt32();
- for (int i = 0; i < numHeaders; ++i) {
- String8 key = data.readString8();
- String8 value = data.readString8();
- headers.add(key, value);
- }
- //在BnMediaPlayerService的派生类MediaPlayerService中实现,创建一个Client对象(Client:public BnMediaPlayer)
- sp<IMediaPlayer> player = create(
- pid, client, url, numHeaders > 0 ? &headers : NULL);
- reply->writeStrongBinder(player->asBinder());
- return NO_ERROR;
- } break;
- }
MediaPlayerService::create才是真正的实现创建IMediaPlayer
- <p>sp<IMediaPlayer> MediaPlayerService::create(
- pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- const KeyedVector<String8, String8> *headers)
- {
- int32_t connId = android_atomic_inc(&mNextConnId);</p><p> //创建一个Clinet,class Client : public BnMediaPlayer,真正实现start, stop, pause, resume...
- sp<Client> c = new Client(this, pid, connId, client);
- LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);</p><p> //分析url,并创建真正的player(demuxer,decoder)
- if (NO_ERROR != c->setDataSource(url, headers))
- {
- c.clear();
- return c;
- }
- wp<Client> w = c;
- Mutex::Autolock lock(mLock);
- mClients.add(w);
- return c;//返回此BnMediaPlayer派生类的对象
- }</p>
MediaPlayerService::Client::setDataSource分析URL类型,然后创建对应的Player
- status_t MediaPlayerService::Client::setDataSource(
- const char *url, const KeyedVector<String8, String8> *headers)
- {
- LOGV("setDataSource(%s)", url);
- if (url == NULL)
- return UNKNOWN_ERROR;
- if (strncmp(url, "content://", 10) == 0) {
- // get a filedescriptor for the content Uri and
- // pass it to the setDataSource(fd) method
- String16 url16(url);
- int fd = android::openContentProviderFile(url16);
- if (fd < 0)
- {
- LOGE("Couldn't open fd for %s", url);
- return UNKNOWN_ERROR;
- }
- setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
- close(fd);
- return mStatus;
- } else {
- //根据url返回对应的player_type,如: PV_PLAYER,STAGEFRIGHT_PLAYER, XX_PLAYER
- player_type playerType = getPlayerType(url);
- LOGV("player type = %d", playerType);
- // create the right type of player,建立真正的AVPlayer
- sp<MediaPlayerBase> p = createPlayer(playerType);
- if (p == NULL) return NO_INIT;
- if (!p->hardwareOutput()) {
- mAudioOutput = new AudioOutput();
- static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
- }
- // now set data source,把URL传递给真正的AVPlayer
- LOGV(" setDataSource");
- mStatus = p->setDataSource(url, headers);
- p->setOutRange( mService->getLeft(), mService->getTop(), mService->getWidth(), mService->getHeight());
- if (mStatus == NO_ERROR) {
- mPlayer = p;
- } else {
- LOGE(" error: %d", mStatus);
- }
- return mStatus;
- }
- }
创建真正的AVPlayer
- sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
- {
- // determine if we have the right player type
- sp<MediaPlayerBase> p = mPlayer;
- LOGV("Enter MediaPlayerService::Client::createPlayer: playerType is %d", playerType);
- if ((p != NULL) && (p->playerType() != playerType)) {
- LOGV("p->playerType() is: %d, , delete player", p->playerType());
- p.clear();
- }
- if (p == NULL) {
- LOGV("Create new player");
- p = android::createPlayer(playerType, this, notify);
- }
- return p;
- }
- static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
- notify_callback_f notifyFunc)
- {
- sp<MediaPlayerBase> p;
- switch (playerType) {
- case XX_PLAYER:
- LOGV("Create XXPlayer");
- p = new XXPlayerService();
- break;
- #ifndef NO_OPENCORE
- case PV_PLAYER:
- LOGV(" create PVPlayer");
- p = new PVPlayer();
- break;
- #endif
- case SONIVOX_PLAYER:
- LOGV(" create MidiFile");
- p = new MidiFile();
- break;
- case VORBIS_PLAYER:
- LOGV(" create VorbisPlayer");
- p = new VorbisPlayer();
- break;
- #if BUILD_WITH_FULL_STAGEFRIGHT
- case STAGEFRIGHT_PLAYER:
- LOGV(" create StagefrightPlayer");
- p = new StagefrightPlayer;
- break;
- #endif
- case TEST_PLAYER:
- LOGV("Create Test Player stub");
- p = new TestPlayerStub();
- break;
- }
- if (p != NULL) {
- if (p->initCheck() == NO_ERROR) {
- p->setNotifyCallback(cookie, notifyFunc);
- } else {
- p.clear();
- }
- }
- if (p == NULL) {
- LOGE("Failed to create player object");
- }
- return p;
- }
6.4 开始播放MediaPlayer::start
MediaPlayer::mPlayer实质为BpMediaPlayer
MediaPlayerService::Client::mPlayer实质为真正的AVPlayer,如:PVPlayer, XXPlayer
class PVPlayer: public MediaPlayerInterface
class MediaPlayerInterface : public MediaPlayerBase
MediaPlayer::start() --> mPlayer->start(BpMediaPlayer::start) --> remote()->transact(START, data, &reply)--> BpBinder::transact--> IPCThreadState::self()->transact--> ioctl(写) --> ioctl(读,在IPCThreadState::joinThreadPool中调用) --> BBinder::transact --> BnMediaPlayer::onTransact --> MediaPlayerService::Client::start -->MediaPlayerService::Client::mPlayer->start(PVPlayer->start)
- 深入了解MediaServer-1
- 深入了解MediaServer-1
- 深入了解MediaServer-1
- 深入了解MediaServer-1
- 深入了解mediaserver-2
- 深入了解mediaserver-3
- 深入了解mediaserver-2
- 深入了解mediaserver-3
- mediaserver
- 深入了解GNED.....1
- 深入了解HashMap(1)
- 深入了解C语言(1)
- 深入了解javaScipt--String(1)
- 深入了解phalanger(1)
- 深入了解:++与+1、--与-1
- 深入了解php4(1)--回到未来
- 深入了解:液晶显示器的工作原理1
- 转载: 深入了解Oracle SCN (1)
- string 字符串分割
- 数据结构之汉诺塔(递归)
- spring aop 实现读写分离
- 重温数据结构:Huffman树的建立
- 【我所认知的BIOS】—> uEFI 开始
- 深入了解MediaServer-1
- WIN7下解决AVR编译Invalid argument异常的问题
- hivesql语法经验
- WinDbg命令详解--断点
- LCD基本原来
- (libgdx学习)Fullscreen&vsync
- jquery解析JSON数据的方法
- asp.net ToString()格式汇总
- CMMI3 和 CMMI 4