summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Laurent <elaurent@google.com> 2010-06-21 09:27:30 -0700
committer Eric Laurent <elaurent@google.com> 2010-06-22 17:14:04 -0700
commit619346f902241736d933657a4fe10f10c50a1ba8 (patch)
treef80b46008c2d457def70dfab095a18d6eb61fc09
parentd1559d6b2db1d7e1718a15dc43a82450de2934db (diff)
Added support for audio sessions in MediaPlayer and AudioTrack.
Audio sessions are used to associate audio effects to particular instances (or groups) of MediaPlayers or AudioTracks. Change-Id: Ib94eec43241cfcb416590f435ddce7ab39a07640
-rw-r--r--core/jni/android_media_AudioTrack.cpp33
-rw-r--r--include/media/IMediaPlayerService.h7
-rw-r--r--include/media/mediaplayer.h3
-rw-r--r--media/java/android/media/AudioTrack.java70
-rw-r--r--media/java/android/media/MediaPlayer.java44
-rw-r--r--media/jni/android_media_MediaPlayer.cpp27
-rw-r--r--media/libmedia/AudioTrack.cpp6
-rw-r--r--media/libmedia/IMediaPlayerService.cpp19
-rw-r--r--media/libmedia/mediaplayer.cpp26
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp42
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h13
11 files changed, 252 insertions, 38 deletions
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 65c04357adfd..ce43e736b145 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -166,7 +166,7 @@ static void audioCallback(int event, void* user, void *info) {
static int
android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jint streamType, jint sampleRateInHertz, jint channels,
- jint audioFormat, jint buffSizeInBytes, jint memoryMode)
+ jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession)
{
LOGV("sampleRate=%d, audioFormat(from Java)=%d, channels=%x, buffSize=%d",
sampleRateInHertz, audioFormat, channels, buffSizeInBytes);
@@ -253,6 +253,20 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
lpJniStorage->mStreamType = atStreamType;
+ jint* nSession = NULL;
+ if (jSession) {
+ nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
+ if (nSession == NULL) {
+ LOGE("Error creating AudioTrack: Error retrieving session id pointer");
+ delete lpJniStorage;
+ return AUDIOTRACK_ERROR;
+ }
+ } else {
+ LOGE("Error creating AudioTrack: invalid session ID pointer");
+ delete lpJniStorage;
+ return AUDIOTRACK_ERROR;
+ }
+
// create the native AudioTrack object
AudioTrack* lpTrack = new AudioTrack();
if (lpTrack == NULL) {
@@ -273,7 +287,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
0,// shared mem
- true);// thread can call Java
+ true,// thread can call Java
+ nSession[0]);// audio session ID
} else if (memoryMode == javaAudioTrackFields.MODE_STATIC) {
// AudioTrack is using shared memory
@@ -293,7 +308,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
lpJniStorage->mMemBase,// shared mem
- true);// thread can call Java
+ true,// thread can call Java
+ nSession[0]);// audio session ID
}
if (lpTrack->initCheck() != NO_ERROR) {
@@ -301,6 +317,12 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
goto native_init_failure;
}
+ // read the audio session ID back from AudioTrack in case we create a new session
+ nSession[0] = lpTrack->getSessionId();
+
+ env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
+ nSession = NULL;
+
// save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field
// of the Java object (in mNativeTrackInJavaObj)
env->SetIntField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (int)lpTrack);
@@ -317,6 +339,9 @@ native_init_failure:
env->SetIntField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, 0);
native_track_failure:
+ if (nSession != NULL) {
+ env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
+ }
env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class);
env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref);
delete lpJniStorage;
@@ -785,7 +810,7 @@ static JNINativeMethod gMethods[] = {
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
- {"native_setup", "(Ljava/lang/Object;IIIIII)I",
+ {"native_setup", "(Ljava/lang/Object;IIIIII[I)I",
(void *)android_media_AudioTrack_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_native_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_native_release},
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 31c09917fc2e..e892875113fd 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -40,8 +40,11 @@ public:
virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, const KeyedVector<String8, String8> *headers = NULL) = 0;
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
+ const char* url, const KeyedVector<String8, String8> *headers = NULL,
+ int audioSessionId = 0) = 0;
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
+ int fd, int64_t offset, int64_t length, int audioSessionId) = 0;
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IOMX> getOMX() = 0;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index dc783ce9b6ff..62a4e50a2e68 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -172,6 +172,8 @@ public:
status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
status_t suspend();
status_t resume();
+ status_t setAudioSessionId(int sessionId);
+ int getAudioSessionId();
private:
void clear_l();
status_t seekTo_l(int msec);
@@ -198,6 +200,7 @@ private:
float mRightVolume;
int mVideoWidth;
int mVideoHeight;
+ int mAudioSessionId;
};
}; // namespace android
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1e8d72f47a34..079c41fdfab7 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -210,6 +210,10 @@ public class AudioTrack
* @see AudioFormat#ENCODING_PCM_16BIT
*/
private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+ /**
+ * Audio session ID
+ */
+ private int mSessionId = 0;
//--------------------------------
@@ -258,6 +262,48 @@ public class AudioTrack
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode)
throws IllegalArgumentException {
+ this(streamType, sampleRateInHz, channelConfig, audioFormat,
+ bufferSizeInBytes, mode, 0);
+ }
+
+ /**
+ * Class constructor with audio session. Use this constructor when the AudioTrack must be
+ * attached to a particular audio session. The primary use of the audio session ID is to
+ * associate audio effects to a particular instance of AudioTrack: if an audio session ID
+ * is provided when creating an AudioEffect, this effect will be applied only to audio tracks
+ * and media players in the same session and not to the output mix.
+ * When an AudioTrack is created without specifying a session, it will create its own session
+ * which can be retreived by calling the {@link #getAudioSessionId()} method.
+ * If a session ID is provided, this AudioTrack will share effects attached to this session
+ * with all other media players or audio tracks in the same session.
+ * @param streamType the type of the audio stream. See
+ * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
+ * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and
+ * {@link AudioManager#STREAM_ALARM}
+ * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but
+ * not limited to) 44100, 22050 and 11025.
+ * @param channelConfig describes the configuration of the audio channels.
+ * See {@link AudioFormat#CHANNEL_OUT_MONO} and
+ * {@link AudioFormat#CHANNEL_OUT_STEREO}
+ * @param audioFormat the format in which the audio data is represented.
+ * See {@link AudioFormat#ENCODING_PCM_16BIT} and
+ * {@link AudioFormat#ENCODING_PCM_8BIT}
+ * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read
+ * from for playback. If using the AudioTrack in streaming mode, you can write data into
+ * this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
+ * this is the maximum size of the sound that will be played for this instance.
+ * See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size
+ * for the successful creation of an AudioTrack instance in streaming mode. Using values
+ * smaller than getMinBufferSize() will result in an initialization failure.
+ * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
+ * @param sessionId Id of audio session the AudioTrack must be attached to
+ * @throws java.lang.IllegalArgumentException
+ // FIXME: unhide.
+ * @hide
+ */
+ public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
+ int bufferSizeInBytes, int mode, int sessionId)
+ throws IllegalArgumentException {
mState = STATE_UNINITIALIZED;
// remember which looper is associated with the AudioTrack instanciation
@@ -269,15 +315,23 @@ public class AudioTrack
audioBuffSizeCheck(bufferSizeInBytes);
+ if (sessionId < 0) {
+ throw (new IllegalArgumentException("Invalid audio session ID: "+sessionId));
+ }
+
+ int[] session = new int[1];
+ session[0] = sessionId;
// native initialization
int initResult = native_setup(new WeakReference<AudioTrack>(this),
mStreamType, mSampleRate, mChannels, mAudioFormat,
- mNativeBufferSizeInBytes, mDataLoadMode);
+ mNativeBufferSizeInBytes, mDataLoadMode, session);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
}
+ mSessionId = session[0];
+
if (mDataLoadMode == MODE_STATIC) {
mState = STATE_NO_STATIC_DATA;
} else {
@@ -590,6 +644,17 @@ public class AudioTrack
}
}
+ /**
+ * Returns the audio session ID.
+ *
+ * @return the ID of the audio session this AudioTrack belongs to.
+ // FIXME: unhide.
+ // FIXME: link to AudioEffect class when public.
+ * @hide
+ */
+ public int getAudioSessionId() {
+ return mSessionId;
+ }
//--------------------------------------------------------------------------
// Initialization / configuration
@@ -1012,7 +1077,7 @@ public class AudioTrack
private native final int native_setup(Object audiotrack_this,
int streamType, int sampleRate, int nbChannels, int audioFormat,
- int buffSizeInBytes, int mode);
+ int buffSizeInBytes, int mode, int[] sessionId);
private native final void native_finalize();
@@ -1056,6 +1121,7 @@ public class AudioTrack
static private native final int native_get_min_buff_size(
int sampleRateInHz, int channelConfig, int audioFormat);
+ private native final int native_get_session_id();
//---------------------------------------------------------
// Utility methods
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index c9d46508aecf..8caa07a5821f 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -423,6 +423,18 @@ import java.lang.ref.WeakReference;
* <td>Successful invoke of this method in a valid state transfers the
* object to the <em>Stopped</em> state. Calling this method in an
* invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>setAudioSessionId </p></td>
+ * <td>{Idle} </p></td>
+ * <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
+ * Error} </p></td>
+ * <td>This method must be called in idle state as the audio session ID must be known before
+ * calling setDataSource. Calling it does not change the object state. </p></td></tr>
+ * <tr><td>getAudioSessionId </p></td>
+ * <td>any </p></td>
+ * <td>{} </p></td>
+ * <td>This method can be called in any state and calling it does not change
+ * the object state. </p></td></tr>
+ *
* </table>
*
* <a name="Permissions"></a>
@@ -1159,6 +1171,38 @@ public class MediaPlayer
public native Bitmap getFrameAt(int msec) throws IllegalStateException;
/**
+ * Sets the audio session ID.
+ *
+ * @param sessionId: the audio session ID.
+ * The audio session ID is a system wide unique identifier for the audio stream played by
+ * this MediaPlayer instance.
+ * The primary use of the audio session ID is to associate audio effects to a particular
+ * instance of MediaPlayer: if an audio session ID is provided when creating an audio effect,
+ * this effect will be applied only to the audio content of media players within the same
+ * audio session and not to the output mix.
+ * When created, a MediaPlayer instance automatically generates its own audio session ID.
+ * However, it is possible to force this player to be part of an already existing audio session
+ * by calling this method.
+ * This method must be called before one of the overloaded <code> setDataSource </code> methods.
+ * @throws IllegalStateException if it is called in an invalid state
+ *
+ // FIXME: unhide.
+ // FIXME: link to AudioEffect class when public.
+ * @hide
+ */
+ public native void setAudioSessionId(int sessionId) throws IllegalArgumentException, IllegalStateException;
+
+ /**
+ * Returns the audio session ID.
+ *
+ * @return the audio session ID. {@see #setAudioSessionId(int)}.
+ * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer was contructed.
+ // FIXME: unhide.
+ * @hide
+ */
+ public native int getAudioSessionId();
+
+ /**
* @param request Parcel destinated to the media player. The
* Interface token must be set to the IMediaPlayer
* one to be routed correctly through the system.
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 60ff26493487..c5250d7bb44f 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -292,7 +292,7 @@ static void setVideoSurface(const sp<MediaPlayer>& mp, JNIEnv *env, jobject thiz
if (surface != NULL) {
const sp<Surface> native_surface = get_surface(env, surface);
LOGV("prepare: surface=%p (id=%d)",
- native_surface.get(), native_surface->ID());
+ native_surface.get(), native_surface->getIdentity());
mp->setVideoSurface(native_surface);
}
}
@@ -332,7 +332,7 @@ android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
if (surface != NULL) {
const sp<Surface> native_surface = get_surface(env, surface);
LOGV("prepareAsync: surface=%p (id=%d)",
- native_surface.get(), native_surface->ID());
+ native_surface.get(), native_surface->getIdentity());
mp->setVideoSurface(native_surface);
}
process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
@@ -705,6 +705,27 @@ android_media_MediaPlayer_native_suspend_resume(
return isSuspend ? mp->suspend() : mp->resume();
}
+static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, jint sessionId) {
+ LOGV("set_session_id(): %d", sessionId);
+ sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL ) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+ process_media_player_call( env, thiz, mp->setAudioSessionId(sessionId), NULL, NULL );
+}
+
+static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) {
+ LOGV("get_session_id()");
+ sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL ) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return 0;
+ }
+
+ return mp->getAudioSessionId();
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -738,6 +759,8 @@ static JNINativeMethod gMethods[] = {
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"snoop", "([SI)I", (void *)android_media_MediaPlayer_snoop},
{"native_suspend_resume", "(Z)I", (void *)android_media_MediaPlayer_native_suspend_resume},
+ {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
+ {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
};
static const char* const kClassPathName = "android/media/MediaPlayer";
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 2118f8f350c2..0f2093a176dd 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -92,7 +92,8 @@ AudioTrack::AudioTrack(
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
- frameCount, flags, cbf, user, notificationFrames, 0);
+ frameCount, flags, cbf, user, notificationFrames,
+ 0, false, sessionId);
}
AudioTrack::AudioTrack(
@@ -109,7 +110,8 @@ AudioTrack::AudioTrack(
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
- 0, flags, cbf, user, notificationFrames, sharedBuffer);
+ 0, flags, cbf, user, notificationFrames,
+ sharedBuffer, false, sessionId);
}
AudioTrack::~AudioTrack()
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 71c5f862cdad..1ae222ea4638 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -58,7 +58,7 @@ public:
virtual sp<IMediaPlayer> create(
pid_t pid, const sp<IMediaPlayerClient>& client,
- const char* url, const KeyedVector<String8, String8> *headers) {
+ const char* url, const KeyedVector<String8, String8> *headers, int audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(pid);
@@ -75,8 +75,10 @@ public:
data.writeString8(headers->valueAt(i));
}
}
+ data.writeInt32(audioSessionId);
remote()->transact(CREATE_URL, data, &reply);
+
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}
@@ -89,7 +91,8 @@ public:
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length)
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd,
+ int64_t offset, int64_t length, int audioSessionId)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -98,8 +101,11 @@ public:
data.writeFileDescriptor(fd);
data.writeInt64(offset);
data.writeInt64(length);
+ data.writeInt32(audioSessionId);
+
remote()->transact(CREATE_FD, data, &reply);
- return interface_cast<IMediaPlayer>(reply.readStrongBinder());
+
+ return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
}
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
@@ -166,9 +172,10 @@ status_t BnMediaPlayerService::onTransact(
String8 value = data.readString8();
headers.add(key, value);
}
+ int audioSessionId = data.readInt32();
sp<IMediaPlayer> player = create(
- pid, client, url, numHeaders > 0 ? &headers : NULL);
+ pid, client, url, numHeaders > 0 ? &headers : NULL, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
@@ -180,7 +187,9 @@ status_t BnMediaPlayerService::onTransact(
int fd = dup(data.readFileDescriptor());
int64_t offset = data.readInt64();
int64_t length = data.readInt64();
- sp<IMediaPlayer> player = create(pid, client, fd, offset, length);
+ int audioSessionId = data.readInt32();
+
+ sp<IMediaPlayer> player = create(pid, client, fd, offset, length, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index c6bbbcc9cf2d..d5a3c133e816 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -55,6 +55,7 @@ MediaPlayer::MediaPlayer()
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
+ mAudioSessionId = AudioSystem::newAudioSessionId();
}
MediaPlayer::~MediaPlayer()
@@ -137,7 +138,7 @@ status_t MediaPlayer::setDataSource(
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(
- service->create(getpid(), this, url, headers));
+ service->create(getpid(), this, url, headers, mAudioSessionId));
err = setDataSource(player);
}
}
@@ -150,7 +151,7 @@ status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
- sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
+ sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
err = setDataSource(player);
}
return err;
@@ -501,6 +502,27 @@ status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
return OK;
}
+status_t MediaPlayer::setAudioSessionId(int sessionId)
+{
+ LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
+ Mutex::Autolock _l(mLock);
+ if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
+ LOGE("setAudioSessionId called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (sessionId < 0) {
+ return BAD_VALUE;
+ }
+ mAudioSessionId = sessionId;
+ return NO_ERROR;
+}
+
+int MediaPlayer::getAudioSessionId()
+{
+ Mutex::Autolock _l(mLock);
+ return mAudioSessionId;
+}
+
void MediaPlayer::notify(int msg, int ext1, int ext2)
{
LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index d7ca6356300d..d45c17b1e5ad 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -252,11 +252,12 @@ sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pi
sp<IMediaPlayer> MediaPlayerService::create(
pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- const KeyedVector<String8, String8> *headers)
+ const KeyedVector<String8, String8> *headers, int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
- 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);
+ sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+ LOGV("Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d",
+ connId, pid, url, connId, audioSessionId);
if (NO_ERROR != c->setDataSource(url, headers))
{
c.clear();
@@ -269,12 +270,12 @@ sp<IMediaPlayer> MediaPlayerService::create(
}
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
- int fd, int64_t offset, int64_t length)
+ int fd, int64_t offset, int64_t length, int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
- sp<Client> c = new Client(this, pid, connId, client);
- LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",
- connId, pid, fd, offset, length);
+ sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+ LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d",
+ connId, pid, fd, offset, length, audioSessionId);
if (NO_ERROR != c->setDataSource(fd, offset, length)) {
c.clear();
} else {
@@ -609,7 +610,7 @@ void MediaPlayerService::removeClient(wp<Client> client)
}
MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
- int32_t connId, const sp<IMediaPlayerClient>& client)
+ int32_t connId, const sp<IMediaPlayerClient>& client, int audioSessionId)
{
LOGV("Client(%d) constructor", connId);
mPid = pid;
@@ -618,6 +619,8 @@ MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t
mClient = client;
mLoop = false;
mStatus = NO_INIT;
+ mAudioSessionId = audioSessionId;
+
#if CALLBACK_ANTAGONIZER
LOGD("create Antagonizer");
mAntagonizer = new Antagonizer(notify, this);
@@ -871,7 +874,7 @@ status_t MediaPlayerService::Client::setDataSource(
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
- mAudioOutput = new AudioOutput();
+ mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@@ -921,7 +924,7 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
- mAudioOutput = new AudioOutput();
+ mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@@ -1412,9 +1415,11 @@ sp<IMemory> MediaPlayerService::snoop()
#undef LOG_TAG
#define LOG_TAG "AudioSink"
-MediaPlayerService::AudioOutput::AudioOutput()
+MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
: mCallback(NULL),
- mCallbackCookie(NULL) {
+ mCallbackCookie(NULL),
+ mSessionId(sessionId) {
+ LOGV("AudioOutput(%d)", sessionId);
mTrack = 0;
mStreamType = AudioSystem::MUSIC;
mLeftVolume = 1.0;
@@ -1504,7 +1509,7 @@ status_t MediaPlayerService::AudioOutput::open(
bufferCount = mMinBufferCount;
}
- LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+ LOGV("open(%u, %d, %d, %d, %d)", sampleRate, channelCount, format, bufferCount,mSessionId);
if (mTrack) close();
int afSampleRate;
int afFrameCount;
@@ -1529,14 +1534,21 @@ status_t MediaPlayerService::AudioOutput::open(
frameCount,
0 /* flags */,
CallbackWrapper,
- this);
+ this,
+ 0,
+ mSessionId);
} else {
t = new AudioTrack(
mStreamType,
sampleRate,
format,
(channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
- frameCount);
+ frameCount,
+ 0,
+ NULL,
+ NULL,
+ 0,
+ mSessionId);
}
if ((t == 0) || (t->initCheck() != NO_ERROR)) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 2408c621b9b5..60b91c6907d0 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -65,7 +65,7 @@ class MediaPlayerService : public BnMediaPlayerService
class AudioOutput : public MediaPlayerBase::AudioSink
{
public:
- AudioOutput();
+ AudioOutput(int sessionId);
virtual ~AudioOutput();
virtual bool ready() const { return mTrack != NULL; }
@@ -108,6 +108,7 @@ class MediaPlayerService : public BnMediaPlayerService
float mRightVolume;
float mMsecsPerFrame;
uint32_t mLatency;
+ int mSessionId;
static bool mIsOnEmulator;
static int mMinBufferCount; // 12 for emulator; otherwise 4
@@ -185,9 +186,9 @@ public:
// 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);
+ const KeyedVector<String8, String8> *headers, int audioSessionId);
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId);
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();
@@ -237,12 +238,15 @@ private:
pid_t pid() const { return mPid; }
virtual status_t dump(int fd, const Vector<String16>& args) const;
+ int getAudioSessionId() { return mAudioSessionId; }
+
private:
friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service,
pid_t pid,
int32_t connId,
- const sp<IMediaPlayerClient>& client);
+ const sp<IMediaPlayerClient>& client,
+ int audioSessionId);
Client();
virtual ~Client();
@@ -271,6 +275,7 @@ private:
status_t mStatus;
bool mLoop;
int32_t mConnId;
+ int mAudioSessionId;
// Metadata filters.
media::Metadata::Filter mMetadataAllow; // protected by mLock