am bf14c62e: am 72bf901c: Merge "audio policy: new getOutputForAttr() prototype." into lmp-mr1-dev

* commit 'bf14c62e7973ed793a3b00c2c67beca4484c1c7a':
  audio policy: new getOutputForAttr() prototype.
diff --git a/include/media/AudioPolicyHelper.h b/include/media/AudioPolicyHelper.h
index f4afd45..3ed0b74 100644
--- a/include/media/AudioPolicyHelper.h
+++ b/include/media/AudioPolicyHelper.h
@@ -18,7 +18,7 @@
 
 #include <system/audio.h>
 
-audio_stream_type_t audio_attributes_to_stream_type(const audio_attributes_t *attr)
+static audio_stream_type_t audio_attributes_to_stream_type(const audio_attributes_t *attr)
 {
     // flags to stream type mapping
     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
@@ -61,4 +61,55 @@
     }
 }
 
+static void stream_type_to_audio_attributes(audio_stream_type_t streamType,
+                                     audio_attributes_t *attr) {
+    attr->flags = 0x0;
+
+    switch (streamType) {
+    case AUDIO_STREAM_DEFAULT:
+    case AUDIO_STREAM_MUSIC:
+        attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
+        attr->usage = AUDIO_USAGE_MEDIA;
+        break;
+    case AUDIO_STREAM_VOICE_CALL:
+        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
+        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+        break;
+    case AUDIO_STREAM_ENFORCED_AUDIBLE:
+        attr->flags  |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
+        // intended fall through, attributes in common with STREAM_SYSTEM
+    case AUDIO_STREAM_SYSTEM:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+        break;
+    case AUDIO_STREAM_RING:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+        break;
+    case AUDIO_STREAM_ALARM:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_ALARM;
+        break;
+    case AUDIO_STREAM_NOTIFICATION:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_NOTIFICATION;
+        break;
+    case AUDIO_STREAM_BLUETOOTH_SCO:
+        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
+        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+        attr->flags |= AUDIO_FLAG_SCO;
+        break;
+    case AUDIO_STREAM_DTMF:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+        break;
+    case AUDIO_STREAM_TTS:
+        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
+        attr->usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+        break;
+    default:
+        ALOGE("invalid stream type %d when converting to attributes", streamType);
+    }
+}
+
 #endif //AUDIO_POLICY_HELPER_H_
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 1614525..7f1afb3 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -215,7 +215,10 @@
                                         audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO,
                                         audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                         const audio_offload_info_t *offloadInfo = NULL);
-    static audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
+    static status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
                                         uint32_t samplingRate = 0,
                                         audio_format_t format = AUDIO_FORMAT_DEFAULT,
                                         audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO,
@@ -223,11 +226,13 @@
                                         const audio_offload_info_t *offloadInfo = NULL);
     static status_t startOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session);
+                                audio_session_t session);
     static status_t stopOutput(audio_io_handle_t output,
                                audio_stream_type_t stream,
-                               int session);
-    static void releaseOutput(audio_io_handle_t output);
+                               audio_session_t session);
+    static void releaseOutput(audio_io_handle_t output,
+                              audio_stream_type_t stream,
+                              audio_session_t session);
 
     // Client must successfully hand off the handle reference to AudioFlinger via openRecord(),
     // or release it with releaseInput().
@@ -235,7 +240,7 @@
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int sessionId,
+                                    audio_session_t sessionId,
                                     audio_input_flags_t);
 
     static status_t startInput(audio_io_handle_t input,
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index b5256f0..fd51b8f 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -239,6 +239,9 @@
      * Parameters not listed in the AudioTrack constructors above:
      *
      * threadCanCallJava:  Whether callbacks are made from an attached thread and thus can call JNI.
+     *
+     * Internal state post condition:
+     *      (mStreamType == AUDIO_STREAM_DEFAULT) implies this AudioTrack has valid attributes
      */
             status_t    set(audio_stream_type_t streamType,
                             uint32_t sampleRate,
@@ -273,7 +276,7 @@
 
     /* getters, see constructors and set() */
 
-            audio_stream_type_t streamType() const { return mStreamType; }
+            audio_stream_type_t streamType() const;
             audio_format_t format() const   { return mFormat; }
 
     /* Return frame size in bytes, which for linear PCM is
@@ -598,9 +601,6 @@
             AudioTrack& operator = (const AudioTrack& other);
 
             void        setAttributesFromStreamType(audio_stream_type_t streamType);
-            void        setStreamTypeFromAttributes(audio_attributes_t& aa);
-    /* paa is guaranteed non-NULL */
-            bool        isValidAttributes(const audio_attributes_t *paa);
 
     /* a small internal class to handle the callback */
     class AudioTrackThread : public Thread
@@ -688,7 +688,8 @@
 
     // constant after constructor or set()
     audio_format_t          mFormat;                // as requested by client, not forced to 16-bit
-    audio_stream_type_t     mStreamType;
+    audio_stream_type_t     mStreamType;            // mStreamType == AUDIO_STREAM_DEFAULT implies
+                                                    // this AudioTrack has valid attributes
     uint32_t                mChannelCount;
     audio_channel_mask_t    mChannelMask;
     sp<IMemory>             mSharedBuffer;
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 16fe9cf..2f30304 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -56,24 +56,29 @@
                                         audio_channel_mask_t channelMask = 0,
                                         audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                         const audio_offload_info_t *offloadInfo = NULL) = 0;
-    virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                            uint32_t samplingRate = 0,
-                                            audio_format_t format = AUDIO_FORMAT_DEFAULT,
-                                            audio_channel_mask_t channelMask = 0,
-                                            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                                            const audio_offload_info_t *offloadInfo = NULL) = 0;
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate = 0,
+                                        audio_format_t format = AUDIO_FORMAT_DEFAULT,
+                                        audio_channel_mask_t channelMask = 0,
+                                        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+                                        const audio_offload_info_t *offloadInfo = NULL) = 0;
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session = 0) = 0;
+                                 audio_session_t session) = 0;
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session = 0) = 0;
-    virtual void releaseOutput(audio_io_handle_t output) = 0;
+                                audio_session_t session) = 0;
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session) = 0;
     virtual audio_io_handle_t getInput(audio_source_t inputSource,
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int audioSession,
+                                    audio_session_t audioSession,
                                     audio_input_flags_t flags) = 0;
     virtual status_t startInput(audio_io_handle_t input,
                                 audio_session_t session) = 0;
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 9d92cfe..5b5fe5d 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -445,7 +445,7 @@
     }
 
     audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat,
-            mChannelMask, mSessionId, mFlags);
+            mChannelMask, (audio_session_t)mSessionId, mFlags);
     if (input == AUDIO_IO_HANDLE_NONE) {
         ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, "
               "channel mask %#x, session %d, flags %#x",
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 1f8e9b6..5f42f25 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -649,22 +649,26 @@
     return aps->getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
 }
 
-audio_io_handle_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate,
+                                        audio_format_t format,
+                                        audio_channel_mask_t channelMask,
+                                        audio_output_flags_t flags,
+                                        const audio_offload_info_t *offloadInfo)
 {
-    if (attr == NULL) return 0;
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
-    if (aps == 0) return 0;
-    return aps->getOutputForAttr(attr, samplingRate, format, channelMask, flags, offloadInfo);
+    if (aps == 0) return NO_INIT;
+    return aps->getOutputForAttr(attr, output, session, stream,
+                                 samplingRate, format, channelMask,
+                                 flags, offloadInfo);
 }
 
 status_t AudioSystem::startOutput(audio_io_handle_t output,
                                   audio_stream_type_t stream,
-                                  int session)
+                                  audio_session_t session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
@@ -673,25 +677,27 @@
 
 status_t AudioSystem::stopOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session)
+                                 audio_session_t session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
     return aps->stopOutput(output, stream, session);
 }
 
-void AudioSystem::releaseOutput(audio_io_handle_t output)
+void AudioSystem::releaseOutput(audio_io_handle_t output,
+                                audio_stream_type_t stream,
+                                audio_session_t session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return;
-    aps->releaseOutput(output);
+    aps->releaseOutput(output, stream, session);
 }
 
 audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource,
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int sessionId,
+                                    audio_session_t sessionId,
                                     audio_input_flags_t flags)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ca79f25..6f09cbc 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -28,6 +28,7 @@
 #include <utils/Log.h>
 #include <private/media/AudioTrackShared.h>
 #include <media/IAudioFlinger.h>
+#include <media/AudioPolicyHelper.h>
 #include <media/AudioResamplerPublic.h>
 
 #define WAIT_PERIOD_MS                  10
@@ -278,30 +279,22 @@
     }
 
     // handle default values first.
-    // TODO once AudioPolicyManager fully supports audio_attributes_t,
-    //   remove stream "text-to-speech" redirect
-    if ((streamType == AUDIO_STREAM_DEFAULT) || (streamType == AUDIO_STREAM_TTS)) {
+    if (streamType == AUDIO_STREAM_DEFAULT) {
         streamType = AUDIO_STREAM_MUSIC;
     }
-
     if (pAttributes == NULL) {
         if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
             ALOGE("Invalid stream type %d", streamType);
             return BAD_VALUE;
         }
-        setAttributesFromStreamType(streamType);
         mStreamType = streamType;
+
     } else {
-        if (!isValidAttributes(pAttributes)) {
-            ALOGE("Invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
-                pAttributes->usage, pAttributes->content_type, pAttributes->flags,
-                pAttributes->tags);
-        }
         // stream type shouldn't be looked at, this track has audio attributes
         memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
-        setStreamTypeFromAttributes(mAttributes);
         ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]",
                 mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
+        mStreamType = AUDIO_STREAM_DEFAULT;
     }
 
     // these below should probably come from the audioFlinger too...
@@ -341,10 +334,6 @@
                 // FIXME why can't we allow direct AND fast?
                 ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST);
     }
-    // only allow deep buffering for music stream type
-    if (mStreamType != AUDIO_STREAM_MUSIC) {
-        flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
-    }
 
     if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
         if (audio_is_linear_pcm(format)) {
@@ -914,24 +903,38 @@
     return status;
 }
 
+audio_stream_type_t AudioTrack::streamType() const
+{
+    if (mStreamType == AUDIO_STREAM_DEFAULT) {
+        return audio_attributes_to_stream_type(&mAttributes);
+    }
+    return mStreamType;
+}
+
 // -------------------------------------------------------------------------
 
 // must be called with mLock held
 status_t AudioTrack::createTrack_l()
 {
-    status_t status;
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     if (audioFlinger == 0) {
         ALOGE("Could not get audioflinger");
         return NO_INIT;
     }
 
-    audio_io_handle_t output = AudioSystem::getOutputForAttr(&mAttributes, mSampleRate, mFormat,
-            mChannelMask, mFlags, mOffloadInfo);
-    if (output == AUDIO_IO_HANDLE_NONE) {
+    audio_io_handle_t output;
+    audio_stream_type_t streamType = mStreamType;
+    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
+    status_t status = AudioSystem::getOutputForAttr(attr, &output,
+                                                    (audio_session_t)mSessionId, &streamType,
+                                                    mSampleRate, mFormat, mChannelMask,
+                                                    mFlags, mOffloadInfo);
+
+
+    if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
         ALOGE("Could not get audio output for stream type %d, usage %d, sample rate %u, format %#x,"
               " channel mask %#x, flags %#x",
-              mStreamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
+              streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
         return BAD_VALUE;
     }
     {
@@ -1085,7 +1088,7 @@
 
     size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
                                 // but we will still need the original value also
-    sp<IAudioTrack> track = audioFlinger->createTrack(mStreamType,
+    sp<IAudioTrack> track = audioFlinger->createTrack(streamType,
                                                       mSampleRate,
                                                       // AudioFlinger only sees 16-bit PCM
                                                       mFormat == AUDIO_FORMAT_PCM_8_BIT &&
@@ -1231,7 +1234,7 @@
     }
 
 release:
-    AudioSystem::releaseOutput(output);
+    AudioSystem::releaseOutput(output, streamType, (audio_session_t)mSessionId);
     if (status == NO_ERROR) {
         status = NO_INIT;
     }
@@ -2065,161 +2068,6 @@
     return mProxy->getUnderrunFrames();
 }
 
-void AudioTrack::setAttributesFromStreamType(audio_stream_type_t streamType) {
-    mAttributes.flags = 0x0;
-
-    switch(streamType) {
-    case AUDIO_STREAM_DEFAULT:
-    case AUDIO_STREAM_MUSIC:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
-        mAttributes.usage = AUDIO_USAGE_MEDIA;
-        break;
-    case AUDIO_STREAM_VOICE_CALL:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
-        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
-        break;
-    case AUDIO_STREAM_ENFORCED_AUDIBLE:
-        mAttributes.flags  |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
-        // intended fall through, attributes in common with STREAM_SYSTEM
-    case AUDIO_STREAM_SYSTEM:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
-        break;
-    case AUDIO_STREAM_RING:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
-        break;
-    case AUDIO_STREAM_ALARM:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_ALARM;
-        break;
-    case AUDIO_STREAM_NOTIFICATION:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_NOTIFICATION;
-        break;
-    case AUDIO_STREAM_BLUETOOTH_SCO:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
-        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
-        mAttributes.flags |= AUDIO_FLAG_SCO;
-        break;
-    case AUDIO_STREAM_DTMF:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
-        break;
-    case AUDIO_STREAM_TTS:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
-        mAttributes.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
-        break;
-    default:
-        ALOGE("invalid stream type %d when converting to attributes", streamType);
-    }
-}
-
-void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) {
-    // flags to stream type mapping
-    if ((aa.flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
-        mStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;
-        return;
-    }
-    if ((aa.flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
-        mStreamType = AUDIO_STREAM_BLUETOOTH_SCO;
-        return;
-    }
-    // TODO once AudioPolicyManager fully supports audio_attributes_t,
-    //   remove stream remap, the flag will be enough
-    if ((aa.flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
-        mStreamType = AUDIO_STREAM_TTS;
-        return;
-    }
-
-    // usage to stream type mapping
-    switch (aa.usage) {
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: {
-        // TODO once AudioPolicyManager fully supports audio_attributes_t,
-        //   remove stream change based on stream activity
-        bool active;
-        status_t status = AudioSystem::isStreamActive(AUDIO_STREAM_RING, &active, 0);
-        if (status == NO_ERROR && active == true) {
-            mStreamType = AUDIO_STREAM_RING;
-            break;
-        }
-        status = AudioSystem::isStreamActive(AUDIO_STREAM_ALARM, &active, 0);
-        if (status == NO_ERROR && active == true) {
-            mStreamType = AUDIO_STREAM_ALARM;
-            break;
-        }
-        audio_mode_t phoneState = AudioSystem::getPhoneState();
-        if (phoneState == AUDIO_MODE_IN_CALL || phoneState == AUDIO_MODE_IN_COMMUNICATION) {
-            mStreamType = AUDIO_STREAM_VOICE_CALL;
-            break;
-        }
-    }    /// FALL THROUGH
-    case AUDIO_USAGE_MEDIA:
-    case AUDIO_USAGE_GAME:
-    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-        mStreamType = AUDIO_STREAM_MUSIC;
-        return;
-    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
-        mStreamType = AUDIO_STREAM_SYSTEM;
-        return;
-    case AUDIO_USAGE_VOICE_COMMUNICATION:
-        mStreamType = AUDIO_STREAM_VOICE_CALL;
-        return;
-
-    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
-        mStreamType = AUDIO_STREAM_DTMF;
-        return;
-
-    case AUDIO_USAGE_ALARM:
-        mStreamType = AUDIO_STREAM_ALARM;
-        return;
-    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
-        mStreamType = AUDIO_STREAM_RING;
-        return;
-
-    case AUDIO_USAGE_NOTIFICATION:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-    case AUDIO_USAGE_NOTIFICATION_EVENT:
-        mStreamType = AUDIO_STREAM_NOTIFICATION;
-        return;
-
-    case AUDIO_USAGE_UNKNOWN:
-    default:
-        mStreamType = AUDIO_STREAM_MUSIC;
-    }
-}
-
-bool AudioTrack::isValidAttributes(const audio_attributes_t *paa) {
-    // has flags that map to a strategy?
-    if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
-        return true;
-    }
-
-    // has known usage?
-    switch (paa->usage) {
-    case AUDIO_USAGE_UNKNOWN:
-    case AUDIO_USAGE_MEDIA:
-    case AUDIO_USAGE_VOICE_COMMUNICATION:
-    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
-    case AUDIO_USAGE_ALARM:
-    case AUDIO_USAGE_NOTIFICATION:
-    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-    case AUDIO_USAGE_NOTIFICATION_EVENT:
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
-    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
-    case AUDIO_USAGE_GAME:
-        break;
-    default:
-        return false;
-    }
-    return true;
-}
 // =========================================================================
 
 void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 9349662..a381dff 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -160,21 +160,45 @@
         return static_cast <audio_io_handle_t> (reply.readInt32());
     }
 
-    virtual audio_io_handle_t getOutputForAttr(
-                                            const audio_attributes_t *attr,
-                                            uint32_t samplingRate,
-                                            audio_format_t format,
-                                            audio_channel_mask_t channelMask,
-                                            audio_output_flags_t flags,
-                                            const audio_offload_info_t *offloadInfo)
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate,
+                                        audio_format_t format,
+                                        audio_channel_mask_t channelMask,
+                                        audio_output_flags_t flags,
+                                        const audio_offload_info_t *offloadInfo)
         {
             Parcel data, reply;
             data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
             if (attr == NULL) {
-                ALOGE("Writing NULL audio attributes - shouldn't happen");
-                return (audio_io_handle_t) 0;
+                if (stream == NULL) {
+                    ALOGE("getOutputForAttr(): NULL audio attributes and stream type");
+                    return BAD_VALUE;
+                }
+                if (*stream == AUDIO_STREAM_DEFAULT) {
+                    ALOGE("getOutputForAttr unspecified stream type");
+                    return BAD_VALUE;
+                }
             }
-            data.write(attr, sizeof(audio_attributes_t));
+            if (output == NULL) {
+                ALOGE("getOutputForAttr NULL output - shouldn't happen");
+                return BAD_VALUE;
+            }
+            if (attr == NULL) {
+                data.writeInt32(0);
+            } else {
+                data.writeInt32(1);
+                data.write(attr, sizeof(audio_attributes_t));
+            }
+            data.writeInt32(session);
+            if (stream == NULL) {
+                data.writeInt32(0);
+            } else {
+                data.writeInt32(1);
+                data.writeInt32(*stream);
+            }
             data.writeInt32(samplingRate);
             data.writeInt32(static_cast <uint32_t>(format));
             data.writeInt32(channelMask);
@@ -186,41 +210,56 @@
                 data.writeInt32(1);
                 data.write(offloadInfo, sizeof(audio_offload_info_t));
             }
-            remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply);
-            return static_cast <audio_io_handle_t> (reply.readInt32());
+            status_t status = remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = (status_t)reply.readInt32();
+            if (status != NO_ERROR) {
+                return status;
+            }
+            *output = (audio_io_handle_t)reply.readInt32();
+            if (stream != NULL) {
+                *stream = (audio_stream_type_t)reply.readInt32();
+            }
+            return status;
         }
 
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session)
+                                 audio_session_t session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
         data.writeInt32((int32_t) stream);
-        data.writeInt32(session);
+        data.writeInt32((int32_t)session);
         remote()->transact(START_OUTPUT, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
 
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session)
+                                audio_session_t session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
         data.writeInt32((int32_t) stream);
-        data.writeInt32(session);
+        data.writeInt32((int32_t)session);
         remote()->transact(STOP_OUTPUT, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
 
-    virtual void releaseOutput(audio_io_handle_t output)
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
+        data.writeInt32((int32_t)stream);
+        data.writeInt32((int32_t)session);
         remote()->transact(RELEASE_OUTPUT, data, &reply);
     }
 
@@ -229,7 +268,7 @@
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int audioSession,
+                                    audio_session_t audioSession,
                                     audio_input_flags_t flags)
     {
         Parcel data, reply;
@@ -238,7 +277,7 @@
         data.writeInt32(samplingRate);
         data.writeInt32(static_cast <uint32_t>(format));
         data.writeInt32(channelMask);
-        data.writeInt32(audioSession);
+        data.writeInt32((int32_t)audioSession);
         data.writeInt32(flags);
         remote()->transact(GET_INPUT, data, &reply);
         return static_cast <audio_io_handle_t> (reply.readInt32());
@@ -706,7 +745,16 @@
         case GET_OUTPUT_FOR_ATTR: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_attributes_t attr;
-            data.read(&attr, sizeof(audio_attributes_t));
+            bool hasAttributes = data.readInt32() != 0;
+            if (hasAttributes) {
+                data.read(&attr, sizeof(audio_attributes_t));
+            }
+            audio_session_t session = (audio_session_t)data.readInt32();
+            audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
+            bool hasStream = data.readInt32() != 0;
+            if (hasStream) {
+                stream = (audio_stream_type_t)data.readInt32();
+            }
             uint32_t samplingRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
@@ -717,13 +765,14 @@
             if (hasOffloadInfo) {
                 data.read(&offloadInfo, sizeof(audio_offload_info_t));
             }
-            audio_io_handle_t output = getOutputForAttr(&attr,
-                    samplingRate,
-                    format,
-                    channelMask,
-                    flags,
-                    hasOffloadInfo ? &offloadInfo : NULL);
-            reply->writeInt32(static_cast <int>(output));
+            audio_io_handle_t output;
+            status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
+                    &output, session, &stream,
+                    samplingRate, format, channelMask,
+                    flags, hasOffloadInfo ? &offloadInfo : NULL);
+            reply->writeInt32(status);
+            reply->writeInt32(output);
+            reply->writeInt32(stream);
             return NO_ERROR;
         } break;
 
@@ -732,7 +781,7 @@
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
             audio_stream_type_t stream =
                                 static_cast <audio_stream_type_t>(data.readInt32());
-            int session = data.readInt32();
+            audio_session_t session = (audio_session_t)data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(startOutput(output,
                                                                  stream,
                                                                  session)));
@@ -744,7 +793,7 @@
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
             audio_stream_type_t stream =
                                 static_cast <audio_stream_type_t>(data.readInt32());
-            int session = data.readInt32();
+            audio_session_t session = (audio_session_t)data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(stopOutput(output,
                                                                 stream,
                                                                 session)));
@@ -754,7 +803,9 @@
         case RELEASE_OUTPUT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
-            releaseOutput(output);
+            audio_stream_type_t stream = (audio_stream_type_t)data.readInt32();
+            audio_session_t session = (audio_session_t)data.readInt32();
+            releaseOutput(output, stream, session);
             return NO_ERROR;
         } break;
 
@@ -764,7 +815,7 @@
             uint32_t samplingRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
-            int audioSession = data.readInt32();
+            audio_session_t audioSession = (audio_session_t)data.readInt32();
             audio_input_flags_t flags = (audio_input_flags_t) data.readInt32();
             audio_io_handle_t input = getInput(inputSource,
                                                samplingRate,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index cbb64c8..b95bb77 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1622,13 +1622,15 @@
         if (track->isExternalTrack()) {
             TrackBase::track_state state = track->mState;
             mLock.unlock();
-            status = AudioSystem::startOutput(mId, track->streamType(), track->sessionId());
+            status = AudioSystem::startOutput(mId, track->streamType(),
+                                              (audio_session_t)track->sessionId());
             mLock.lock();
             // abort track was stopped/paused while we released the lock
             if (state != track->mState) {
                 if (status == NO_ERROR) {
                     mLock.unlock();
-                    AudioSystem::stopOutput(mId, track->streamType(), track->sessionId());
+                    AudioSystem::stopOutput(mId, track->streamType(),
+                                            (audio_session_t)track->sessionId());
                     mLock.lock();
                 }
                 return INVALID_OPERATION;
@@ -2057,13 +2059,15 @@
         for (size_t i = 0 ; i < count ; i++) {
             const sp<Track>& track = tracksToRemove.itemAt(i);
             if (track->isExternalTrack()) {
-                AudioSystem::stopOutput(mId, track->streamType(), track->sessionId());
+                AudioSystem::stopOutput(mId, track->streamType(),
+                                        (audio_session_t)track->sessionId());
 #ifdef ADD_BATTERY_DATA
                 // to track the speaker usage
                 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
 #endif
                 if (track->isTerminated()) {
-                    AudioSystem::releaseOutput(mId);
+                    AudioSystem::releaseOutput(mId, track->streamType(),
+                                               (audio_session_t)track->sessionId());
                 }
             }
         }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index aa708ec..fcbf8f8 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -491,7 +491,7 @@
             wasActive = playbackThread->destroyTrack_l(this);
         }
         if (isExternalTrack() && !wasActive) {
-            AudioSystem::releaseOutput(mThreadIoHandle);
+            AudioSystem::releaseOutput(mThreadIoHandle, mStreamType, (audio_session_t)mSessionId);
         }
     }
 }
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 5524463..f7ffb6d 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -90,22 +90,27 @@
                                         audio_channel_mask_t channelMask,
                                         audio_output_flags_t flags,
                                         const audio_offload_info_t *offloadInfo) = 0;
-    virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                                uint32_t samplingRate,
-                                                audio_format_t format,
-                                                audio_channel_mask_t channelMask,
-                                                audio_output_flags_t flags,
-                                                const audio_offload_info_t *offloadInfo) = 0;
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate,
+                                        audio_format_t format,
+                                        audio_channel_mask_t channelMask,
+                                        audio_output_flags_t flags,
+                                        const audio_offload_info_t *offloadInfo) = 0;
     // indicates to the audio policy manager that the output starts being used by corresponding stream.
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session = 0) = 0;
+                                 audio_session_t session) = 0;
     // indicates to the audio policy manager that the output stops being used by corresponding stream.
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session = 0) = 0;
+                                audio_session_t session) = 0;
     // releases the output.
-    virtual void releaseOutput(audio_io_handle_t output) = 0;
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session) = 0;
 
     // request an input appropriate for record from the supplied device with supplied parameters.
     virtual audio_io_handle_t getInput(audio_source_t inputSource,
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index 710a905..8b64d5b 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -141,25 +141,28 @@
                                     format, channelMask, flags, offloadInfo);
 }
 
-audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session,
+                                              audio_stream_type_t *stream,
+                                              uint32_t samplingRate,
+                                              audio_format_t format,
+                                              audio_channel_mask_t channelMask,
+                                              audio_output_flags_t flags,
+                                              const audio_offload_info_t *offloadInfo)
 {
     if (mAudioPolicyManager == NULL) {
-        return 0;
+        return NO_INIT;
     }
     ALOGV("getOutput()");
     Mutex::Autolock _l(mLock);
-    return mAudioPolicyManager->getOutputForAttr(attr, samplingRate,
+    return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, samplingRate,
                                     format, channelMask, flags, offloadInfo);
 }
 
 status_t AudioPolicyService::startOutput(audio_io_handle_t output,
                                          audio_stream_type_t stream,
-                                         int session)
+                                         audio_session_t session)
 {
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         return BAD_VALUE;
@@ -186,7 +189,7 @@
 
 status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
                                         audio_stream_type_t stream,
-                                        int session)
+                                        audio_session_t session)
 {
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         return BAD_VALUE;
@@ -201,7 +204,7 @@
 
 status_t  AudioPolicyService::doStopOutput(audio_io_handle_t output,
                                       audio_stream_type_t stream,
-                                      int session)
+                                      audio_session_t session)
 {
     ALOGV("doStopOutput from tid %d", gettid());
     sp<AudioPolicyEffects>audioPolicyEffects;
@@ -220,27 +223,31 @@
     return mAudioPolicyManager->stopOutput(output, stream, session);
 }
 
-void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+void AudioPolicyService::releaseOutput(audio_io_handle_t output,
+                                       audio_stream_type_t stream,
+                                       audio_session_t session)
 {
     if (mAudioPolicyManager == NULL) {
         return;
     }
     ALOGV("releaseOutput()");
-    mOutputCommandThread->releaseOutputCommand(output);
+    mOutputCommandThread->releaseOutputCommand(output, stream, session);
 }
 
-void AudioPolicyService::doReleaseOutput(audio_io_handle_t output)
+void AudioPolicyService::doReleaseOutput(audio_io_handle_t output,
+                                         audio_stream_type_t stream,
+                                         audio_session_t session)
 {
     ALOGV("doReleaseOutput from tid %d", gettid());
     Mutex::Autolock _l(mLock);
-    mAudioPolicyManager->releaseOutput(output);
+    mAudioPolicyManager->releaseOutput(output, stream, session);
 }
 
 audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource,
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int audioSession,
+                                    audio_session_t audioSession,
                                     audio_input_flags_t flags)
 {
     if (mAudioPolicyManager == NULL) {
@@ -263,7 +270,7 @@
         // the audio_in_acoustics_t parameter is ignored by get_input()
         input = mAudioPolicyManager->getInput(inputSource, samplingRate,
                                                        format, channelMask,
-                                                       (audio_session_t)audioSession, flags);
+                                                       audioSession, flags);
         audioPolicyEffects = mAudioPolicyEffects;
     }
     if (input == 0) {
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index ac61cb2..694dea3 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -148,7 +148,7 @@
 
 status_t AudioPolicyService::startOutput(audio_io_handle_t output,
                                          audio_stream_type_t stream,
-                                         int session)
+                                         audio_session_t session)
 {
     if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
@@ -176,7 +176,7 @@
 
 status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
                                         audio_stream_type_t stream,
-                                        int session)
+                                        audio_session_t session)
 {
     if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
@@ -191,7 +191,7 @@
 
 status_t  AudioPolicyService::doStopOutput(audio_io_handle_t output,
                                       audio_stream_type_t stream,
-                                      int session)
+                                      audio_session_t session)
 {
     ALOGV("doStopOutput from tid %d", gettid());
     // release audio processors from the stream
@@ -210,16 +210,20 @@
     return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session);
 }
 
-void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+void AudioPolicyService::releaseOutput(audio_io_handle_t output,
+                                       audio_stream_type_t stream,
+                                       audio_session_t session)
 {
     if (mpAudioPolicy == NULL) {
         return;
     }
     ALOGV("releaseOutput()");
-    mOutputCommandThread->releaseOutputCommand(output);
+    mOutputCommandThread->releaseOutputCommand(output, stream, session);
 }
 
-void AudioPolicyService::doReleaseOutput(audio_io_handle_t output)
+void AudioPolicyService::doReleaseOutput(audio_io_handle_t output,
+                                         audio_stream_type_t stream __unused,
+                                         audio_session_t session __unused)
 {
     ALOGV("doReleaseOutput from tid %d", gettid());
     Mutex::Autolock _l(mLock);
@@ -230,7 +234,7 @@
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int audioSession,
+                                    audio_session_t audioSession,
                                     audio_input_flags_t flags __unused)
 {
     if (mpAudioPolicy == NULL) {
@@ -549,16 +553,29 @@
     return INVALID_OPERATION;
 }
 
-audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session,
+                                              audio_stream_type_t *stream,
+                                              uint32_t samplingRate,
+                                              audio_format_t format,
+                                              audio_channel_mask_t channelMask,
+                                              audio_output_flags_t flags,
+                                              const audio_offload_info_t *offloadInfo)
 {
-    audio_stream_type_t stream = audio_attributes_to_stream_type(attr);
-
-    return getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
+    if (attr != NULL) {
+        *stream = audio_attributes_to_stream_type(attr);
+    } else {
+        if (*stream == AUDIO_STREAM_DEFAULT) {
+            return BAD_VALUE;
+        }
+    }
+    *output = getOutput(*stream, samplingRate, format, channelMask,
+                                          flags, offloadInfo);
+    if (*output == AUDIO_IO_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
 }
 
 status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session __unused,
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 1631d6c..8ca0b96 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -43,6 +43,7 @@
 #include <hardware/audio.h>
 #include <hardware/audio_effect.h>
 #include <media/AudioParameter.h>
+#include <media/AudioPolicyHelper.h>
 #include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
 #include "audio_policy_conf.h"
@@ -841,42 +842,65 @@
     ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x",
           device, stream, samplingRate, format, channelMask, flags);
 
-    return getOutputForDevice(device, stream, samplingRate,format, channelMask, flags,
-            offloadInfo);
+    return getOutputForDevice(device, AUDIO_SESSION_ALLOCATE,
+                              stream, samplingRate,format, channelMask,
+                              flags, offloadInfo);
 }
 
-audio_io_handle_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session,
+                                              audio_stream_type_t *stream,
+                                              uint32_t samplingRate,
+                                              audio_format_t format,
+                                              audio_channel_mask_t channelMask,
+                                              audio_output_flags_t flags,
+                                              const audio_offload_info_t *offloadInfo)
 {
-    if (attr == NULL) {
-        ALOGE("getOutputForAttr() called with NULL audio attributes");
-        return 0;
+    audio_attributes_t attributes;
+    if (attr != NULL) {
+        if (!isValidAttributes(attr)) {
+            ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
+                  attr->usage, attr->content_type, attr->flags,
+                  attr->tags);
+            return BAD_VALUE;
+        }
+        attributes = *attr;
+    } else {
+        if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) {
+            ALOGE("getOutputForAttr():  invalid stream type");
+            return BAD_VALUE;
+        }
+        stream_type_to_audio_attributes(*stream, &attributes);
     }
+
     ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x",
-            attr->usage, attr->content_type, attr->tags, attr->flags);
+            attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
 
     // TODO this is where filtering for custom policies (rerouting, dynamic sources) will go
-    routing_strategy strategy = (routing_strategy) getStrategyForAttr(attr);
+    routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
 
-    if ((attr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
+    if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
     }
 
     ALOGV("getOutputForAttr() device 0x%x, samplingRate %d, format %x, channelMask %x, flags %x",
           device, samplingRate, format, channelMask, flags);
 
-    audio_stream_type_t stream = streamTypefromAttributesInt(attr);
-    return getOutputForDevice(device, stream, samplingRate, format, channelMask, flags,
-                offloadInfo);
+    *stream = streamTypefromAttributesInt(&attributes);
+    *output = getOutputForDevice(device, session, *stream,
+                                 samplingRate, format, channelMask,
+                                 flags, offloadInfo);
+    if (*output == AUDIO_IO_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
 }
 
 audio_io_handle_t AudioPolicyManager::getOutputForDevice(
         audio_devices_t device,
+        audio_session_t session,
         audio_stream_type_t stream,
         uint32_t samplingRate,
         audio_format_t format,
@@ -939,6 +963,10 @@
     if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
     }
+    // only allow deep buffering for music stream type
+    if (stream != AUDIO_STREAM_MUSIC) {
+        flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+    }
 
     sp<IOProfile> profile;
 
@@ -1123,7 +1151,7 @@
 
 status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
                                              audio_stream_type_t stream,
-                                             int session)
+                                             audio_session_t session)
 {
     ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
     ssize_t index = mOutputs.indexOfKey(output);
@@ -1207,7 +1235,7 @@
 
 status_t AudioPolicyManager::stopOutput(audio_io_handle_t output,
                                             audio_stream_type_t stream,
-                                            int session)
+                                            audio_session_t session)
 {
     ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
     ssize_t index = mOutputs.indexOfKey(output);
@@ -1265,7 +1293,9 @@
     }
 }
 
-void AudioPolicyManager::releaseOutput(audio_io_handle_t output)
+void AudioPolicyManager::releaseOutput(audio_io_handle_t output,
+                                       audio_stream_type_t stream,
+                                       audio_session_t session)
 {
     ALOGV("releaseOutput() %d", output);
     ssize_t index = mOutputs.indexOfKey(output);
@@ -7494,6 +7524,15 @@
     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
         return AUDIO_STREAM_MUSIC;
     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+        if (isStreamActive(AUDIO_STREAM_ALARM)) {
+            return AUDIO_STREAM_ALARM;
+        }
+        if (isStreamActive(AUDIO_STREAM_RING)) {
+            return AUDIO_STREAM_RING;
+        }
+        if (isInCall()) {
+            return AUDIO_STREAM_VOICE_CALL;
+        }
         return AUDIO_STREAM_ACCESSIBILITY;
     case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
         return AUDIO_STREAM_SYSTEM;
@@ -7520,4 +7559,35 @@
         return AUDIO_STREAM_MUSIC;
     }
 }
+
+bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) {
+    // has flags that map to a strategy?
+    if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
+        return true;
+    }
+
+    // has known usage?
+    switch (paa->usage) {
+    case AUDIO_USAGE_UNKNOWN:
+    case AUDIO_USAGE_MEDIA:
+    case AUDIO_USAGE_VOICE_COMMUNICATION:
+    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+    case AUDIO_USAGE_ALARM:
+    case AUDIO_USAGE_NOTIFICATION:
+    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+    case AUDIO_USAGE_NOTIFICATION_EVENT:
+    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+    case AUDIO_USAGE_GAME:
+        break;
+    default:
+        return false;
+    }
+    return true;
+}
+
 }; // namespace android
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index 7af6475..6eb2163 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -87,19 +87,24 @@
                                             audio_channel_mask_t channelMask,
                                             audio_output_flags_t flags,
                                             const audio_offload_info_t *offloadInfo);
-        virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                            uint32_t samplingRate,
-                                            audio_format_t format,
-                                            audio_channel_mask_t channelMask,
-                                            audio_output_flags_t flags,
-                                            const audio_offload_info_t *offloadInfo);
+        virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                          audio_io_handle_t *output,
+                                          audio_session_t session,
+                                          audio_stream_type_t *stream,
+                                          uint32_t samplingRate,
+                                          audio_format_t format,
+                                          audio_channel_mask_t channelMask,
+                                          audio_output_flags_t flags,
+                                          const audio_offload_info_t *offloadInfo);
         virtual status_t startOutput(audio_io_handle_t output,
                                      audio_stream_type_t stream,
-                                     int session = 0);
+                                     audio_session_t session);
         virtual status_t stopOutput(audio_io_handle_t output,
                                     audio_stream_type_t stream,
-                                    int session = 0);
-        virtual void releaseOutput(audio_io_handle_t output);
+                                    audio_session_t session);
+        virtual void releaseOutput(audio_io_handle_t output,
+                                   audio_stream_type_t stream,
+                                   audio_session_t session);
         virtual audio_io_handle_t getInput(audio_source_t inputSource,
                                             uint32_t samplingRate,
                                             audio_format_t format,
@@ -862,6 +867,7 @@
         // internal method to return the output handle for the given device and format
         audio_io_handle_t getOutputForDevice(
                 audio_devices_t device,
+                audio_session_t session,
                 audio_stream_type_t stream,
                 uint32_t samplingRate,
                 audio_format_t format,
@@ -877,6 +883,7 @@
         //   the mute/unmute happened
         uint32_t handleEventForBeacon(int event);
         uint32_t setBeaconMute(bool mute);
+        bool     isValidAttributes(const audio_attributes_t *paa);
 };
 
 };
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index 127c25b..b80380e 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -458,7 +458,7 @@
                         break;
                     }
                     mLock.unlock();
-                    svc->doReleaseOutput(data->mIO);
+                    svc->doReleaseOutput(data->mIO, data->mStream, data->mSession);
                     mLock.lock();
                     }break;
                 case CREATE_AUDIO_PATCH: {
@@ -655,7 +655,7 @@
 
 void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output,
                                                                audio_stream_type_t stream,
-                                                               int session)
+                                                               audio_session_t session)
 {
     sp<AudioCommand> command = new AudioCommand();
     command->mCommand = STOP_OUTPUT;
@@ -668,12 +668,16 @@
     sendCommand(command);
 }
 
-void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output)
+void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output,
+                                                                  audio_stream_type_t stream,
+                                                                  audio_session_t session)
 {
     sp<AudioCommand> command = new AudioCommand();
     command->mCommand = RELEASE_OUTPUT;
     sp<ReleaseOutputData> data = new ReleaseOutputData();
     data->mIO = output;
+    data->mStream = stream;
+    data->mSession = session;
     command->mParam = data;
     ALOGV("AudioCommandThread() adding release output %d", output);
     sendCommand(command);
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 2ac31df..23f335e 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -74,24 +74,29 @@
                                         audio_output_flags_t flags =
                                                 AUDIO_OUTPUT_FLAG_NONE,
                                         const audio_offload_info_t *offloadInfo = NULL);
-    virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                            uint32_t samplingRate = 0,
-                                            audio_format_t format = AUDIO_FORMAT_DEFAULT,
-                                            audio_channel_mask_t channelMask = 0,
-                                            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                                            const audio_offload_info_t *offloadInfo = NULL);
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                      audio_io_handle_t *output,
+                                      audio_session_t session,
+                                      audio_stream_type_t *stream,
+                                      uint32_t samplingRate = 0,
+                                      audio_format_t format = AUDIO_FORMAT_DEFAULT,
+                                      audio_channel_mask_t channelMask = 0,
+                                      audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+                                      const audio_offload_info_t *offloadInfo = NULL);
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session = 0);
+                                 audio_session_t session);
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session = 0);
-    virtual void releaseOutput(audio_io_handle_t output);
+                                audio_session_t session);
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session);
     virtual audio_io_handle_t getInput(audio_source_t inputSource,
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int audioSession,
+                                    audio_session_t audioSession,
                                     audio_input_flags_t flags);
     virtual status_t startInput(audio_io_handle_t input,
                                 audio_session_t session);
@@ -183,8 +188,10 @@
 
             status_t doStopOutput(audio_io_handle_t output,
                                   audio_stream_type_t stream,
-                                  int session = 0);
-            void doReleaseOutput(audio_io_handle_t output);
+                                  audio_session_t session);
+            void doReleaseOutput(audio_io_handle_t output,
+                                 audio_stream_type_t stream,
+                                 audio_session_t session);
 
             status_t clientCreateAudioPatch(const struct audio_patch *patch,
                                       audio_patch_handle_t *handle,
@@ -252,8 +259,10 @@
                     status_t    voiceVolumeCommand(float volume, int delayMs = 0);
                     void        stopOutputCommand(audio_io_handle_t output,
                                                   audio_stream_type_t stream,
-                                                  int session);
-                    void        releaseOutputCommand(audio_io_handle_t output);
+                                                  audio_session_t session);
+                    void        releaseOutputCommand(audio_io_handle_t output,
+                                                     audio_stream_type_t stream,
+                                                     audio_session_t session);
                     status_t    sendCommand(sp<AudioCommand>& command, int delayMs = 0);
                     void        insertCommand_l(sp<AudioCommand>& command, int delayMs = 0);
                     status_t    createAudioPatchCommand(const struct audio_patch *patch,
@@ -323,12 +332,14 @@
         public:
             audio_io_handle_t mIO;
             audio_stream_type_t mStream;
-            int mSession;
+            audio_session_t mSession;
         };
 
         class ReleaseOutputData : public AudioCommandData {
         public:
             audio_io_handle_t mIO;
+            audio_stream_type_t mStream;
+            audio_session_t mSession;
         };
 
         class CreateAudioPatchData : public AudioCommandData {