Loading api/current.xml +15 −0 Original line number Diff line number Diff line Loading @@ -78333,6 +78333,19 @@ visibility="public" > </method> <method name="startTone" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="toneType" type="int"> </parameter> </method> <method name="startTone" return="boolean" abstract="false" Loading @@ -78345,6 +78358,8 @@ > <parameter name="toneType" type="int"> </parameter> <parameter name="durationMs" type="int"> </parameter> </method> <method name="stopTone" return="void" core/jni/android_media_ToneGenerator.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ struct fields_t { }; static fields_t fields; static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, jint toneType) { static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, jint toneType, jint durationMs) { LOGV("android_media_ToneGenerator_startTone: %x\n", (int)thiz); ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(thiz, Loading @@ -48,7 +48,7 @@ static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, return false; } return lpToneGen->startTone(toneType); return lpToneGen->startTone(toneType, durationMs); } static void android_media_ToneGenerator_stopTone(JNIEnv *env, jobject thiz) { Loading Loading @@ -120,7 +120,7 @@ static void android_media_ToneGenerator_native_finalize(JNIEnv *env, // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { { "startTone", "(I)Z", (void *)android_media_ToneGenerator_startTone }, { "startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone }, { "stopTone", "()V", (void *)android_media_ToneGenerator_stopTone }, { "release", "()V", (void *)android_media_ToneGenerator_release }, { "native_setup", "(II)V", (void *)android_media_ToneGenerator_native_setup }, Loading include/media/ToneGenerator.h +2 −1 Original line number Diff line number Diff line Loading @@ -154,7 +154,7 @@ public: ToneGenerator(int streamType, float volume); ~ToneGenerator(); bool startTone(int toneType); bool startTone(int toneType, int durationMs = -1); void stopTone(); bool isInited() { return (mState == TONE_IDLE)?false:true;} Loading Loading @@ -246,6 +246,7 @@ private: // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded, // no crash will occur but tone sequence will show a glitch. unsigned int mMaxSmp; // Maximum number of audio samples played (maximun tone duration) unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[] unsigned short mCurCount; // Current sequence repeat count Loading libs/audioflinger/AudioFlinger.cpp +63 −55 Original line number Diff line number Diff line Loading @@ -1160,7 +1160,7 @@ AudioFlinger::MixerThread::~MixerThread() bool AudioFlinger::MixerThread::threadLoop() { unsigned long sleepTime = kBufferRecoveryInUsecs; unsigned long sleepTime = 0; int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; Loading Loading @@ -1215,6 +1215,7 @@ bool AudioFlinger::MixerThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading @@ -1222,14 +1223,31 @@ bool AudioFlinger::MixerThread::threadLoop() enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove); } if (LIKELY(enabledTracks)) { // mix buffers... mAudioMixer->process(curBuf); // output audio to hardware if (mSuspended) { usleep(kMaxBufferRecoveryInUsecs); } else { if (LIKELY(enabledTracks)) { // mix buffers... mAudioMixer->process(curBuf); sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (sleepTime < kMaxBufferRecoveryInUsecs) { usleep(kBufferRecoveryInUsecs); } else { memset (curBuf, 0, mixBufferSize); sleepTime = 0; } } // sleepTime == 0 means PCM data were written to mMixBuffer[] if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); Loading @@ -1237,24 +1255,11 @@ bool AudioFlinger::MixerThread::threadLoop() mNumWrites++; mInWrite = false; mStandby = false; nsecs_t temp = systemTime(); standbyTime = temp + kStandbyTimeInNsecs; nsecs_t delta = temp - mLastWriteTime; nsecs_t delta = systemTime() - mLastWriteTime; if (delta > maxPeriod) { LOGW("write blocked for %llu msecs", ns2ms(delta)); mNumDelayedWrites++; } sleepTime = kBufferRecoveryInUsecs; } } else { // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, the audio // hardware will zero-fill for us. // LOGV("thread %p no buffers - usleep(%lu)", this, sleepTime); usleep(sleepTime); if (sleepTime < kMaxBufferRecoveryInUsecs) { sleepTime += kBufferRecoveryInUsecs; } } Loading Loading @@ -1568,7 +1573,7 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread() bool AudioFlinger::DirectOutputThread::threadLoop() { unsigned long sleepTime = kBufferRecoveryInUsecs; unsigned long sleepTime = 0; sp<Track> trackToRemove; sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); Loading Loading @@ -1618,6 +1623,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading Loading @@ -1710,13 +1716,15 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } } // output audio to hardware if (mSuspended) { usleep(kMaxBufferRecoveryInUsecs); } else { if (activeTrack != 0) { AudioBufferProvider::Buffer buffer; size_t frameCount = mFrameCount; curBuf = (int8_t *)mMixBuffer; // output audio to hardware mLastWriteTime = systemTime(); mInWrite = true; while(frameCount) { buffer.frameCount = frameCount; activeTrack->getNextBuffer(&buffer); Loading @@ -1729,27 +1737,27 @@ bool AudioFlinger::DirectOutputThread::threadLoop() curBuf += buffer.frameCount * mFrameSize; activeTrack->releaseBuffer(&buffer); } if (mSuspended) { usleep(kMaxBufferRecoveryInUsecs); sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime < kMaxBufferRecoveryInUsecs) { usleep(kBufferRecoveryInUsecs); } else { memset (mMixBuffer, 0, mFrameCount * mFrameSize); sleepTime = 0; } } // sleepTime == 0 means PCM data were written to mMixBuffer[] if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize); if (bytesWritten) mBytesWritten += bytesWritten; mNumWrites++; mInWrite = false; mStandby = false; nsecs_t temp = systemTime(); standbyTime = temp + kStandbyTimeInNsecs; sleepTime = kBufferRecoveryInUsecs; } } else { // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, the audio // hardware will zero-fill for us. //LOGV("no buffers - usleep(%lu)", sleepTime); usleep(sleepTime); if (sleepTime < kMaxBufferRecoveryInUsecs) { sleepTime += kBufferRecoveryInUsecs; } } Loading media/java/android/media/ToneGenerator.java +13 −2 Original line number Diff line number Diff line Loading @@ -744,7 +744,7 @@ public class ToneGenerator * This method starts the playback of a tone of the specified type. * only one tone can play at a time: if a tone is playing while this method is called, * this tone is stopped and replaced by the one requested. * @param toneType The type of tone generate chosen from the following list: * @param toneType The type of tone generated chosen from the following list: * <ul> * <li>{@link #TONE_DTMF_0} * <li>{@link #TONE_DTMF_1} Loading Loading @@ -846,7 +846,18 @@ public class ToneGenerator * </ul> * @see #ToneGenerator(int, int) */ public native boolean startTone(int toneType); public boolean startTone(int toneType) { return startTone(toneType, -1); } /** * This method starts the playback of a tone of the specified type for the specified duration. * @param toneType The type of tone generated @see #startTone(int). * @param durationMs The tone duration in milliseconds. If the tone is limited in time by definition, * the actual duration will be the minimum of durationMs and the defined tone duration. Setting durationMs to -1, * is equivalent to calling #startTone(int). */ public native boolean startTone(int toneType, int durationMs); /** * This method stops the tone currently playing playback. Loading Loading
api/current.xml +15 −0 Original line number Diff line number Diff line Loading @@ -78333,6 +78333,19 @@ visibility="public" > </method> <method name="startTone" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="toneType" type="int"> </parameter> </method> <method name="startTone" return="boolean" abstract="false" Loading @@ -78345,6 +78358,8 @@ > <parameter name="toneType" type="int"> </parameter> <parameter name="durationMs" type="int"> </parameter> </method> <method name="stopTone" return="void"
core/jni/android_media_ToneGenerator.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ struct fields_t { }; static fields_t fields; static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, jint toneType) { static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, jint toneType, jint durationMs) { LOGV("android_media_ToneGenerator_startTone: %x\n", (int)thiz); ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(thiz, Loading @@ -48,7 +48,7 @@ static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, return false; } return lpToneGen->startTone(toneType); return lpToneGen->startTone(toneType, durationMs); } static void android_media_ToneGenerator_stopTone(JNIEnv *env, jobject thiz) { Loading Loading @@ -120,7 +120,7 @@ static void android_media_ToneGenerator_native_finalize(JNIEnv *env, // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { { "startTone", "(I)Z", (void *)android_media_ToneGenerator_startTone }, { "startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone }, { "stopTone", "()V", (void *)android_media_ToneGenerator_stopTone }, { "release", "()V", (void *)android_media_ToneGenerator_release }, { "native_setup", "(II)V", (void *)android_media_ToneGenerator_native_setup }, Loading
include/media/ToneGenerator.h +2 −1 Original line number Diff line number Diff line Loading @@ -154,7 +154,7 @@ public: ToneGenerator(int streamType, float volume); ~ToneGenerator(); bool startTone(int toneType); bool startTone(int toneType, int durationMs = -1); void stopTone(); bool isInited() { return (mState == TONE_IDLE)?false:true;} Loading Loading @@ -246,6 +246,7 @@ private: // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded, // no crash will occur but tone sequence will show a glitch. unsigned int mMaxSmp; // Maximum number of audio samples played (maximun tone duration) unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[] unsigned short mCurCount; // Current sequence repeat count Loading
libs/audioflinger/AudioFlinger.cpp +63 −55 Original line number Diff line number Diff line Loading @@ -1160,7 +1160,7 @@ AudioFlinger::MixerThread::~MixerThread() bool AudioFlinger::MixerThread::threadLoop() { unsigned long sleepTime = kBufferRecoveryInUsecs; unsigned long sleepTime = 0; int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; Loading Loading @@ -1215,6 +1215,7 @@ bool AudioFlinger::MixerThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading @@ -1222,14 +1223,31 @@ bool AudioFlinger::MixerThread::threadLoop() enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove); } if (LIKELY(enabledTracks)) { // mix buffers... mAudioMixer->process(curBuf); // output audio to hardware if (mSuspended) { usleep(kMaxBufferRecoveryInUsecs); } else { if (LIKELY(enabledTracks)) { // mix buffers... mAudioMixer->process(curBuf); sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, write 0s to audio // hardware to avoid underrun. if (sleepTime < kMaxBufferRecoveryInUsecs) { usleep(kBufferRecoveryInUsecs); } else { memset (curBuf, 0, mixBufferSize); sleepTime = 0; } } // sleepTime == 0 means PCM data were written to mMixBuffer[] if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); Loading @@ -1237,24 +1255,11 @@ bool AudioFlinger::MixerThread::threadLoop() mNumWrites++; mInWrite = false; mStandby = false; nsecs_t temp = systemTime(); standbyTime = temp + kStandbyTimeInNsecs; nsecs_t delta = temp - mLastWriteTime; nsecs_t delta = systemTime() - mLastWriteTime; if (delta > maxPeriod) { LOGW("write blocked for %llu msecs", ns2ms(delta)); mNumDelayedWrites++; } sleepTime = kBufferRecoveryInUsecs; } } else { // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, the audio // hardware will zero-fill for us. // LOGV("thread %p no buffers - usleep(%lu)", this, sleepTime); usleep(sleepTime); if (sleepTime < kMaxBufferRecoveryInUsecs) { sleepTime += kBufferRecoveryInUsecs; } } Loading Loading @@ -1568,7 +1573,7 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread() bool AudioFlinger::DirectOutputThread::threadLoop() { unsigned long sleepTime = kBufferRecoveryInUsecs; unsigned long sleepTime = 0; sp<Track> trackToRemove; sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); Loading Loading @@ -1618,6 +1623,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = 0; continue; } } Loading Loading @@ -1710,13 +1716,15 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } } // output audio to hardware if (mSuspended) { usleep(kMaxBufferRecoveryInUsecs); } else { if (activeTrack != 0) { AudioBufferProvider::Buffer buffer; size_t frameCount = mFrameCount; curBuf = (int8_t *)mMixBuffer; // output audio to hardware mLastWriteTime = systemTime(); mInWrite = true; while(frameCount) { buffer.frameCount = frameCount; activeTrack->getNextBuffer(&buffer); Loading @@ -1729,27 +1737,27 @@ bool AudioFlinger::DirectOutputThread::threadLoop() curBuf += buffer.frameCount * mFrameSize; activeTrack->releaseBuffer(&buffer); } if (mSuspended) { usleep(kMaxBufferRecoveryInUsecs); sleepTime = 0; standbyTime = systemTime() + kStandbyTimeInNsecs; } else { sleepTime += kBufferRecoveryInUsecs; if (sleepTime < kMaxBufferRecoveryInUsecs) { usleep(kBufferRecoveryInUsecs); } else { memset (mMixBuffer, 0, mFrameCount * mFrameSize); sleepTime = 0; } } // sleepTime == 0 means PCM data were written to mMixBuffer[] if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize); if (bytesWritten) mBytesWritten += bytesWritten; mNumWrites++; mInWrite = false; mStandby = false; nsecs_t temp = systemTime(); standbyTime = temp + kStandbyTimeInNsecs; sleepTime = kBufferRecoveryInUsecs; } } else { // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, the audio // hardware will zero-fill for us. //LOGV("no buffers - usleep(%lu)", sleepTime); usleep(sleepTime); if (sleepTime < kMaxBufferRecoveryInUsecs) { sleepTime += kBufferRecoveryInUsecs; } } Loading
media/java/android/media/ToneGenerator.java +13 −2 Original line number Diff line number Diff line Loading @@ -744,7 +744,7 @@ public class ToneGenerator * This method starts the playback of a tone of the specified type. * only one tone can play at a time: if a tone is playing while this method is called, * this tone is stopped and replaced by the one requested. * @param toneType The type of tone generate chosen from the following list: * @param toneType The type of tone generated chosen from the following list: * <ul> * <li>{@link #TONE_DTMF_0} * <li>{@link #TONE_DTMF_1} Loading Loading @@ -846,7 +846,18 @@ public class ToneGenerator * </ul> * @see #ToneGenerator(int, int) */ public native boolean startTone(int toneType); public boolean startTone(int toneType) { return startTone(toneType, -1); } /** * This method starts the playback of a tone of the specified type for the specified duration. * @param toneType The type of tone generated @see #startTone(int). * @param durationMs The tone duration in milliseconds. If the tone is limited in time by definition, * the actual duration will be the minimum of durationMs and the defined tone duration. Setting durationMs to -1, * is equivalent to calling #startTone(int). */ public native boolean startTone(int toneType, int durationMs); /** * This method stops the tone currently playing playback. Loading