audio: Subsystem Restart changes

 - Handle new ADSP status parameter
   - media/libmedia: Add new ADSP status audio parameter
   - framework/av: Add handling of new key-pair value in
     Audio Flinger

 - Handle Tunnel mode SubSys Restart
   - framework/av: Post SSR event to Audio Flinger
   - media/libmedia: Post SSR event to AudioTrack
   - media/libmediaplayerservice: Post SSR event to
     MediaPlayerService
   - media/libstagefright: Post SSR event to TunnelPlayer

Change-Id: I8c8385af45be91caf7d7160ab2e0236d6591b159
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
index d29c699..2476e66 100644
--- a/include/media/AudioParameter.h
+++ b/include/media/AudioParameter.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008-2011 The Android Open Source Project
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@
     static const char * const keyFluenceType;
     static const char * const keySSR;
     static const char * const keyHandleA2dpDevice;
+    static const char * const keyADSPStatus;
 #endif
 
     String8 toString();
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 77a0b26..108f1a7 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -64,7 +65,8 @@
         EVENT_LOOP_END = 2,         // Sample loop end was reached; playback restarted from loop start if loop count was not 0.
         EVENT_MARKER = 3,           // Playback head is at the specified marker position (See setMarkerPosition()).
         EVENT_NEW_POS = 4,          // Playback head is at a new position (See setPositionUpdatePeriod()).
-        EVENT_BUFFER_END = 5        // Playback head is at the end of the buffer.
+        EVENT_BUFFER_END = 5,       // Playback head is at the end of the buffer.
+        EVENT_HW_FAIL = 6,          // ADSP failure.
     };
 
     /* Client should declare Buffer on the stack and pass address to obtainBuffer()
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
index fbb34f4..367d9f6 100644
--- a/media/libmedia/AudioParameter.cpp
+++ b/media/libmedia/AudioParameter.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2006-2011 The Android Open Source Project
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
 const char * const AudioParameter::keyFluenceType = AUDIO_PARAMETER_KEY_FLUENCE_TYPE;
 const char * const AudioParameter::keySSR = AUDIO_PARAMETER_KEY_SSR;
 const char * const AudioParameter::keyHandleA2dpDevice = AUDIO_PARAMETER_KEY_HANDLE_A2DP_DEVICE;
+const char * const AudioParameter::keyADSPStatus = AUDIO_PARAMETER_KEY_ADSP_STATUS;
 #endif
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 36b1469..0d7d733 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -2,7 +2,7 @@
 **
 ** Copyright 2007, The Android Open Source Project
 **
-** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 ** Not a Contribution, Apache license notifications and license are retained
 ** for attribution purposes only.
 
@@ -1620,6 +1620,10 @@
         ALOGV("Posting event underrun to Audio Sink.");
         mCbf(EVENT_UNDERRUN, mUserData, 0);
     }
+    if (msg == EVENT_HW_FAIL) {
+        ALOGV("Posting event HW fail to Audio Sink.");
+        mCbf(EVENT_HW_FAIL, mUserData, 0);
+    }
 }
 
 status_t AudioTrack::getTimeStamp(uint64_t *tstamp) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 414c262..f238e89 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1,6 +1,6 @@
 /*
 **
-** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 ** Not a Contribution, Apache license notifications and license are retained
 ** for attribution purposes only.
 **
@@ -1735,6 +1735,27 @@
         data->unlock();
         return;
     }
+    if (event == AudioTrack::EVENT_HW_FAIL) {
+        ALOGW("Event hardware failure");
+        CallbackData *data = (CallbackData*)cookie;
+        if (data != NULL) {
+            data->lock();
+            AudioOutput *me = data->getOutput();
+            if (me == NULL) {
+                // no output set, likely because the track was
+                // scheduled to be reused
+                // by another player, but the format turned out
+                // to be incompatible.
+                data->unlock();
+                return;
+            }
+            ALOGV("Callback!!!");
+            (*me->mCallback)(me, NULL, (size_t)AudioTrack::EVENT_HW_FAIL,
+                             me->mCallbackCookie);
+            data->unlock();
+        }
+        return;
+    }
 #endif
     if (event == AudioTrack::EVENT_MORE_DATA) {
         CallbackData *data = (CallbackData*)cookie;
diff --git a/media/libstagefright/TunnelPlayer.cpp b/media/libstagefright/TunnelPlayer.cpp
index 3b45db4..f9d0976 100644
--- a/media/libstagefright/TunnelPlayer.cpp
+++ b/media/libstagefright/TunnelPlayer.cpp
@@ -501,6 +501,28 @@
 size_t TunnelPlayer::AudioSinkCallback(
         MediaPlayerBase::AudioSink *audioSink,
         void *buffer, size_t size, void *cookie) {
+#ifdef QCOM_HARDWARE
+    TunnelPlayer *me = (TunnelPlayer *)cookie;
+    if(me != NULL) {
+        ALOGV("postAudioEOS mSeeking %d", me->mSeeking);
+        if (buffer == NULL && size == AudioTrack::EVENT_UNDERRUN) {
+            if(me->mReachedEOS == true) {
+                //in the case of seek all these flags will be reset
+                me->mReachedOutputEOS = true;
+                ALOGV("postAudioEOS mSeeking %d", me->mSeeking);
+                me->mObserver->postAudioEOS(0);
+            }else {
+                ALOGV("postAudioEOS ignored since %d", me->mSeeking);
+            }
+        } else if (size == AudioTrack::EVENT_HW_FAIL) {
+            ALOGV("postAudioEOS in SSR " );
+            me->mReachedOutputEOS = true;
+            me->mReachedEOS = true;
+            me->killExtractorThread = true;
+            me->mObserver->postAudioEOS(0);
+        }
+    }
+#else
     if (buffer == NULL && size == AudioTrack::EVENT_UNDERRUN) {
         TunnelPlayer *me = (TunnelPlayer *)cookie;
         if(me->mReachedEOS == true) {
@@ -512,6 +534,7 @@
             ALOGV("postAudioEOS ignored since %d", me->mSeeking);
         }
     }
+#endif
     return 1;
 }
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e4c055a..5975b62 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -107,6 +107,7 @@
 
 #ifdef QCOM_HARDWARE
 #define DIRECT_TRACK_EOS 1
+#define DIRECT_TRACK_HW_FAIL 6
 static const char lockName[] = "DirectTrack";
 #endif
 
@@ -1162,9 +1163,29 @@
             }
             mHardwareStatus = AUDIO_HW_IDLE;
         }
+#ifdef QCOM_HARDWARE
+        AudioParameter param = AudioParameter(keyValuePairs);
+        String8 value, key;
+        int i = 0;
+
+        key = String8(AudioParameter::keyADSPStatus);
+        if (param.get(key, value) == NO_ERROR) {
+            ALOGV("Set keyADSPStatus:%s", value.string());
+            if (value == "ONLINE" || value == "OFFLINE") {
+               if (!mDirectAudioTracks.isEmpty()) {
+                   for (i=0; i < mDirectAudioTracks.size(); i++) {
+                       mDirectAudioTracks.valueAt(i)->stream->common.set_parameters(
+                          &mDirectAudioTracks.valueAt(i)->stream->common, keyValuePairs.string());
+                   }
+               }
+           }
+        }
+#else
         // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
         AudioParameter param = AudioParameter(keyValuePairs);
         String8 value;
+#endif
+
         if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
             bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
             if (mBtNrecIsOff != btNrecIsOff) {
@@ -6262,8 +6283,18 @@
 }
 
 void AudioFlinger::DirectAudioTrack::postEOS(int64_t delayUs) {
+#ifdef QCOM_HARDWARE
+    if (delayUs == 0 ) {
+       ALOGV("Notify Audio Track of EOS event");
+       mClient->notify(DIRECT_TRACK_EOS);
+    } else {
+       ALOGV("Notify Audio Track of hardware failure event");
+       mClient->notify(DIRECT_TRACK_HW_FAIL);
+    }
+#else
     ALOGV("Notify Audio Track of EOS event");
     mClient->notify(DIRECT_TRACK_EOS);
+#endif
 }
 
 void AudioFlinger::DirectAudioTrack::allocateBufPool() {