可爱的BpXXX-图
来源:互联网 发布:Linux grep-e 编辑:程序博客网 时间:2024/04/28 14:37
1. 说BpXXX(如BpMediaPlayer)可爱,是因为它总是默默无闻地工作做,且基本上不露面(有点害羞的样子),但却总是做着重要的工作,没有它你如何调用mediaserver中为你准备好的各种功能呢?有了它,我们告诉它要听流行的“伤不起”,它就帮你放。你说它是不是一个听话的孩子呢?老板是不是很喜欢这样的员工呢
2. 既然它如此重要,但又基本上不露面,这可太为难我们这些天天if else的兄弟了。因为要找它难,没找到它之前,对这些if else的理解就更难了。所以做人也不能太害羞了,否则害了自己也害了大家,当然像MediaPlayer这样过于高调也不好,啥事不做,只当一个传话筒,还哪么高调,天天到处叫,来调我吧,来用我吧
3. 在上一篇文章《Android媒体播放器框架--图》中讲过,MediaPlayer在setDataSource中调用BpMediaPlayerService::create时创建了BpMediaPlayer,并把它保存在MediaPlayer的mPlayer中,以供后面的调用。
4. 本文重点分析这个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) { const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != 0) { //调用BpMediaPlayerService::create sp<IMediaPlayer> player(service->create(getpid(), this, url, headers)); //把新创建的BpMediaPlayer保存在MediaPlayer的成员变量mPlayer中 err = setDataSource(player); } } return err;}
自从这个MediaPlayer有了这个mPlayer之后,什么事就叫mPlayer来做,自已就成了领导了。
5.这明明是返回的是IMediaPlayer,为什么偏说是BpMediaPlayer呢?其原因有二。
1)得益于C++中,只要这个指针指向派生类的对象,可把它转换为基类的指针来保存,调用方法时,会执行对应派生类中的方法。
2)先看看MediaPlayer的家族图谱:
现在有两个问题需要解答:
1)为什么说上面代码中创建的player为指向BpMediaPlayer的指针?
2)为什么说BpMediaPlayer中的mRemote为指向BpBinder的指针?
6. 为什么说上面代码中创建的player为指向BpMediaPlayer的指针
这个还是让代码自己来讲吧:
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>{public: ... 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)); } } //通过Binder发送请求给MediaPlayerService remote()->transact(CREATE_URL, data, &reply); //这就是重点??? reply.readStrongBinder()); 的返回值为一个new的BpBinder return interface_cast<IMediaPlayer>(reply.readStrongBinder()); //返回值为一个new的BpMediaPlayer } ...}
interface_cast<IMediaPlayer>(reply.readStrongBinder());结果是什么呢? 是IMediaPlayer还是BpMediaPlayer?期待其中的答案...(让我轻轻地告诉你,它是一个BpMeidaPlayer)
看似简单的一行代码,其内容可不简单,因为它涉及一个又一个模板。好玩吧!
6.1 先看看其参数是什么东东...(先偷偷地告诉你,一个新new的BpBinder)
reply.readStrongBinder()代码如下:
sp<IBinder> Parcel::readStrongBinder() const{ sp<IBinder> val; unflatten_binder(ProcessState::self(), *this, &val); return val;}
没什么,再向下看,不是什么东东都可以向下看的,否则别人会骂的。
status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out){ const flat_binder_object* flat = in.readObject(false); if (flat) { switch (flat->type) { case BINDER_TYPE_BINDER: *out = static_cast<IBinder*>(flat->cookie); return finish_unflatten_binder(NULL, *flat, in); case BINDER_TYPE_HANDLE: //因为我们是Client,当然会调用这个 *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in); } } return BAD_TYPE;}
6.1.1 还是哪么简单,只有两行代码,可内容还是不简单,再深入一步,看看第一行代码out返回的是什么东东?
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); 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,其handle为传入的handle.现在已经看到reply.readStrongBinder()的返回值为一个BpBinder,即interface_cast<IMediaPlayer>(reply.readStrongBinder());的参数为一个BpBinder.
6.1.2 返回值已经产生,第二行代码finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in);做什么呢?
inline static status_t finish_unflatten_binder( BpBinder* proxy, const flat_binder_object& flat, const Parcel& in){ return NO_ERROR;}
啥事没干,而且游戏嘎然而止。至此,参数已经分析完成,其结果就是一个指向BpBinder的一个指针。
7. 看看interface_cast<IMediaPlayer>(reply.readStrongBinder())即interface_cast<IMediaPlayer>(BpBinder)做了些什么,且返回值是什么? 老规距,让代码自己说话。以下就要与模板打交道了。
7.1 寻找asInterface的真身
template<typename INTERFACE>inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){ return INTERFACE::asInterface(obj);}
又是一很简单。还原后代码为:
inline sp<IMediaPlayer> interface_cast(const sp<IBinder>& obj){ return IMediaPlayer::asInterface(obj);}
原来以刚new的BpBinder对象为参数,调用IMediaPlayer::asInterface,还不快进去看其中的代码...,你以为你想进就进啊,你以为你是谁,告诉你没地方可进,代码中没看到这个函数,怎么办呢。只能看看IMedialayer的定义了。其定义中发现这么一行代码:
class IMediaPlayer: public IInterface{public: DECLARE_META_INTERFACE(MediaPlayer); ...}
很显然这是一个宏,这个可以看看吧!
#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();
我终于明白了你,原来在这儿定义了这个一直找寻的IMedaiPlayer::asInterface,老办法,还原啊!
static const String16 descriptor; static sp<IMediaPlayer> asInterface(const sp<IBinder>& obj); virtual const String16& getInterfaceDescriptor() const; IMediaPlayer(); virtual ~IMediaPlayer();
asInterface的定义是有了,实现呢? asInterface啊asInterface,你怎么这么喜欢折腾人呢? 原来还认为你的BpXXX很可爱,现在觉得有点狡猾了。没办法,谁叫我们是搞if esle的呢! 继续找啊,相信有定义就有实现。找啊找,找到一个有意思的东东IMPLEMENT_META_INTERFACE(INTERFACE, NAME),Search下,在IMediaPlayer发现了IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");此宏定义如下:
#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 IMediaPlayer::descriptor("android.media.IMediaPlayer"); const String16& IMediaPlayer::getInterfaceDescriptor() const { return IMediaPlayer::descriptor; } sp<IMediaPlayer> IMediaPlayer::asInterface(const sp<IBinder>& obj) { sp<IMediaPlayer> intr; if (obj != NULL) { intr = static_cast<IMediaPlayer*>( obj->queryLocalInterface( IMediaPlayer::descriptor).get()); if (intr == NULL) { intr = new BpMediaPlayer(obj); } } return intr; } IMediaPlayer::IMediaPlayer() { } IMediaPlayer::~IMediaPlayer() { }
终于有asInterface的实现了,急切的心情看看他都做了些什么,单独拿出来品品吧!
sp<IMediaPlayer> IMediaPlayer::asInterface(const sp<IBinder>& obj) { sp<IMediaPlayer> intr; if (obj != NULL) { intr = static_cast<IMediaPlayer*>( obj->queryLocalInterface( IMediaPlayer::descriptor).get()); if (intr == NULL) { intr = new BpMediaPlayer(obj); //第一次肯定执行这儿 } } return intr; }
看到intr = new BpMediaPlayer(obj),obj为刚创建的BpBinder, 看到没有,BpMediaPlayer(常说的BpXXX)以如此低调的方式登场,难怪我们一时找不到它。
至此,已经很明确了,interface_cast<IMediaPlayer>(reply.readStrongBinder());的结果是上面创建的BpMediaPlayer.
7.2 看看new BpMediaPlayer都做了些什么?
还是让代码自己讲吧!
BpMediaPlayer(const sp<IBinder>& impl) : BpInterface<IMediaPlayer>(impl) { }
impl为刚创建的BpBinder, 再看看BpInterface<IMediaPlayer>(impl)做了什么。
template<typename INTERFACE>inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote) : BpRefBase(remote){}
inline BpInterface<IMediaPlayer>::BpInterface(const sp<IBinder>& remote) : BpRefBase(remote){}
深入看看BpRefBase(remote)做了些什么?
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. }}
Oh,my God, 把刚创建的BpBinder赋值给了BpRefBase中的mRemote,所以上面的图上说mRemote本质上是一个BpBinder.现在得到证实了。
- 可爱的BpXXX-图
- 可爱的BpXXX-图
- 可爱的BpXXX-图
- BpXXX
- 可爱的图,送给可爱的人们
- 可爱的
- 挺可爱的强盗
- [图片] 可爱的Google
- 可爱的MM~
- 我的可爱老公
- 可爱的猪:)
- 可爱的女友
- 可爱的卡片!
- 可爱的孩子们
- 可爱的小动物
- 怪诞可爱的闹钟
- 可爱的重庆人
- 可爱的搜索引擎
- Android动态加载jar/dex
- 高校访问数据库
- android:minSdkVersion 之我见
- xshell 不能显示多个tab
- HTML h1 h2 h3 h4 h5 h6 标签
- 可爱的BpXXX-图
- 关于MyEclipse中配置Tomcat出错问题云云
- ACM 计划
- XCode快捷键
- Linux内存管理(下)
- GoldenGate配置实例:RHEL 4.7下的Oracle 10g RAC到单实例的单向同步(一)
- php读取文件的几种方法
- asp.net生成验证码
- Linux内存管理(上)