Fix issue 3371080

Modified default volume control logic in AudioService:
1 IN_CALL volume if in video/audio chat
2 NOTIFICATION if notification is playing or was playing less than 5s ago.
3 MUSIC

Modified silent mode:
- now also affect MUSIC stream type
- entering silent mode when VOL- hard key is pressed once while selected
stream volume is already at 0 (except for VOICE_CALL stream).
- exiting silent mode when pressing VOL+ hard key while in silent mode

Play sound FX (audible selections, keyboard clicks) at a fixed volume.

Modified audio framework:
- isStreamActive() method now implemented in AudioPolicyManagerBase (previously AudioFlinger)
- iStreamActive() now specifies a time window during which the stream is considered
active after it actually stopped.

Change-Id: I7e5a0724099450b9fc90825224180ac97322785f
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 1e29d82..03f8944 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -204,8 +204,9 @@
     // set audio mode in audio hardware (see AudioSystem::audio_mode)
     static status_t setMode(int mode);
 
-    // returns true in *state if tracks are active on the specified stream
-    static status_t isStreamActive(int stream, bool *state);
+    // returns true in *state if tracks are active on the specified stream or has been active
+    // in the past inPastMs milliseconds
+    static status_t isStreamActive(int stream, bool *state, uint32_t inPastMs = 0);
 
     // set/get audio hardware parameters. The function accepts a list of parameters
     // key value pairs in the form: key1=value1;key2=value2;...
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 70e505e..589f7cd 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -102,9 +102,6 @@
     virtual     status_t    setMicMute(bool state) = 0;
     virtual     bool        getMicMute() const = 0;
 
-    // is any track active on this stream?
-    virtual     bool        isStreamActive(int stream) const = 0;
-
     virtual     status_t    setParameters(int ioHandle, const String8& keyValuePairs) = 0;
     virtual     String8     getParameters(int ioHandle, const String8& keys) = 0;
 
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 49eee59..5afceaa 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -81,6 +81,7 @@
                                     int session,
                                     int id) = 0;
     virtual status_t unregisterEffect(int id) = 0;
+    virtual bool     isStreamActive(int stream, uint32_t inPastMs = 0) const = 0;
 };
 
 
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 1a3fcd6..9d9b3c0 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -169,15 +169,6 @@
     return af->setMode(mode);
 }
 
-
-status_t AudioSystem::isStreamActive(int stream, bool* state) {
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return PERMISSION_DENIED;
-    *state = af->isStreamActive(stream);
-    return NO_ERROR;
-}
-
-
 status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
@@ -702,6 +693,14 @@
     return aps->unregisterEffect(id);
 }
 
+status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) {
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    *state = aps->isStreamActive(stream, inPastMs);
+    return NO_ERROR;
+}
+
+
 // ---------------------------------------------------------------------------
 
 void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 3a89e25..eec47c0 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -47,7 +47,6 @@
     SET_MODE,
     SET_MIC_MUTE,
     GET_MIC_MUTE,
-    IS_STREAM_ACTIVE,
     SET_PARAMETERS,
     GET_PARAMETERS,
     REGISTER_CLIENT,
@@ -316,15 +315,6 @@
         return reply.readInt32();
     }
 
-    virtual bool isStreamActive(int stream) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(stream);
-        remote()->transact(IS_STREAM_ACTIVE, data, &reply);
-        return reply.readInt32();
-    }
-
     virtual status_t setParameters(int ioHandle, const String8& keyValuePairs)
     {
         Parcel data, reply;
@@ -826,12 +816,6 @@
             reply->writeInt32( getMicMute() );
             return NO_ERROR;
         } break;
-        case IS_STREAM_ACTIVE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int stream = data.readInt32();
-            reply->writeInt32( isStreamActive(stream) );
-            return NO_ERROR;
-        } break;
         case SET_PARAMETERS: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int ioHandle = data.readInt32();
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 950c213..457f7ed 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -48,7 +48,8 @@
     GET_STRATEGY_FOR_STREAM,
     GET_OUTPUT_FOR_EFFECT,
     REGISTER_EFFECT,
-    UNREGISTER_EFFECT
+    UNREGISTER_EFFECT,
+    IS_STREAM_ACTIVE
 };
 
 class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -297,6 +298,15 @@
         return static_cast <status_t> (reply.readInt32());
     }
 
+    virtual bool isStreamActive(int stream, uint32_t inPastMs) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(stream);
+        data.writeInt32(inPastMs);
+        remote()->transact(IS_STREAM_ACTIVE, data, &reply);
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -517,6 +527,14 @@
             return NO_ERROR;
         } break;
 
+        case IS_STREAM_ACTIVE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            int stream = data.readInt32();
+            uint32_t inPastMs = (uint32_t)data.readInt32();
+            reply->writeInt32( isStreamActive(stream, inPastMs) );
+            return NO_ERROR;
+        } break;
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 11ad4e4..4ec16c1 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -624,17 +624,6 @@
     return mStreamTypes[stream].mute;
 }
 
-bool AudioFlinger::isStreamActive(int stream) const
-{
-    Mutex::Autolock _l(mLock);
-    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
-        if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) {
-            return true;
-        }
-    }
-    return false;
-}
-
 status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
 {
     status_t result;
@@ -1291,20 +1280,6 @@
     return mStreamTypes[stream].mute;
 }
 
-bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const
-{
-    Mutex::Autolock _l(mLock);
-    size_t count = mActiveTracks.size();
-    for (size_t i = 0 ; i < count ; ++i) {
-        sp<Track> t = mActiveTracks[i].promote();
-        if (t == 0) continue;
-        Track* const track = t.get();
-        if (t->type() == stream)
-            return true;
-    }
-    return false;
-}
-
 // addTrack_l() must be called with ThreadBase::mLock held
 status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
 {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index f0ef867..81f2eb4 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -107,8 +107,6 @@
     virtual     status_t    setMicMute(bool state);
     virtual     bool        getMicMute() const;
 
-    virtual     bool        isStreamActive(int stream) const;
-
     virtual     status_t    setParameters(int ioHandle, const String8& keyValuePairs);
     virtual     String8     getParameters(int ioHandle, const String8& keys);
 
@@ -579,8 +577,6 @@
         virtual     float       streamVolume(int stream) const;
         virtual     bool        streamMute(int stream) const;
 
-                    bool        isStreamActive(int stream) const;
-
                     sp<Track>   createTrack_l(
                                     const sp<AudioFlinger::Client>& client,
                                     int streamType,
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 2c81c34..afa9acc 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -312,8 +312,7 @@
 
     // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
     if (state == AudioSystem::MODE_RINGTONE &&
-        (hwOutputDesc->mRefCount[AudioSystem::MUSIC] ||
-        (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) {
+        isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) {
         mLimitRingtoneVolume = true;
     } else {
         mLimitRingtoneVolume = false;
@@ -478,6 +477,7 @@
         outputDesc->mLatency = 0;
         outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
         outputDesc->mRefCount[stream] = 0;
+        outputDesc->mStopTime[stream] = 0;
         output = mpClientInterface->openOutput(&outputDesc->mDevice,
                                         &outputDesc->mSamplingRate,
                                         &outputDesc->mFormat,
@@ -606,10 +606,8 @@
     if (outputDesc->mRefCount[stream] > 0) {
         // decrement usage count of this stream on the output
         outputDesc->changeRefCount(stream, -1);
-        // store time at which the last music track was stopped - see computeVolume()
-        if (stream == AudioSystem::MUSIC) {
-            mMusicStopTime = systemTime();
-        }
+        // store time at which the stream was stopped - see isStreamActive()
+        outputDesc->mStopTime[stream] = systemTime();
 
         setOutputDevice(output, getNewDevice(output));
 
@@ -919,6 +917,19 @@
     return NO_ERROR;
 }
 
+bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const
+{
+    nsecs_t sysTime = systemTime();
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        if (mOutputs.valueAt(i)->mRefCount[stream] != 0 ||
+            ns2ms(sysTime - mOutputs.valueAt(i)->mStopTime[stream]) < inPastMs) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
 status_t AudioPolicyManagerBase::dump(int fd)
 {
     const size_t SIZE = 256;
@@ -1009,7 +1020,7 @@
     Thread(false),
 #endif //AUDIO_POLICY_TEST
     mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0),
-    mMusicStopTime(0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
+    mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
     mA2dpSuspended(false)
 {
@@ -2036,6 +2047,7 @@
         mRefCount[i] = 0;
         mCurVolume[i] = -1.0;
         mMuteCount[i] = 0;
+        mStopTime[i] = 0;
     }
 }
 
@@ -2086,7 +2098,6 @@
     return refCount;
 }
 
-
 status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
 {
     const size_t SIZE = 256;
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 46a01ad..b04672d 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -394,6 +394,15 @@
     return mpPolicyManager->unregisterEffect(id);
 }
 
+bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const
+{
+    if (mpPolicyManager == NULL) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->isStreamActive(stream, inPastMs);
+}
+
 void AudioPolicyService::binderDied(const wp<IBinder>& who) {
     LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
             IPCThreadState::self()->getCallingPid());
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 558f455..54af1f1 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -88,6 +88,7 @@
                                     int session,
                                     int id);
     virtual status_t unregisterEffect(int id);
+    virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
 
     virtual     status_t    onTransact(
                                 uint32_t code,
@@ -230,8 +231,8 @@
     status_t dumpPermissionDenial(int fd);
 
 
-    Mutex   mLock;      // prevents concurrent access to AudioPolicy manager functions changing device
-                        // connection stated our routing
+    mutable Mutex mLock;    // prevents concurrent access to AudioPolicy manager functions changing
+                            // device connection state  or routing
     AudioPolicyInterface* mpPolicyManager;          // the platform specific policy manager
     sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
     sp <AudioCommandThread> mTonePlaybackThread;     // tone playback thread