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
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1e8d72f..079c41f 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -210,6 +210,10 @@
      * @see AudioFormat#ENCODING_PCM_16BIT
      */
     private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+    /**
+     * Audio session ID
+     */
+    private int mSessionId = 0;
 
 
     //--------------------------------
@@ -258,6 +262,48 @@
     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 @@
 
         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 @@
         }
     }
 
+    /**
+     * 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 @@
 
     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 @@
     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 c9d4650..8caa07a 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -423,6 +423,18 @@
  *     <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 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 60ff264..c5250d7 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -292,7 +292,7 @@
     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 @@
     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 @@
     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 @@
     {"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 2118f8f..0f2093a 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -92,7 +92,8 @@
     : 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 @@
     : 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 71c5f86..1ae222e 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -58,7 +58,7 @@
 
     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 @@
                 data.writeString8(headers->valueAt(i));
             }
         }
+        data.writeInt32(audioSessionId);
 
         remote()->transact(CREATE_URL, data, &reply);
+
         return interface_cast<IMediaPlayer>(reply.readStrongBinder());
     }
 
@@ -89,7 +91,8 @@
         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 @@
         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 @@
                 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 @@
             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 c6bbbcc..d5a3c13 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -55,6 +55,7 @@
     mLeftVolume = mRightVolume = 1.0;
     mVideoWidth = mVideoHeight = 0;
     mLockThreadId = 0;
+    mAudioSessionId = AudioSystem::newAudioSessionId();
 }
 
 MediaPlayer::~MediaPlayer()
@@ -137,7 +138,7 @@
         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 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 @@
     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 d7ca635..d45c17b 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -252,11 +252,12 @@
 
 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(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 @@
 }
 
 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 @@
     mClient = client;
     mLoop = false;
     mStatus = NO_INIT;
+    mAudioSessionId = audioSessionId;
+
 #if CALLBACK_ANTAGONIZER
     LOGD("create Antagonizer");
     mAntagonizer = new Antagonizer(notify, this);
@@ -871,7 +874,7 @@
         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 @@
     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 @@
 
 #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 @@
         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 @@
                 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 2408c62..60b91c6 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -65,7 +65,7 @@
     class AudioOutput : public MediaPlayerBase::AudioSink
     {
     public:
-                                AudioOutput();
+                                AudioOutput(int sessionId);
         virtual                 ~AudioOutput();
 
         virtual bool            ready() const { return mTrack != NULL; }
@@ -108,6 +108,7 @@
         float                   mRightVolume;
         float                   mMsecsPerFrame;
         uint32_t                mLatency;
+        int                     mSessionId;
 
         static bool             mIsOnEmulator;
         static int              mMinBufferCount;  // 12 for emulator; otherwise 4
@@ -185,9 +186,9 @@
     // 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 @@
                 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 @@
                     status_t                    mStatus;
                     bool                        mLoop;
                     int32_t                     mConnId;
+                    int                         mAudioSessionId;
 
         // Metadata filters.
         media::Metadata::Filter mMetadataAllow;  // protected by mLock