前言
废话不多说,media媒体服务重要就是了
服务启动
media服务是开机init进程解析init.rc时候启动的
init.rc:
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
它启动的是/system/bin/mediaserver的可执行程序,原型是main_mediaserver.cpp
我们直接看他的函数入口main函数关键实现:
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
我们只看上面代码的 MediaPlayerService::instantiate();这一行代码,
跟踪实现可得:
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
实际就是向defaultServiceManager注册服务,函数启动告一段落,后面说明怎么使用。
java层api调用
上面知道了服务在开机的时候就已经注册到系统的服务管理了,我们上层应用层在开发的时候会用到mediaplayer,不管你使用什么套路,最终都会调用setDataSource这个函数,它又会调用到native层_setDataSource:
private native void _setDataSource(
String path, String[] keys, String[] values)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
_setDataSource在native层代码在
android_media_MediaPlayer.cpp文件中,
{"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
它对应着android_media_MediaPlayer_setDataSourceFD函数,继续看这个函数的具体实现:
native层C/S端
static void
android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
{
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
if (fileDescriptor == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return;
}
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
ALOGV("setDataSourceFD: fd %d", fd);
process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
}
可以看到他又调用了native MediaPlayer类的setDataSource函数:
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService>& service(getMediaPlayerService()); //1
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); //2
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(fd, offset, length))) {
player.clear();
}
err = attachNewPlayer(player); //3
}
return err;
}
好了,这里是关键地方,速度放慢一点,首先是在注释1处,获取到了media.player服务,然后将返回值给了service这个引用,
注释2通过这个应用,调用了:
virtual sp<IMediaPlayer> create(
const sp<IMediaPlayerClient>& client, int audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeStrongBinder(client->asBinder());
data.writeInt32(audioSessionId);
remote()->transact(CREATE, data, &reply);
return interface_cast<IMediaPlayer>(reply.readStrongBinder()); //4
}
然后呢,服务端收到CREATE这个信令之后做了什么呢:
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
int audioSessionId = data.readInt32();
sp<IMediaPlayer> player = create(client, audioSessionId);//5
reply->writeStrongBinder(player->asBinder()); //6
return NO_ERROR;
} break;
主要注意注释5,6这段代码,结果是返回给上层一个MediaPlayerService::Client的实例,其中注释5所调用的代码如下:
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
int audioSessionId)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid());
ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
IPCThreadState::self()->getCallingUid());
wp<Client> w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
上层收到返回值之后,会调用 interface_cast,即注释4所在代码,
interface_cast实现:
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
asInterface实现:
android::sp<I##INTERFACE> I##INTERFACE::asInterface(
const android::sp<android::IBinder>& obj)
{
android::sp<I##INTERFACE> intr;
if (obj != NULL) {
intr = static_cast<I##INTERFACE*>(
obj->queryLocalInterface(
I##INTERFACE::descriptor).get());
if (intr == NULL) {
intr = new Bp##INTERFACE(obj);
}
}
return intr;
}
所以说注释4中最终返回给再上一层的是一个BpMediaPlayer对象
我们再回到注释3中,看这个attachNewPlayer函数实现:
status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
{
status_t err = UNKNOWN_ERROR;
sp<IMediaPlayer> p;
{ // scope for the lock
Mutex::Autolock _l(mLock);
if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
(mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
ALOGE("attachNewPlayer called in state %d", mCurrentState);
return INVALID_OPERATION;
}
clear_l();
p = mPlayer; //7
mPlayer = player; //8
if (player != 0) {
mCurrentState = MEDIA_PLAYER_INITIALIZED;
err = NO_ERROR;
} else {
ALOGE("Unable to create media player");
}
}
if (p != 0) {
p->disconnect();
}
return err;
}
再看一下注释7,8是关键,mPlayer 现在就是BpMediaPlayer这个对象了,后面start或者其他操作就可以通过binder调用
到BnMediaPlayer,而BnMediaPlayer是Client的父类,最终其实就是在调用MediaPlayerService::Client的函数。
后记
mediaplayer蛮有意思的,可以更好的辅助理解binder实现机制