Merge "Camera: Add input side to camera3 HAL device" into jb-mr2-dev
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 0529bcd..2183fbe 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -271,6 +271,7 @@
     float mVolume;  // Volume applied to audio track
     audio_stream_type_t mStreamType; // Audio stream used for output
     unsigned int mProcessSize;  // Size of audio blocks generated at a time by audioCallback() (in PCM frames).
+    struct timespec mStartTime; // tone start time: needed to guaranty actual tone duration
 
     bool initAudioTrack();
     static void audioCallback(int event, void* user, void *info);
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 58d495e..9ea3ea7 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -922,6 +922,9 @@
             ALOGV("Immediate start, time %d", (unsigned int)(systemTime()/1000000));
             lResult = true;
             mState = TONE_STARTING;
+            if (clock_gettime(CLOCK_MONOTONIC, &mStartTime) != 0) {
+                mStartTime.tv_sec = 0;
+            }
             mLock.unlock();
             mpAudioTrack->start();
             mLock.lock();
@@ -940,6 +943,7 @@
     } else {
         ALOGV("Delayed start");
         mState = TONE_RESTARTING;
+        mStartTime.tv_sec = 0;
         lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
         if (lStatus == NO_ERROR) {
             if (mState != TONE_IDLE) {
@@ -976,21 +980,49 @@
     ALOGV("stopTone");
 
     mLock.lock();
-    if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) {
-        mState = TONE_STOPPING;
+    if (mState != TONE_IDLE && mState != TONE_INIT) {
+        if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) {
+            struct timespec stopTime;
+            // If the start time is valid, make sure that the number of audio samples produced
+            // corresponds at least to the time between the start and stop commands.
+            // This is needed in case of cold start of the output stream.
+            if ((mStartTime. tv_sec != 0) && (clock_gettime(CLOCK_MONOTONIC, &stopTime) == 0)) {
+                time_t sec = stopTime.tv_sec - mStartTime.tv_sec;
+                long nsec = stopTime.tv_nsec - mStartTime.tv_nsec;
+                long durationMs;
+                if (nsec < 0) {
+                    --sec;
+                    nsec += 1000000000;
+                }
+
+                if ((sec + 1) > ((long)(INT_MAX / mSamplingRate))) {
+                    mMaxSmp = sec * mSamplingRate;
+                } else {
+                    // mSamplingRate is always > 1000
+                    sec = sec * 1000 + nsec / 1000000; // duration in milliseconds
+                    mMaxSmp = (sec * mSamplingRate) / 1000;
+                }
+                ALOGV("stopTone() forcing mMaxSmp to %d, total for far %d", mMaxSmp,  mTotalSmp);
+            } else {
+                mState = TONE_STOPPING;
+            }
+        }
         ALOGV("waiting cond");
         status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
         if (lStatus == NO_ERROR) {
+            // If the tone was restarted exit now before calling clearWaveGens();
+            if (mState != TONE_INIT) {
+                return;
+            }
             ALOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000));
         } else {
             ALOGE("--- Stop timed out");
             mState = TONE_IDLE;
             mpAudioTrack->stop();
         }
+        clearWaveGens();
     }
 
-    clearWaveGens();
-
     mLock.unlock();
 }
 
@@ -1258,6 +1290,9 @@
             ALOGV("Cbk restarting track");
             if (lpToneGen->prepareWave()) {
                 lpToneGen->mState = TONE_STARTING;
+                if (clock_gettime(CLOCK_MONOTONIC, &lpToneGen->mStartTime) != 0) {
+                    lpToneGen->mStartTime.tv_sec = 0;
+                }
                 // must reload lpToneDesc as prepareWave() may change mpToneDesc
                 lpToneDesc = lpToneGen->mpToneDesc;
             } else {
@@ -1299,7 +1334,7 @@
         }
 
         if (lSignal)
-            lpToneGen->mWaitCbkCond.signal();
+            lpToneGen->mWaitCbkCond.broadcast();
         lpToneGen->mLock.unlock();
     }
 }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index c2c9985..095d5ca 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -70,7 +70,8 @@
       mOutputFd(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
-      mStarted(false), mSurfaceMediaSource(NULL) {
+      mStarted(false), mSurfaceMediaSource(NULL),
+      mCaptureTimeLapse(false) {
 
     ALOGV("Constructor");
     reset();