Merge change I93f500a5 into eclair

* changes:
  Fix issue 2203561: Sholes: audio playing out of earpiece.
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 503cb31..008468c 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -314,6 +314,11 @@
     };
 
             bool processAudioBuffer(const sp<ClientRecordThread>& thread);
+            status_t openRecord(uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int frameCount,
+                                uint32_t flags);
 
     sp<IAudioRecord>        mAudioRecord;
     sp<IMemory>             mCblkMemory;
@@ -341,6 +346,7 @@
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
     audio_io_handle_t       mInput;
+    uint32_t                mFlags;
 };
 
 }; // namespace android
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 981c2f6..14b30ae 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -391,6 +391,14 @@
     };
 
             bool processAudioBuffer(const sp<AudioTrackThread>& thread);
+            status_t createTrack(int streamType,
+                                 uint32_t sampleRate,
+                                 int format,
+                                 int channelCount,
+                                 int frameCount,
+                                 uint32_t flags,
+                                 const sp<IMemory>& sharedBuffer,
+                                 audio_io_handle_t output);
 
     sp<IAudioTrack>         mAudioTrack;
     sp<IMemory>             mCblkMemory;
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index c884c2c..1ad1f26 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -151,7 +151,7 @@
         NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
     };
 
-    ToneGenerator(int streamType, float volume);
+    ToneGenerator(int streamType, float volume, bool threadCanCallJava = false);
     ~ToneGenerator();
 
     bool startTone(int toneType, int durationMs = -1);
@@ -242,6 +242,7 @@
 
     static const ToneDescriptor sToneDescriptors[];
 
+    bool mThreadCanCallJava;
     unsigned int mTotalSmp;  // Total number of audio samples played (gives current time)
     unsigned int mNextSegSmp;  // Position of next segment transition expressed in samples
     // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 5e35564..e63c0d2 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -101,11 +101,6 @@
         return INVALID_OPERATION;
     }
 
-    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
-    if (audioFlinger == 0) {
-        return NO_INIT;
-    }
-
     if (inputSource == AUDIO_SOURCE_DEFAULT) {
         inputSource = AUDIO_SOURCE_MIC;
     }
@@ -171,22 +166,14 @@
         notificationFrames = frameCount/2;
     }
 
-    // open record channel
-    status_t status;
-    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
-                                                       sampleRate, format,
-                                                       channelCount,
-                                                       frameCount,
-                                                       ((uint16_t)flags) << 16,
-                                                       &status);
-    if (record == 0) {
-        LOGE("AudioFlinger could not create record track, status: %d", status);
+    // create the IAudioRecord
+    status_t status = openRecord(sampleRate, format, channelCount,
+                                 frameCount, flags);
+
+    if (status != NO_ERROR) {
         return status;
     }
-    sp<IMemory> cblk = record->getCblk();
-    if (cblk == 0) {
-        return NO_INIT;
-    }
+
     if (cbf != 0) {
         mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
         if (mClientRecordThread == 0) {
@@ -196,11 +183,6 @@
 
     mStatus = NO_ERROR;
 
-    mAudioRecord = record;
-    mCblkMemory = cblk;
-    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
-    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
-    mCblk->out = 0;
     mFormat = format;
     // Update buffer size in case it has been limited by AudioFlinger during track creation
     mFrameCount = mCblk->frameCount;
@@ -217,6 +199,7 @@
     mNewPosition = 0;
     mUpdatePeriod = 0;
     mInputSource = (uint8_t)inputSource;
+    mFlags = flags;
 
     return NO_ERROR;
 }
@@ -284,15 +267,26 @@
     if (android_atomic_or(1, &mActive) == 0) {
         ret = AudioSystem::startInput(mInput);
         if (ret == NO_ERROR) {
-            mNewPosition = mCblk->user + mUpdatePeriod;
-            mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
-            mCblk->waitTimeMs = 0;
-            if (t != 0) {
-               t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
-            } else {
-                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
-            }
             ret = mAudioRecord->start();
+            if (ret == DEAD_OBJECT) {
+                LOGV("start() dead IAudioRecord: creating a new one");
+                ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
+                        mFrameCount, mFlags);
+            }
+            if (ret == NO_ERROR) {
+                mNewPosition = mCblk->user + mUpdatePeriod;
+                mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+                mCblk->waitTimeMs = 0;
+                if (t != 0) {
+                   t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
+                } else {
+                    setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+                }
+            } else {
+                LOGV("start() failed");
+                AudioSystem::stopInput(mInput);
+                android_atomic_and(~1, &mActive);
+            }
         }
     }
 
@@ -396,10 +390,48 @@
 
 // -------------------------------------------------------------------------
 
+status_t AudioRecord::openRecord(
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags)
+{
+    status_t status;
+    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+    if (audioFlinger == 0) {
+        return NO_INIT;
+    }
+
+    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
+                                                       sampleRate, format,
+                                                       channelCount,
+                                                       frameCount,
+                                                       ((uint16_t)flags) << 16,
+                                                       &status);
+    if (record == 0) {
+        LOGE("AudioFlinger could not create record track, status: %d", status);
+        return status;
+    }
+    sp<IMemory> cblk = record->getCblk();
+    if (cblk == 0) {
+        LOGE("Could not get control block");
+        return NO_INIT;
+    }
+    mAudioRecord.clear();
+    mAudioRecord = record;
+    mCblkMemory.clear();
+    mCblkMemory = cblk;
+    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+    mCblk->out = 0;
+
+    return NO_ERROR;
+}
+
 status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
 {
     int active;
-    int timeout = 0;
     status_t result;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = audioBuffer->frameCount;
@@ -411,25 +443,40 @@
     uint32_t framesReady = cblk->framesReady();
 
     if (framesReady == 0) {
-        Mutex::Autolock _l(cblk->lock);
+        cblk->lock.lock();
         goto start_loop_here;
         while (framesReady == 0) {
             active = mActive;
-            if (UNLIKELY(!active))
+            if (UNLIKELY(!active)) {
+                cblk->lock.unlock();
                 return NO_MORE_BUFFERS;
-            if (UNLIKELY(!waitCount))
+            }
+            if (UNLIKELY(!waitCount)) {
+                cblk->lock.unlock();
                 return WOULD_BLOCK;
-            timeout = 0;
+            }
             result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
             if (__builtin_expect(result!=NO_ERROR, false)) {
                 cblk->waitTimeMs += waitTimeMs;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
                     LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
                             "user=%08x, server=%08x", cblk->user, cblk->server);
-                    timeout = 1;
+                    cblk->lock.unlock();
+                    result = mAudioRecord->start();
+                    if (result == DEAD_OBJECT) {
+                        LOGW("obtainBuffer() dead IAudioRecord: creating a new one");
+                        result = openRecord(cblk->sampleRate, mFormat, mChannelCount,
+                                            mFrameCount, mFlags);
+                        if (result == NO_ERROR) {
+                            cblk = mCblk;
+                            cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+                        }
+                    }
+                    cblk->lock.lock();
                     cblk->waitTimeMs = 0;
                 }
                 if (--waitCount == 0) {
+                    cblk->lock.unlock();
                     return TIMED_OUT;
                 }
             }
@@ -437,13 +484,9 @@
         start_loop_here:
             framesReady = cblk->framesReady();
         }
+        cblk->lock.unlock();
     }
 
-    LOGW_IF(timeout,
-        "*** SERIOUS WARNING *** obtainBuffer() timed out "
-        "but didn't need to be locked. We recovered, but "
-        "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
-
     cblk->waitTimeMs = 0;
 
     if (framesReq > framesReady) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 4b9d272..8529a8e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -122,11 +122,6 @@
         return INVALID_OPERATION;
     }
 
-    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
-    if (audioFlinger == 0) {
-       LOGE("Could not get audioflinger");
-       return NO_INIT;
-    }
     int afSampleRate;
     if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         return NO_INIT;
@@ -217,28 +212,16 @@
         }
     }
 
-    // create the track
-    status_t status;
-    sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
-                                                      streamType,
-                                                      sampleRate,
-                                                      format,
-                                                      channelCount,
-                                                      frameCount,
-                                                      ((uint16_t)flags) << 16,
-                                                      sharedBuffer,
-                                                      output,
-                                                      &status);
+    mVolume[LEFT] = 1.0f;
+    mVolume[RIGHT] = 1.0f;
+    // create the IAudioTrack
+    status_t status = createTrack(streamType, sampleRate, format, channelCount,
+                                  frameCount, flags, sharedBuffer, output);
 
-    if (track == 0) {
-        LOGE("AudioFlinger could not create track, status: %d", status);
+    if (status != NO_ERROR) {
         return status;
     }
-    sp<IMemory> cblk = track->getCblk();
-    if (cblk == 0) {
-        LOGE("Could not get control block");
-        return NO_INIT;
-    }
+
     if (cbf != 0) {
         mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
         if (mAudioTrackThread == 0) {
@@ -249,22 +232,6 @@
 
     mStatus = NO_ERROR;
 
-    mAudioTrack = track;
-    mCblkMemory = cblk;
-    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
-    mCblk->out = 1;
-    // Update buffer size in case it has been limited by AudioFlinger during track creation
-    mFrameCount = mCblk->frameCount;
-    if (sharedBuffer == 0) {
-        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
-    } else {
-        mCblk->buffers = sharedBuffer->pointer();
-         // Force buffer full condition as data is already present in shared memory
-        mCblk->stepUser(mFrameCount);
-    }
-    mCblk->volume[0] = mCblk->volume[1] = 0x1000;
-    mVolume[LEFT] = 1.0f;
-    mVolume[RIGHT] = 1.0f;
     mStreamType = streamType;
     mFormat = format;
     mChannels = channels;
@@ -351,16 +318,27 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
-        AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
-        mNewPosition = mCblk->server + mUpdatePeriod;
-        mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
-        mCblk->waitTimeMs = 0;
-        if (t != 0) {
-           t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
-        } else {
-            setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+        audio_io_handle_t output = AudioTrack::getOutput();
+        status_t status = mAudioTrack->start();
+        if (status == DEAD_OBJECT) {
+            LOGV("start() dead IAudioTrack: creating a new one");
+            status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
+                                 mFrameCount, mFlags, mSharedBuffer, output);
         }
-        mAudioTrack->start();
+        if (status == NO_ERROR) {
+            AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
+            mNewPosition = mCblk->server + mUpdatePeriod;
+            mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+            mCblk->waitTimeMs = 0;
+            if (t != 0) {
+               t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
+            } else {
+                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+            }
+        } else {
+            LOGV("start() failed");
+            android_atomic_and(~1, &mActive);
+        }
     }
 
     if (t != 0) {
@@ -617,10 +595,67 @@
 
 // -------------------------------------------------------------------------
 
+status_t AudioTrack::createTrack(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags,
+        const sp<IMemory>& sharedBuffer,
+        audio_io_handle_t output)
+{
+    status_t status;
+    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+    if (audioFlinger == 0) {
+       LOGE("Could not get audioflinger");
+       return NO_INIT;
+    }
+
+    sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
+                                                      streamType,
+                                                      sampleRate,
+                                                      format,
+                                                      channelCount,
+                                                      frameCount,
+                                                      ((uint16_t)flags) << 16,
+                                                      sharedBuffer,
+                                                      output,
+                                                      &status);
+
+    if (track == 0) {
+        LOGE("AudioFlinger could not create track, status: %d", status);
+        return status;
+    }
+    sp<IMemory> cblk = track->getCblk();
+    if (cblk == 0) {
+        LOGE("Could not get control block");
+        return NO_INIT;
+    }
+    mAudioTrack.clear();
+    mAudioTrack = track;
+    mCblkMemory.clear();
+    mCblkMemory = cblk;
+    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+    mCblk->out = 1;
+    // Update buffer size in case it has been limited by AudioFlinger during track creation
+    mFrameCount = mCblk->frameCount;
+    if (sharedBuffer == 0) {
+        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+    } else {
+        mCblk->buffers = sharedBuffer->pointer();
+         // Force buffer full condition as data is already present in shared memory
+        mCblk->stepUser(mFrameCount);
+    }
+
+    mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);
+
+    return NO_ERROR;
+}
+
 status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
 {
     int active;
-    int timeout = 0;
     status_t result;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = audioBuffer->frameCount;
@@ -632,17 +667,20 @@
     uint32_t framesAvail = cblk->framesAvailable();
 
     if (framesAvail == 0) {
-        Mutex::Autolock _l(cblk->lock);
+        cblk->lock.lock();
         goto start_loop_here;
         while (framesAvail == 0) {
             active = mActive;
             if (UNLIKELY(!active)) {
                 LOGV("Not active and NO_MORE_BUFFERS");
+                cblk->lock.unlock();
                 return NO_MORE_BUFFERS;
             }
-            if (UNLIKELY(!waitCount))
+            if (UNLIKELY(!waitCount)) {
+                cblk->lock.unlock();
                 return WOULD_BLOCK;
-            timeout = 0;
+            }
+
             result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
             if (__builtin_expect(result!=NO_ERROR, false)) {
                 cblk->waitTimeMs += waitTimeMs;
@@ -654,14 +692,23 @@
                                 "user=%08x, server=%08x", this, cblk->user, cblk->server);
                         //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
                         cblk->lock.unlock();
-                        mAudioTrack->start();
+                        result = mAudioTrack->start();
+                        if (result == DEAD_OBJECT) {
+                            LOGW("obtainBuffer() dead IAudioTrack: creating a new one");
+                            result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount,
+                                                 mFrameCount, mFlags, mSharedBuffer, getOutput());
+                            if (result == NO_ERROR) {
+                                cblk = mCblk;
+                                cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+                            }
+                        }
                         cblk->lock.lock();
-                        timeout = 1;
                     }
                     cblk->waitTimeMs = 0;
                 }
 
                 if (--waitCount == 0) {
+                    cblk->lock.unlock();
                     return TIMED_OUT;
                 }
             }
@@ -669,6 +716,7 @@
         start_loop_here:
             framesAvail = cblk->framesAvailable_l();
         }
+        cblk->lock.unlock();
     }
 
     cblk->waitTimeMs = 0;
@@ -684,11 +732,6 @@
         framesReq = bufferEnd - u;
     }
 
-    LOGW_IF(timeout,
-        "*** SERIOUS WARNING *** obtainBuffer() timed out "
-        "but didn't need to be locked. We recovered, but "
-        "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
-
     audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
     audioBuffer->channelCount = mChannelCount;
     audioBuffer->frameCount = framesReq;
@@ -991,7 +1034,7 @@
         // Mark that we have read the first buffer so that next time stepUser() is called
         // we switch to normal obtainBuffer() timeout period
         if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
-            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
+            bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1;
         }
         // It is possible that we receive a flush()
         // while the mixer is processing a block: in this case,
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
index dacf75a..ba0d55b 100644
--- a/media/libmedia/IAudioRecord.cpp
+++ b/media/libmedia/IAudioRecord.cpp
@@ -15,6 +15,10 @@
 ** limitations under the License.
 */
 
+#define LOG_TAG "IAudioRecord"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -42,8 +46,13 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
-        remote()->transact(START, data, &reply);
-        return reply.readInt32();
+        status_t status = remote()->transact(START, data, &reply);
+        if (status == NO_ERROR) {
+            status = reply.readInt32();
+        } else {
+            LOGW("start() error: %s", strerror(-status));
+        }
+        return status;
     }
     
     virtual void stop()
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 7f43347..01ffd75 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -15,6 +15,10 @@
 ** limitations under the License.
 */
 
+#define LOG_TAG "IAudioTrack"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -45,8 +49,13 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
-        remote()->transact(START, data, &reply);
-        return reply.readInt32();
+        status_t status = remote()->transact(START, data, &reply);
+        if (status == NO_ERROR) {
+            status = reply.readInt32();
+        } else {
+            LOGW("start() error: %s", strerror(-status));
+        }
+        return status;
     }
     
     virtual void stop()
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 91d0d00..60e3d71 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -798,7 +798,7 @@
 //        none
 //
 ////////////////////////////////////////////////////////////////////////////////
-ToneGenerator::ToneGenerator(int streamType, float volume) {
+ToneGenerator::ToneGenerator(int streamType, float volume, bool threadCanCallJava) {
 
     LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume);
 
@@ -808,6 +808,7 @@
         LOGE("Unable to marshal AudioFlinger");
         return;
     }
+    mThreadCanCallJava = threadCanCallJava;
     mStreamType = streamType;
     mVolume = volume;
     mpAudioTrack = 0;
@@ -1015,15 +1016,25 @@
     }
 
    // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
-    mpAudioTrack
-            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0);
-
+    mpAudioTrack = new AudioTrack();
     if (mpAudioTrack == 0) {
         LOGE("AudioTrack allocation failed");
         goto initAudioTrack_exit;
     }
     LOGV("Create Track: %p\n", mpAudioTrack);
 
+    mpAudioTrack->set(mStreamType,
+                      0,
+                      AudioSystem::PCM_16_BIT,
+                      AudioSystem::CHANNEL_OUT_MONO,
+                      0,
+                      0,
+                      audioCallback,
+                      this,
+                      0,
+                      0,
+                      mThreadCanCallJava);
+
     if (mpAudioTrack->initCheck() != NO_ERROR) {
         LOGE("AudioTrack->initCheck failed");
         goto initAudioTrack_exit;