当前位置:   article > 正文

Android Audio代码分析15 - testPlaybackHeadPositionAfterFlush_unable to retrieve audiotrack pointer for stop()

unable to retrieve audiotrack pointer for stop()
上次看到的testPlaybackHeadPositionIncrease函数中,先play了一会,然后获取position。
今天看个复杂点的,先play,然后stop,之后在flush,此时再获取position会是什么情况呢?


*****************************************源码*************************************************
  1. //Test case 3: getPlaybackHeadPosition() is 0 after flush();
  2. @LargeTest
  3. public void testPlaybackHeadPositionAfterFlush() throws Exception {
  4. // constants for test
  5. final String TEST_NAME = "testPlaybackHeadPositionAfterFlush";
  6. final int TEST_SR = 22050;
  7. final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
  8. final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
  9. final int TEST_MODE = AudioTrack.MODE_STREAM;
  10. final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
  11. //-------- initialization --------------
  12. int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
  13. AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
  14. minBuffSize, TEST_MODE);
  15. byte data[] = new byte[minBuffSize/2];
  16. //-------- test --------------
  17. assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
  18. track.write(data, 0, data.length);
  19. track.write(data, 0, data.length);
  20. track.play();
  21. Thread.sleep(100);
  22. track.stop();
  23. track.flush();
  24. log(TEST_NAME, "position ="+ track.getPlaybackHeadPosition());
  25. assertTrue(TEST_NAME, track.getPlaybackHeadPosition() == 0);
  26. //-------- tear down --------------
  27. track.release();
  28. }

**********************************************************************************************
源码路径:
frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioTrackTest.java


#######################说明################################
  1. //Test case 3: getPlaybackHeadPosition() is 0 after flush();
  2. @LargeTest
  3. public void testPlaybackHeadPositionAfterFlush() throws Exception {
  4. // constants for test
  5. final String TEST_NAME = "testPlaybackHeadPositionAfterFlush";
  6. final int TEST_SR = 22050;
  7. final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
  8. final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
  9. final int TEST_MODE = AudioTrack.MODE_STREAM;
  10. final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
  11. //-------- initialization --------------
  12. int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
  13. AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
  14. minBuffSize, TEST_MODE);
  15. byte data[] = new byte[minBuffSize/2];
  16. //-------- test --------------
  17. assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
  18. track.write(data, 0, data.length);
  19. track.write(data, 0, data.length);
  20. track.play();
  21. Thread.sleep(100);
  22. track.stop();
  23. // ++++++++++++++++++++++++++++stop++++++++++++++++++++++++++++++++++++
  24. /**
  25. * Stops playing the audio data.
  26. * @throws IllegalStateException
  27. */
  28. public void stop()
  29. throws IllegalStateException {
  30. if (mState != STATE_INITIALIZED) {
  31. throw(new IllegalStateException("stop() called on uninitialized AudioTrack."));
  32. }
  33. // stop playing
  34. synchronized(mPlayStateLock) {
  35. native_stop();
  36. // ++++++++++++++++++++++++++++++android_media_AudioTrack_stop++++++++++++++++++++++++++++++++++
  37. static void
  38. android_media_AudioTrack_stop(JNIEnv *env, jobject thiz)
  39. {
  40. AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
  41. thiz, javaAudioTrackFields.nativeTrackInJavaObj);
  42. if (lpTrack == NULL ) {
  43. jniThrowException(env, "java/lang/IllegalStateException",
  44. "Unable to retrieve AudioTrack pointer for stop()");
  45. return;
  46. }
  47. lpTrack->stop();
  48. // +++++++++++++++++++++++++++++++AudioTrack::stop+++++++++++++++++++++++++++++++++
  49. void AudioTrack::stop()
  50. {
  51. // mAudioTrackThread在函数AudioTrack::set中被赋值。
  52. // mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
  53. sp<AudioTrackThread> t = mAudioTrackThread;
  54. LOGV("stop %p", this);
  55. if (t != 0) {
  56. t->mLock.lock();
  57. }
  58. if (android_atomic_and(~1, &mActive) == 1) {
  59. mCblk->cv.signal();
  60. // mAudioTrack在函数AudioTrack::createTrack中被赋值,其最终指向的其实是一个TrackHandle对象
  61. mAudioTrack->stop();
  62. // ++++++++++++++++++++++++++++++AudioFlinger::TrackHandle::stop++++++++++++++++++++++++++++++++++
  63. void AudioFlinger::TrackHandle::stop() {
  64. mTrack->stop();
  65. // +++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::Track::stop+++++++++++++++++++++++++++++++++++
  66. void AudioFlinger::PlaybackThread::Track::stop()
  67. {
  68. LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
  69. // 在Track的构造函数中赋值,指向创建该Track对象的PlaybackThread
  70. sp<ThreadBase> thread = mThread.promote();
  71. if (thread != 0) {
  72. Mutex::Autolock _l(thread->mLock);
  73. int state = mState;
  74. if (mState > STOPPED) {
  75. // ++++++++++++++++++++++++++++++++track_state++++++++++++++++++++++++++++++++
  76. enum track_state {
  77. IDLE,
  78. TERMINATED,
  79. STOPPED,
  80. RESUMING,
  81. ACTIVE,
  82. PAUSING,
  83. PAUSED
  84. };
  85. // --------------------------------track_state--------------------------------
  86. mState = STOPPED;
  87. // If the track is not active (PAUSED and buffers full), flush buffers
  88. PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
  89. if (playbackThread->mActiveTracks.indexOf(this) < 0) {
  90. reset();
  91. // ++++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::Track::reset++++++++++++++++++++++++++++++++++
  92. void AudioFlinger::PlaybackThread::Track::reset()
  93. {
  94. // Do not reset twice to avoid discarding data written just after a flush and before
  95. // the audioflinger thread detects the track is stopped.
  96. if (!mResetDone) {
  97. TrackBase::reset();
  98. // ++++++++++++++++++++++++++++++AudioFlinger::ThreadBase::TrackBase::reset++++++++++++++++++++++++++++++++++
  99. void AudioFlinger::ThreadBase::TrackBase::reset() {
  100. audio_track_cblk_t* cblk = this->cblk();
  101. cblk->user = 0;
  102. cblk->server = 0;
  103. cblk->userBase = 0;
  104. cblk->serverBase = 0;
  105. mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
  106. LOGV("TrackBase::reset");
  107. }
  108. // ------------------------------AudioFlinger::ThreadBase::TrackBase::reset----------------------------------
  109. // Force underrun condition to avoid false underrun callback until first data is
  110. // written to buffer
  111. mCblk->flags |= CBLK_UNDERRUN_ON;
  112. mCblk->flags &= ~CBLK_FORCEREADY_MSK;
  113. mFillingUpStatus = FS_FILLING;
  114. mResetDone = true;
  115. }
  116. }
  117. // ------------------------------AudioFlinger::PlaybackThread::Track::reset----------------------------------
  118. }
  119. LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
  120. }
  121. if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
  122. thread->mLock.unlock();
  123. AudioSystem::stopOutput(thread->id(),
  124. (AudioSystem::stream_type)mStreamType,
  125. mSessionId);
  126. // ++++++++++++++++++++++++++++++AudioSystem::stopOutput++++++++++++++++++++++++++++++++++
  127. status_t AudioSystem::stopOutput(audio_io_handle_t output,
  128. AudioSystem::stream_type stream,
  129. int session)
  130. {
  131. const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
  132. if (aps == 0) return PERMISSION_DENIED;
  133. return aps->stopOutput(output, stream, session);
  134. // +++++++++++++++++++++++++++++++++AudioPolicyService::stopOutput+++++++++++++++++++++++++++++++
  135. status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
  136. AudioSystem::stream_type stream,
  137. int session)
  138. {
  139. if (mpPolicyManager == NULL) {
  140. return NO_INIT;
  141. }
  142. LOGV("stopOutput() tid %d", gettid());
  143. Mutex::Autolock _l(mLock);
  144. return mpPolicyManager->stopOutput(output, stream, session);
  145. // ++++++++++++++++++++++++++++++AudioPolicyManagerBase::stopOutput++++++++++++++++++++++++++++++++++
  146. status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
  147. AudioSystem::stream_type stream,
  148. int session)
  149. {
  150. LOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
  151. ssize_t index = mOutputs.indexOfKey(output);
  152. if (index < 0) {
  153. LOGW("stopOutput() unknow output %d", output);
  154. return BAD_VALUE;
  155. }
  156. AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
  157. routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
  158. // handle special case for sonification while in call
  159. if (isInCall()) {
  160. handleIncallSonification(stream, false, false);
  161. }
  162. if (outputDesc->mRefCount[stream] > 0) {
  163. // decrement usage count of this stream on the output
  164. outputDesc->changeRefCount(stream, -1);
  165. // ++++++++++++++++++++++++++++AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount++++++++++++++++++++++++++++++++++++
  166. void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
  167. {
  168. // forward usage count change to attached outputs
  169. if (isDuplicated()) {
  170. mOutput1->changeRefCount(stream, delta);
  171. mOutput2->changeRefCount(stream, delta);
  172. }
  173. if ((delta + (int)mRefCount[stream]) < 0) {
  174. LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
  175. mRefCount[stream] = 0;
  176. return;
  177. }
  178. // 函数AudioPolicyManagerBase::AudioOutputDescriptor::refCount会使用mRefCount
  179. mRefCount[stream] += delta;
  180. // +++++++++++++++++++++++++++++AudioPolicyManagerBase::AudioOutputDescriptor::refCount+++++++++++++++++++++++++++++++++++
  181. uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::refCount()
  182. {
  183. uint32_t refcount = 0;
  184. for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
  185. refcount += mRefCount[i];
  186. }
  187. return refcount;
  188. }
  189. // 函数AudioPolicyManagerBase::releaseOutput中有调用函数AudioPolicyManagerBase::AudioOutputDescriptor::refCount。
  190. // +++++++++++++++++++++++++++++AudioPolicyManagerBase::releaseOutput+++++++++++++++++++++++++++++++++++
  191. void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
  192. {
  193. LOGV("releaseOutput() %d", output);
  194. ssize_t index = mOutputs.indexOfKey(output);
  195. if (index < 0) {
  196. LOGW("releaseOutput() releasing unknown output %d", output);
  197. return;
  198. }
  199. #ifdef AUDIO_POLICY_TEST
  200. int testIndex = testOutputIndex(output);
  201. if (testIndex != 0) {
  202. AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
  203. if (outputDesc->refCount() == 0) {
  204. mpClientInterface->closeOutput(output);
  205. delete mOutputs.valueAt(index);
  206. mOutputs.removeItem(output);
  207. mTestOutputs[testIndex] = 0;
  208. }
  209. return;
  210. }
  211. #endif //AUDIO_POLICY_TEST
  212. // 如果没定义AUDIO_POLICY_TEST,只对设置了OUTPUT_FLAG_DIRECT标志的output做delete处理
  213. // 原因,其实在以前我们看AudioPolicyManagerBase::getOutput函数时已经看到了,
  214. // 在get output的时候,只有需要一个direct output的时候,才会调用函数AudioPolicyService::openOutput函数来打开一个output
  215. // 否则,只是将成员变量(在构造函数中打开的output)返回
  216. // 当然,我们没有考虑AUDIO_POLICY_TEST时的情况
  217. if (mOutputs.valueAt(index)->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
  218. // ++++++++++++++++++++++++++++++output_flags++++++++++++++++++++++++++++++++++
  219. // request to open a direct output with getOutput() (by opposition to sharing an output with other AudioTracks)
  220. enum output_flags {
  221. OUTPUT_FLAG_INDIRECT = 0x0,
  222. OUTPUT_FLAG_DIRECT = 0x1
  223. };
  224. // ------------------------------output_flags----------------------------------
  225. mpClientInterface->closeOutput(output);
  226. // +++++++++++++++++++++++++++++AudioPolicyService::closeOutput+++++++++++++++++++++++++++++++++++
  227. status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
  228. {
  229. sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
  230. if (af == 0) return PERMISSION_DENIED;
  231. return af->closeOutput(output);
  232. // +++++++++++++++++++++++++++AudioFlinger::closeOutput++++++++++++++++++++++++++++++++++++
  233. status_t AudioFlinger::closeOutput(int output)
  234. {
  235. // keep strong reference on the playback thread so that
  236. // it is not destroyed while exit() is executed
  237. sp <PlaybackThread> thread;
  238. {
  239. Mutex::Autolock _l(mLock);
  240. thread = checkPlaybackThread_l(output);
  241. if (thread == NULL) {
  242. return BAD_VALUE;
  243. }
  244. LOGV("closeOutput() %d", output);
  245. // 如果thread 为mixer
  246. // 删除所有DUPLICATING thread中包含的该thread
  247. if (thread->type() == PlaybackThread::MIXER) {
  248. for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
  249. if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
  250. DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
  251. dupThread->removeOutputTrack((MixerThread *)thread.get());
  252. }
  253. }
  254. }
  255. void *param2 = 0;
  256. audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
  257. mPlaybackThreads.removeItem(output);
  258. }
  259. thread->exit();
  260. // ++++++++++++++++++++++++++++AudioFlinger::ThreadBase::exit++++++++++++++++++++++++++++++++++++
  261. void AudioFlinger::ThreadBase::exit()
  262. {
  263. // keep a strong ref on ourself so that we wont get
  264. // destroyed in the middle of requestExitAndWait()
  265. sp <ThreadBase> strongMe = this;
  266. LOGV("ThreadBase::exit");
  267. {
  268. AutoMutex lock(&mLock);
  269. mExiting = true;
  270. requestExit();
  271. // +++++++++++++++++++++++++++++Thread::requestExit+++++++++++++++++++++++++++++++++++
  272. void Thread::requestExit()
  273. {
  274. // threadloop函数中会判断该成员变量,以判断是否要结束线程
  275. mExitPending = true;
  276. }
  277. // -----------------------------Thread::requestExit----------------------------------
  278. mWaitWorkCV.signal();
  279. }
  280. requestExitAndWait();
  281. // +++++++++++++++++++++++++++++Thread::requestExitAndWait+++++++++++++++++++++++++++++++++++
  282. status_t Thread::requestExitAndWait()
  283. {
  284. if (mThread == getThreadId()) {
  285. LOGW(
  286. "Thread (this=%p): don't call waitForExit() from this "
  287. "Thread object's thread. It's a guaranteed deadlock!",
  288. this);
  289. return WOULD_BLOCK;
  290. }
  291. requestExit();
  292. Mutex::Autolock _l(mLock);
  293. while (mRunning == true) {
  294. mThreadExitedCondition.wait(mLock);
  295. }
  296. mExitPending = false;
  297. return mStatus;
  298. }
  299. // -----------------------------Thread::requestExitAndWait-----------------------------------
  300. }
  301. // ----------------------------AudioFlinger::ThreadBase::exit------------------------------------
  302. if (thread->type() != PlaybackThread::DUPLICATING) {
  303. // output是在函数AudioFlinger::openOutput中调用函数mAudioHardware->openOutputStream打开的。
  304. mAudioHardware->closeOutputStream(thread->getOutput());
  305. // +++++++++++++++++++++++++++AudioHardwareALSA::closeOutputStream+++++++++++++++++++++++++++++++++++++
  306. void
  307. AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
  308. {
  309. AutoMutex lock(mLock);
  310. delete out;
  311. }
  312. // ---------------------------AudioHardwareALSA::closeOutputStream-------------------------------------
  313. }
  314. return NO_ERROR;
  315. }
  316. // ----------------------------AudioFlinger::closeOutput------------------------------------
  317. }
  318. // -----------------------------AudioPolicyService::closeOutput-----------------------------------
  319. delete mOutputs.valueAt(index);
  320. mOutputs.removeItem(output);
  321. }
  322. }
  323. // -----------------------------AudioPolicyManagerBase::releaseOutput-----------------------------------
  324. // -----------------------------AudioPolicyManagerBase::AudioOutputDescriptor::refCount-----------------------------------
  325. LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
  326. }
  327. // ----------------------------AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount------------------------------------
  328. // store time at which the last music track was stopped - see computeVolume()
  329. if (stream == AudioSystem::MUSIC) {
  330. mMusicStopTime = systemTime();
  331. }
  332. setOutputDevice(output, getNewDevice(output));
  333. #ifdef WITH_A2DP
  334. if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
  335. strategy == STRATEGY_SONIFICATION) {
  336. setStrategyMute(STRATEGY_MEDIA,
  337. false,
  338. mA2dpOutput,
  339. mOutputs.valueFor(mHardwareOutput)->mLatency*2);
  340. }
  341. #endif
  342. if (output != mHardwareOutput) {
  343. setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
  344. }
  345. return NO_ERROR;
  346. } else {
  347. LOGW("stopOutput() refcount is already 0 for output %d", output);
  348. return INVALID_OPERATION;
  349. }
  350. }
  351. // ------------------------------AudioPolicyManagerBase::stopOutput----------------------------------
  352. }
  353. // ---------------------------------AudioPolicyService::stopOutput-------------------------------
  354. }
  355. // ------------------------------AudioSystem::stopOutput----------------------------------
  356. thread->mLock.lock();
  357. }
  358. }
  359. }
  360. // -----------------------------AudioFlinger::PlaybackThread::Track::stop-----------------------------------
  361. }
  362. // ------------------------------AudioFlinger::TrackHandle::stop----------------------------------
  363. // Cancel loops (If we are in the middle of a loop, playback
  364. // would not stop until loopCount reaches 0).
  365. setLoop(0, 0, 0);
  366. // +++++++++++++++++++++++++++++AudioTrack::setLoop+++++++++++++++++++++++++++++++++++
  367. status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
  368. {
  369. audio_track_cblk_t* cblk = mCblk;
  370. Mutex::Autolock _l(cblk->lock);
  371. if (loopCount == 0) {
  372. cblk->loopStart = ULLONG_MAX;
  373. cblk->loopEnd = ULLONG_MAX;
  374. cblk->loopCount = 0;
  375. mLoopCount = 0;
  376. return NO_ERROR;
  377. }
  378. if (loopStart >= loopEnd ||
  379. loopEnd - loopStart > cblk->frameCount) {
  380. LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %lld", loopStart, loopEnd, loopCount, cblk->frameCount, cblk->user);
  381. return BAD_VALUE;
  382. }
  383. if ((mSharedBuffer != 0) && (loopEnd > cblk->frameCount)) {
  384. LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
  385. loopStart, loopEnd, cblk->frameCount);
  386. return BAD_VALUE;
  387. }
  388. cblk->loopStart = loopStart;
  389. cblk->loopEnd = loopEnd;
  390. cblk->loopCount = loopCount;
  391. mLoopCount = loopCount;
  392. return NO_ERROR;
  393. }
  394. // -----------------------------AudioTrack::setLoop-----------------------------------
  395. // the playback head position will reset to 0, so if a marker is set, we need
  396. // to activate it again
  397. mMarkerReached = false;
  398. // Force flush if a shared buffer is used otherwise audioflinger
  399. // will not stop before end of buffer is reached.
  400. if (mSharedBuffer != 0) {
  401. flush();
  402. // ++++++++++++++++++++++++++++AudioTrack::flush++++++++++++++++++++++++++++++++++++
  403. void AudioTrack::flush()
  404. {
  405. LOGV("flush");
  406. // clear playback marker and periodic update counter
  407. mMarkerPosition = 0;
  408. mMarkerReached = false;
  409. mUpdatePeriod = 0;
  410. if (!mActive) {
  411. mAudioTrack->flush();
  412. // ++++++++++++++++++++++++++++++AudioFlinger::TrackHandle::flush++++++++++++++++++++++++++++++++++
  413. void AudioFlinger::TrackHandle::flush() {
  414. mTrack->flush();
  415. // ++++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::Track::flush++++++++++++++++++++++++++++++++++
  416. void AudioFlinger::PlaybackThread::Track::flush()
  417. {
  418. LOGV("flush(%d)", mName);
  419. sp<ThreadBase> thread = mThread.promote();
  420. if (thread != 0) {
  421. Mutex::Autolock _l(thread->mLock);
  422. if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
  423. return;
  424. }
  425. // No point remaining in PAUSED state after a flush => go to
  426. // STOPPED state
  427. mState = STOPPED;
  428. mCblk->lock.lock();
  429. // NOTE: reset() will reset cblk->user and cblk->server with
  430. // the risk that at the same time, the AudioMixer is trying to read
  431. // data. In this case, getNextBuffer() would return a NULL pointer
  432. // as audio buffer => the AudioMixer code MUST always test that pointer
  433. // returned by getNextBuffer() is not NULL!
  434. // reset函数在stop函数中已经看过
  435. reset();
  436. mCblk->lock.unlock();
  437. }
  438. }
  439. // ------------------------------AudioFlinger::PlaybackThread::Track::flush----------------------------------
  440. }
  441. // ------------------------------AudioFlinger::TrackHandle::flush----------------------------------
  442. // Release AudioTrack callback thread in case it was waiting for new buffers
  443. // in AudioTrack::obtainBuffer()
  444. mCblk->cv.signal();
  445. }
  446. }
  447. // ----------------------------AudioTrack::flush------------------------------------
  448. }
  449. if (t != 0) {
  450. t->requestExit();
  451. } else {
  452. setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
  453. }
  454. }
  455. if (t != 0) {
  456. t->mLock.unlock();
  457. }
  458. }
  459. // -------------------------------AudioTrack::stop---------------------------------
  460. }
  461. // ------------------------------android_media_AudioTrack_stop----------------------------------
  462. mPlayState = PLAYSTATE_STOPPED;
  463. }
  464. }
  465. // ----------------------------stop------------------------------------
  466. track.flush();
  467. // ++++++++++++++++++++++++++++flush++++++++++++++++++++++++++++++++++++
  468. /**
  469. * Flushes the audio data currently queued for playback.
  470. */
  471. public void flush() {
  472. if (mState == STATE_INITIALIZED) {
  473. // flush the data in native layer
  474. native_flush();
  475. // ++++++++++++++++++++++++++++android_media_AudioTrack_flush++++++++++++++++++++++++++++++++++++
  476. static void
  477. android_media_AudioTrack_flush(JNIEnv *env, jobject thiz)
  478. {
  479. AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
  480. thiz, javaAudioTrackFields.nativeTrackInJavaObj);
  481. if (lpTrack == NULL ) {
  482. jniThrowException(env, "java/lang/IllegalStateException",
  483. "Unable to retrieve AudioTrack pointer for flush()");
  484. return;
  485. }
  486. lpTrack->flush();
  487. // +++++++++++++++++++++++++++++AudioTrack::flush+++++++++++++++++++++++++++++++++++
  488. void AudioTrack::flush()
  489. {
  490. LOGV("flush");
  491. // clear playback marker and periodic update counter
  492. mMarkerPosition = 0;
  493. mMarkerReached = false;
  494. mUpdatePeriod = 0;
  495. if (!mActive) {
  496. mAudioTrack->flush();
  497. // ++++++++++++++++++++++++++++AudioFlinger::TrackHandle::flush++++++++++++++++++++++++++++++++++++
  498. void AudioFlinger::TrackHandle::flush() {
  499. // 函数AudioFlinger::PlaybackThread::Track::flush在上面已经看过
  500. mTrack->flush();
  501. }
  502. // ----------------------------AudioFlinger::TrackHandle::flush------------------------------------
  503. // Release AudioTrack callback thread in case it was waiting for new buffers
  504. // in AudioTrack::obtainBuffer()
  505. mCblk->cv.signal();
  506. }
  507. }
  508. // -----------------------------AudioTrack::flush-----------------------------------
  509. }
  510. // ----------------------------android_media_AudioTrack_flush------------------------------------
  511. }
  512. }
  513. // ----------------------------flush------------------------------------
  514. log(TEST_NAME, "position ="+ track.getPlaybackHeadPosition());
  515. assertTrue(TEST_NAME, track.getPlaybackHeadPosition() == 0);
  516. //-------- tear down --------------
  517. track.release();
  518. }

###########################################################


&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
stop的时候:
若AudioTrack不是active的,在将其audio_track_cblk_t中的user, server等清0。
若是direct output,则将其close。


flush的时候:
会将audio_track_cblk_t中的user, server等清0。
因此,flush 之后再get position的话,肯定是0.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/318874
推荐阅读
相关标签
  

闽ICP备14008679号