接着上一篇,MediaPlayerService已经被注册到ServiceManager中了,本篇将接着分析MediaPlayerService服务的获取,以及通过MediaPlayerService服务创建播放器2个流程。
从
status_t MediaPlayer::setDataSource(
const sp &httpService,
const char *url, const KeyedVector *headers)
{
ALOGV("setDataSource(%s)", url);
status_t err = BAD_VALUE;
if (url != NULL) {
//1,获取IMediaPlayerService服务
const sp& service(getMediaPlayerService());
if (service != 0) {
//2,让远程服务创建播放器
sp player(service->create(this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
//通过IMediaPlayer操作播放器
(NO_ERROR != player->setDataSource(httpService, url, headers))) {
player.clear();
}
err = attachNewPlayer(player);
}
}
return err;
}
我们先看getMediaPlayerService()函数的执行过程。
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
//获取IServiceManager
sp sm = defaultServiceManager();
sp binder;
do {
//使用String16("media.player")获取服务
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
//如果服务还未注册,等待
usleep(500000); // 0.5 s
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
//将IBinder保存到BpMediaPlayerService的成员变量mRemote中
sMediaPlayerService = interface_cast(binder);
}
return sMediaPlayerService;
}
defaultServiceManager()返回BpServiceManager。
class BpServiceManager : public BpInterface
{
public:
BpServiceManager(const sp& impl)
: BpInterface(impl)
{
}
virtual sp getService(const String16& name) const
{
unsigned n;
//最多查询5次
for (n = 0; n < 5; n++){
sp svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
//发送查找指令
virtual sp checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
//发送CHECK_SERVICE_TRANSACTION指令
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
//读取响应数据
return reply.readStrongBinder();
}
transact会通过BpBinder(0)发送数据给ServiceManager查找名字为"media.player"的Service,在上一篇分析过,ServiceManager会通过svcmgr_handler函数来处理请求。
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
......
switch(txn->code) {
//获取某个Service,通过msg来取
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
//s为对应Service名字
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
//查找Service,返回handle值
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
//不为0则找到
if (!handle)
break;
//写入reply回传给客户端
bio_put_ref(reply, handle);
return 0;
do_find_service根据"media.player"进行查找,并返回它的句柄handle。
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
struct svcinfo *si;
//检查权限
if (!svc_can_find(s, len, spid)) {
ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n",
str8(s, len), uid);
return 0;
}
//查找服务
si = find_svc(s, len);
//si不为null,handle大于0
if (si && si->handle) {
if (!si->allow_isolated) {
uid_t appid = uid % AID_USER;
if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
return 0;
}
}
//成功返回handle
return si->handle;
} else {
return 0;
}
}
继续看查找的关键函数find_svc。
struct svcinfo *find_svc(const uint16_t *s16, size_t len)
{
struct svcinfo *si;
//遍历
for (si = svclist; si; si = si->next) {
if ((len == si->len) &&
!memcmp(s16, si->name, len * sizeof(uint16_t))) {
return si;
}
}
return NULL;
}
Service整个查找过程,就是根据Service名去遍历svcinfo链表,找到svcinfo结构体后,将svcinfo的handle值写入缓存,回传给客户端。
我们回头看reply.readStrongBinder()这个方法如何解析响应数据,和返回需要的服务对象。reply是一个Parcel类。
sp Parcel::readStrongBinder() const
{
sp val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
}
status_t unflatten_binder(const sp& proc,
const Parcel& in, sp* out)
{
//读取数据
const flat_binder_object* flat = in.readObject(false);
//此时为BINDER_TYPE_HANDLE类型
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
//传入handle
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp result;
AutoMutex _l(mLock);
//构建一个entry
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
//此时handle不为0
if (handle == 0) {
Parcel data;
//ping下驱动是否通
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
//根据handle创建了一个BpBinder
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
//将创建的BpBinder返回
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
这里的流程和获取IServiceManger是相同的,只是此时的handle大于0,它通过ProcessState创建了一个BpBinder(handle)。
回到IMediaDeathNotifier::getMediaPlayerService函数,BpBinder(handle)同样通过interface_cast进行了强转,强转流程可以看前面IServiceManger的获取流程。
也就是说,最终客户端得到一个BpMediaPlayerService,它的成员变量mRemote持有一个BpBinder(handle),有了这个handle句柄,就能通过Binder驱动和MediaPlayerService进行通讯了。
流程1到此分析完成,即当前已获取到了IMediaPlayerService。继续分析流程2,IMediaPlayerService调用了create函数,创建播放器。
virtual sp create(
const sp& client, int audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeStrongBinder(client->asBinder());
data.writeInt32(audioSessionId);
//获取mRemote,发送创建指令CREATE,
remote()->transact(CREATE, data, &reply);
//返回播放器引用
return interface_cast(reply.readStrongBinder());
}
通过remote()获取mRemote,即BpBinder(0)发送CREATE创建指令。上一篇分析过,MediaPlayerService在MediaServer中创建,并开启了两个线程循环执行talkWithDriver函数,循环读写消息,假设其中一个线程收到CREATE这个指令,最终将执行executeCommand函数,
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
......
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
if (result != NO_ERROR) break;
......
Parcel reply;
status_t error;
//转为BBinder对象,实际就是BnMediaPlayerService
if (tr.target.ptr) {
sp b((BBinder*)tr.cookie);
error = b->transact(tr.code, buffer, &reply, tr.flags);
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
BpXXX对应着服务端在客户端的业务代理,而Bn则对应服务端本地的业务处理类,因此每个服务端都包含一个BnXXX内部类,它继承模板类BnInterface和BBinder对象。
class BnMediaPlayerService: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
};
template
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
而transact函数定义在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);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
onTransact用于处理消息数据,它是一个虚函数,由继承关系知道,它实现在BnMediaPlayerService中。
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
......
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp client =
interface_cast(data.readStrongBinder());
int audioSessionId = data.readInt32();
//创建播放器
sp player = create(client, audioSessionId);
//将播放器转为Binder类型的数据,写入响应缓冲区
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
......
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
如上,BnMediaPlayerService将会创建一个播放器,返回给MediaPlayer.cpp客户端,这个MediaPlayer.cpp的远程服务端是一个MediaPlayerService的内部类,为Client,它继承自IMediaPlayer。
sp MediaPlayerService::create(const sp& client,
int audioSessionId)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
int32_t connId = android_atomic_inc(&mNextConnId);
//创建Client对象,它是BnMediaPlayer的子类
sp c = new Client(
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid());
wp w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
Client是MediaPlayerService的内部类,它继承自BnMediaPlayer,也就是IMediaPlayer的服务端,函数返回后,也就是客户端得到Client的远程对象代理,那么紧接着会执行Client的setDataSource函数。
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
struct stat sb;
int ret = fstat(fd, &sb);
if (ret != 0) {
return UNKNOWN_ERROR;
}
if (offset >= sb.st_size) {
ALOGE("offset error");
::close(fd);
return UNKNOWN_ERROR;
}
if (offset + length > sb.st_size) {
length = sb.st_size - offset;
ALOGV("calculated length = %lld", length);
}
//获取到当前适合播放该视频源的播放器类型
player_type playerType = MediaPlayerFactory::getPlayerType(this,
fd,
offset,
length);
// 根据得到的播放器类型去创建对应的播放器实例:
sp p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
}
setDataSource_post(p, p->setDataSource(fd, offset, length));
return mStatus;
}
这里分两步执行,先获取到适合播放该视频源的播放器类型,再根据这个类型去创建播放器。MediaPlayerFactory保存的工厂类,在MediaPlayerService构造时就注册好了。
MediaPlayerService::MediaPlayerService()
{
ALOGV("MediaPlayerService created");
mNextConnId = 1;
mBatteryAudio.refCount = 0;
for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
mBatteryAudio.deviceOn[i] = 0;
mBatteryAudio.lastTime[i] = 0;
mBatteryAudio.totalTime[i] = 0;
}
mBatteryAudio.deviceOn[SPEAKER] = 1;
const sp sm(defaultServiceManager());
if (sm != NULL) {
const String16 name("batterystats");
sp batteryStats =
interface_cast(sm->getService(name));
if (batteryStats != NULL) {
batteryStats->noteResetVideo();
batteryStats->noteResetAudio();
}
}
//注册播放器工厂类
MediaPlayerFactory::registerBuiltinFactories();
}
构造函数最后一行注册了所有类型播放器工厂。
void MediaPlayerFactory::registerBuiltinFactories() {
Mutex::Autolock lock_(&sLock);
if (sInitComplete)
return;
registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
sInitComplete = true;
}
我们回头看根据类型获取播放器的函数setDataSource_pre。
sp MediaPlayerService::Client::setDataSource_pre(
player_type playerType)
{
//根据类型创建播放器
sp p = createPlayer(playerType);
if (p == NULL) {
return p;
}
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
mPid, mAudioAttributes);
static_cast(p.get())->setAudioSink(mAudioOutput);
}
return p;
}
sp MediaPlayerService::Client::createPlayer(player_type playerType)
{
sp p = mPlayer;
if ((p != NULL) && (p->playerType() != playerType)) {
ALOGV("delete player");
p.clear();
}
//通过工厂类创建播放器
if (p == NULL) {
p = MediaPlayerFactory::createPlayer(playerType, this, notify);
}
if (p != NULL) {
p->setUID(mUID);
}
return p;
}
关键代码所示,MediaPlayerFactory工厂类获取播放器。
sp MediaPlayerFactory::createPlayer(
player_type playerType,
void* cookie,
notify_callback_f notifyFunc) {
sp p;
IFactory* factory;
status_t init_result;
Mutex::Autolock lock_(&sLock);
if (sFactoryMap.indexOfKey(playerType) < 0) {
ALOGE("Failed to create player object of type %d, no registered"
" factory", playerType);
return p;
}
//从sFactoryMap获取对应的工厂类
factory = sFactoryMap.valueFor(playerType);
CHECK(NULL != factory);
//通过IFactory内部类的不同实现类,创建不同的MediaPlayer
p = factory->createPlayer();
if (p == NULL) {
ALOGE("Failed to create player object of type %d, create failed",
playerType);
return p;
}
init_result = p->initCheck();
if (init_result == NO_ERROR) {
p->setNotifyCallback(cookie, notifyFunc);
} else {
p.clear();
}
return p;
}
在注册工厂类时已经将各类型工厂加入到成员sFactoryMap中,此时根据类型获取到特定的工厂,并通过createPlayer创建播放器,安卓有2种类型的播放器,以NuPlayerFactory为例来看下创建的函数。
class NuPlayerFactory : public MediaPlayerFactory::IFactory {
public:
virtual float scoreFactory(const sp& /*client*/,
const char* url,
float curScore) {
static const float kOurScore = 0.8;
if (kOurScore <= curScore)
return 0.0;
if (!strncasecmp("http://", url, 7)
|| !strncasecmp("https://", url, 8)
|| !strncasecmp("file://", url, 7)) {
size_t len = strlen(url);
if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
return kOurScore;
}
if (strstr(url,"m3u8")) {
return kOurScore;
}
if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
return kOurScore;
}
}
if (!strncasecmp("rtsp://", url, 7)) {
return kOurScore;
}
return 0.0;
}
virtual float scoreFactory(const sp& /*client*/,
const sp& /*source*/,
float /*curScore*/) {
return 1.0;
}
//创建播放器
virtual sp createPlayer() {
ALOGV(" create NuPlayer");
return new NuPlayerDriver;
}
};
到此播放器便创建完成,