首先是从MediaPlayer的setDataSource方法开始,MediaPlayer的setDataSource有多个重载方法:
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(@NonNull Context context, @NonNull Uri uri)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(context, uri, null, null);
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(@NonNull Context context, @NonNull Uri uri,
@Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies)
throws IOException {
if (context == null) {
throw new NullPointerException("context param can not be null.");
}
if (uri == null) {
throw new NullPointerException("uri param can not be null.");
}
if (cookies != null) {
CookieHandler cookieHandler = CookieHandler.getDefault();
if (cookieHandler != null && !(cookieHandler instanceof CookieManager)) {
throw new IllegalArgumentException("The cookie handler has to be of CookieManager "
+ "type when cookies are provided.");
}
}
// The context and URI usually belong to the calling user. Get a resolver for that user
// and strip out the userId from the URI if present.
final ContentResolver resolver = context.getContentResolver();
final String scheme = uri.getScheme();
final String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority());
if (ContentResolver.SCHEME_FILE.equals(scheme)) {
setDataSource(uri.getPath());
return;
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
&& Settings.AUTHORITY.equals(authority)) {
// Try cached ringtone first since the actual provider may not be
// encryption aware, or it may be stored on CE media storage
final int type = RingtoneManager.getDefaultType(uri);
final Uri cacheUri = RingtoneManager.getCacheForType(type, context.getUserId());
final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
if (attemptDataSource(resolver, cacheUri)) {
return;
} else if (attemptDataSource(resolver, actualUri)) {
return;
} else {
setDataSource(uri.toString(), headers, cookies);
}
} else {
// Try requested Uri locally first, or fallback to media server
if (attemptDataSource(resolver, uri)) {
return;
} else {
setDataSource(uri.toString(), headers, cookies);
}
}
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(@NonNull Context context, @NonNull Uri uri,
@Nullable Map<String, String> headers)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(context, uri, headers, null);
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(String path)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(path, null, null);
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(String path, Map<String, String> headers)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(path, headers, null);
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(@NonNull AssetFileDescriptor afd)
throws IOException, IllegalArgumentException, IllegalStateException {
Preconditions.checkNotNull(afd);
// Note: using getDeclaredLength so that our behavior is the same
// as previous versions when the content provider is returning
// a full file.
if (afd.getDeclaredLength() < 0) {
setDataSource(afd.getFileDescriptor());
} else {
setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
}
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(FileDescriptor fd)
throws IOException, IllegalArgumentException, IllegalStateException {
// intentionally less than LONG_MAX
setDataSource(fd, 0, 0x7ffffffffffffffL);
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(FileDescriptor fd, long offset, long length)
throws IOException, IllegalArgumentException, IllegalStateException {
try (ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(fd)) {
if (modernFd == null) {
_setDataSource(fd, offset, length);
} else {
_setDataSource(modernFd.getFileDescriptor(), offset, length);
}
} catch (IOException e) {
Log.w(TAG, "Ignoring IO error while setting data source", e);
}
}
}
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDataSource(MediaDataSource dataSource)
throws IllegalArgumentException, IllegalStateException {
_setDataSource(dataSource);
}
}
上面重载方法最后会调用_setDataSource方法,而_setDataSource是一个native方法:
private native void _setDataSource(FileDescriptor fd, long offset, long length)
private native void _setDataSource(MediaDataSource dataSource)
通过查询frameworks/base/media/jni/android_media_MediaPlayer.cpp的gMethods得到:
{"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
{"_setDataSource", "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback },
调用android_media_MediaPlayer_setDataSourceFD方法:
//frameworks/base/media/jni/android_media_MediaPlayer.cpp
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." );
}
调用android_media_MediaPlayer_setDataSourceCallback方法:
//frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource)
{
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
if (dataSource == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return;
}
sp<IDataSource> callbackDataSource = new JMediaDataSource(env, dataSource);
process_media_player_call(env, thiz, mp->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed." );
}
上面代码处理如下:
取得MediaPlayer对象
创建IDataSource对象callbackDataSource
调用MediaPlayer的setDataSource方法
其中创建IDataSource对象我们之后再分析,我们继续分析MediaPlayer的setDataSource方法:
//frameworks/av/media/libmedia/MediaPlayer.cpp
status_t MediaPlayer::setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url, const KeyedVector<String8, String8> *headers)
{
ALOGV("setDataSource(%s)", url);
status_t err = BAD_VALUE;
if (url != NULL) {
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(httpService, url, headers))) {
player.clear();
}
err = attachNewPlayer(player);
}
}
return err;
}
//frameworks/av/media/libmedia/MediaPlayer.cpp
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(fd, offset, length))) {
player.clear();
}
err = attachNewPlayer(player);
}
return err;
}
//frameworks/av/media/libmedia/MediaPlayer.cpp
status_t MediaPlayer::setDataSource(const sp<IDataSource> &source)
{
ALOGV("setDataSource(IDataSource)");
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService> service(getMediaPlayerService()); //通过ServiceManager找到MediaPlayerService服务的Client端实例,初始化service对象
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource)); //player实例实际是一个MediaPlayerServcie::Client实例,该内部类继承自IMediaPlayer,负责向外提供其定义的业务服务,通过Binder机制向MediaPlayerService请求创建IMediaPlayer对象
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(source))) {
player.clear();
}
err = attachNewPlayer(player);
}
return err;
}
//frameworks/av/media/libmedia/MediaPlayer.cpp
status_t MediaPlayer::setDataSource(const String8& rtpParams)
{
ALOGV("setDataSource(rtpParams)");
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(rtpParams))) {
player.clear();
}
err = attachNewPlayer(player);
}
return err;
}
上面方法主要处理如下:
调用getMediaPlayerService方法,通过ServiceManager找到MediaPlayerService服务的Client端实例,初始化service对象。
调用IMediaPlayerService的create方法,通过Binder机制向MediaPlayerService请求创建IMediaPlayer对象。
调用doSetRetransmitEndpoint方法。
调用IMediaPlayer的setDataSource方法。
下面我们逐步分析:
getMediaPlayerService
调用IMediaDeathNotifier的getMediaPlayerService获取IMediaPlayerService对象:
//frameworks/av/media/libmedia/IMediaDeathNotifier.cpp
sp<IMediaPlayerService> IMediaDeathNotifier::sMediaPlayerService;
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
sp<IServiceManager> sm = defaultServiceManager(); //获取IServiceManager对象
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player")); //获取Media player service的IBinder对象
if (binder != 0) {
break;
}
ALOGW("Media player service not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); //interface_cast是一个模板方法,它会对参数进行判断,如果参数是BnInterface,则返回其自身,如果参数是BpInterface,则new一个Bp代理对象并返回
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
MediaPlayerService::create
通过ServiceManager找到MediaPlayerService服务的Client端实例,通过Binder机制向MediaPlayerService请求创建IMediaPlayer对象:
//frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId, const AttributionSourceState& attributionSource)
{
int32_t connId = android_atomic_inc(&mNextConnId);
// TODO b/182392769: use attribution source util
AttributionSourceState verifiedAttributionSource = attributionSource;
verifiedAttributionSource.pid = VALUE_OR_FATAL(
legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
verifiedAttributionSource.uid = VALUE_OR_FATAL(
legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
sp<Client> c = new Client(
this, verifiedAttributionSource, connId, client, audioSessionId); //创建Client对象,并返回该对象
ALOGV("Create new client(%d) from %s, ", connId,
verifiedAttributionSource.toString().c_str());
wp<Client> w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
doSetRetransmitEndpoint
调用doSetRetransmitEndpoint设置重新传输终结点:
//frameworks/base/media/java/android/media/MediaPlayer.java
status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
Mutex::Autolock _l(mLock);
if (player == NULL) {
return UNKNOWN_ERROR;
}
if (mRetransmitEndpointValid) {
return player->setRetransmitEndpoint(&mRetransmitEndpoint); //调用IMediaPlayer的setRetransmitEndpoint方法
}
return OK;
}
IMediaPlayer的setDataSource
调用sIMediaPlayer的setDataSource方法:
//frameworks/av/media/libmedia/IMediaPlayer.cpp
class BpMediaPlayer: public BpInterface<IMediaPlayer>
{
status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char* url,
const KeyedVector<String8, String8>* headers)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
data.writeInt32(httpService != NULL);
if (httpService != NULL) {
data.writeStrongBinder(IInterface::asBinder(httpService));
}
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(SET_DATA_SOURCE_URL, data, &reply); //发送SET_DATA_SOURCE_URL消息
return reply.readInt32();
}
status_t setDataSource(int fd, int64_t offset, int64_t length) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
data.writeFileDescriptor(fd);
data.writeInt64(offset);
data.writeInt64(length);
remote()->transact(SET_DATA_SOURCE_FD, data, &reply); //发送SET_DATA_SOURCE_URL消息
return reply.readInt32();
}
status_t setDataSource(const sp<IStreamSource> &source) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(source));
remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply); //发送SET_DATA_SOURCE_URL消息
return reply.readInt32();
}
status_t setDataSource(const sp<IDataSource> &source) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(source));
remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply); //发送SET_DATA_SOURCE_URL消息
return reply.readInt32();
}
status_t setDataSource(const String8& rtpParams) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
data.writeString8(rtpParams);
remote()->transact(SET_DATA_SOURCE_RTP, data, &reply); //发送SET_DATA_SOURCE_URL消息
return reply.readInt32();
}
}
发送的消息会在BnMediaPlayer::onTransact中处理:
//frameworks/av/media/libmedia/IMediaPlayer.cpp
status_t BnMediaPlayer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case SET_DATA_SOURCE_URL: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<IMediaHTTPService> httpService;
if (data.readInt32()) {
httpService =
interface_cast<IMediaHTTPService>(data.readStrongBinder());
}
const char* url = data.readCString();
if (url == NULL) {
reply->writeInt32(BAD_VALUE);
return NO_ERROR;
}
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);
}
reply->writeInt32(setDataSource(
httpService, url, numHeaders > 0 ? &headers : NULL)); //调用MediaPlayerService的setDataSource方法
return NO_ERROR;
} break;
case SET_DATA_SOURCE_FD: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
int fd = data.readFileDescriptor();
int64_t offset = data.readInt64();
int64_t length = data.readInt64();
reply->writeInt32(setDataSource(fd, offset, length)); //调用MediaPlayerService的setDataSource方法
return NO_ERROR;
}
case SET_DATA_SOURCE_STREAM: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<IStreamSource> source =
interface_cast<IStreamSource>(data.readStrongBinder());
if (source == NULL) {
reply->writeInt32(BAD_VALUE);
} else {
reply->writeInt32(setDataSource(source)); //调用MediaPlayerService的setDataSource方法
}
return NO_ERROR;
}
case SET_DATA_SOURCE_CALLBACK: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<IDataSource> source =
interface_cast<IDataSource>(data.readStrongBinder());
if (source == NULL) {
reply->writeInt32(BAD_VALUE);
} else {
reply->writeInt32(setDataSource(source)); //调用MediaPlayerService的setDataSource方法
}
return NO_ERROR;
}
case SET_DATA_SOURCE_RTP: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
String8 rtpParams = data.readString8();
reply->writeInt32(setDataSource(rtpParams)); //调用MediaPlayerService的setDataSource方法
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
调用MediaPlayerService的setDataSource方法: