• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "AudioStreamTrack"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <stdint.h>
22 #include <media/AudioTrack.h>
23 
24 #include <aaudio/AAudio.h>
25 #include <system/audio.h>
26 #include "utility/AudioClock.h"
27 #include "legacy/AudioStreamLegacy.h"
28 #include "legacy/AudioStreamTrack.h"
29 #include "utility/FixedBlockReader.h"
30 
31 using namespace android;
32 using namespace aaudio;
33 
34 // Arbitrary and somewhat generous number of bursts.
35 #define DEFAULT_BURSTS_PER_BUFFER_CAPACITY     8
36 
37 /*
38  * Create a stream that uses the AudioTrack.
39  */
AudioStreamTrack()40 AudioStreamTrack::AudioStreamTrack()
41     : AudioStreamLegacy()
42     , mFixedBlockReader(*this)
43 {
44 }
45 
~AudioStreamTrack()46 AudioStreamTrack::~AudioStreamTrack()
47 {
48     const aaudio_stream_state_t state = getState();
49     bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED);
50     ALOGE_IF(bad, "stream not closed, in state %d", state);
51 }
52 
open(const AudioStreamBuilder & builder)53 aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
54 {
55     aaudio_result_t result = AAUDIO_OK;
56 
57     result = AudioStream::open(builder);
58     if (result != OK) {
59         return result;
60     }
61 
62     const aaudio_session_id_t requestedSessionId = builder.getSessionId();
63     const audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
64 
65     // Try to create an AudioTrack
66     // Use stereo if unspecified.
67     int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
68                               ? 2 : getSamplesPerFrame();
69     audio_channel_mask_t channelMask = samplesPerFrame <= 2 ?
70                             audio_channel_out_mask_from_count(samplesPerFrame) :
71                             audio_channel_mask_for_index_assignment_from_count(samplesPerFrame);
72 
73     audio_output_flags_t flags;
74     aaudio_performance_mode_t perfMode = getPerformanceMode();
75     switch(perfMode) {
76         case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
77             // Bypass the normal mixer and go straight to the FAST mixer.
78             // If the app asks for a sessionId then it means they want to use effects.
79             // So don't use RAW flag.
80             flags = (audio_output_flags_t) ((requestedSessionId == AAUDIO_SESSION_ID_NONE)
81                     ? (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW)
82                     : (AUDIO_OUTPUT_FLAG_FAST));
83             break;
84 
85         case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
86             // This uses a mixer that wakes up less often than the FAST mixer.
87             flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
88             break;
89 
90         case AAUDIO_PERFORMANCE_MODE_NONE:
91         default:
92             // No flags. Use a normal mixer in front of the FAST mixer.
93             flags = AUDIO_OUTPUT_FLAG_NONE;
94             break;
95     }
96 
97     size_t frameCount = (size_t)builder.getBufferCapacity();
98 
99     int32_t notificationFrames = 0;
100 
101     const audio_format_t format = (getFormat() == AUDIO_FORMAT_DEFAULT)
102             ? AUDIO_FORMAT_PCM_FLOAT
103             : getFormat();
104 
105     // Setup the callback if there is one.
106     AudioTrack::callback_t callback = nullptr;
107     void *callbackData = nullptr;
108     // Note that TRANSFER_SYNC does not allow FAST track
109     AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC;
110     if (builder.getDataCallbackProc() != nullptr) {
111         streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK;
112         callback = getLegacyCallback();
113         callbackData = this;
114 
115         // If the total buffer size is unspecified then base the size on the burst size.
116         if (frameCount == 0
117                 && ((flags & AUDIO_OUTPUT_FLAG_FAST) != 0)) {
118             // Take advantage of a special trick that allows us to create a buffer
119             // that is some multiple of the burst size.
120             notificationFrames = 0 - DEFAULT_BURSTS_PER_BUFFER_CAPACITY;
121         } else {
122             notificationFrames = builder.getFramesPerDataCallback();
123         }
124     }
125     mCallbackBufferSize = builder.getFramesPerDataCallback();
126 
127     ALOGD("open(), request notificationFrames = %d, frameCount = %u",
128           notificationFrames, (uint)frameCount);
129 
130     // Don't call mAudioTrack->setDeviceId() because it will be overwritten by set()!
131     audio_port_handle_t selectedDeviceId = (getDeviceId() == AAUDIO_UNSPECIFIED)
132                                            ? AUDIO_PORT_HANDLE_NONE
133                                            : getDeviceId();
134 
135     const audio_content_type_t contentType =
136             AAudioConvert_contentTypeToInternal(builder.getContentType());
137     const audio_usage_t usage =
138             AAudioConvert_usageToInternal(builder.getUsage());
139     const audio_flags_mask_t attributesFlags =
140         AAudioConvert_allowCapturePolicyToAudioFlagsMask(builder.getAllowedCapturePolicy());
141 
142     const audio_attributes_t attributes = {
143             .content_type = contentType,
144             .usage = usage,
145             .source = AUDIO_SOURCE_DEFAULT, // only used for recording
146             .flags = attributesFlags,
147             .tags = ""
148     };
149 
150     mAudioTrack = new AudioTrack();
151     mAudioTrack->set(
152             AUDIO_STREAM_DEFAULT,  // ignored because we pass attributes below
153             getSampleRate(),
154             format,
155             channelMask,
156             frameCount,
157             flags,
158             callback,
159             callbackData,
160             notificationFrames,
161             0,       // DEFAULT sharedBuffer*/,
162             false,   // DEFAULT threadCanCallJava
163             sessionId,
164             streamTransferType,
165             NULL,    // DEFAULT audio_offload_info_t
166             AUDIO_UID_INVALID, // DEFAULT uid
167             -1,      // DEFAULT pid
168             &attributes,
169             // WARNING - If doNotReconnect set true then audio stops after plugging and unplugging
170             // headphones a few times.
171             false,   // DEFAULT doNotReconnect,
172             1.0f,    // DEFAULT maxRequiredSpeed
173             selectedDeviceId
174     );
175 
176     // Set it here so it can be logged by the destructor if the open failed.
177     mAudioTrack->setCallerName(kCallerName);
178 
179     // Did we get a valid track?
180     status_t status = mAudioTrack->initCheck();
181     if (status != NO_ERROR) {
182         releaseCloseFinal();
183         ALOGE("open(), initCheck() returned %d", status);
184         return AAudioConvert_androidToAAudioResult(status);
185     }
186 
187     mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
188             + std::to_string(mAudioTrack->getPortId());
189 
190     doSetVolume();
191 
192     // Get the actual values from the AudioTrack.
193     setSamplesPerFrame(mAudioTrack->channelCount());
194     setFormat(mAudioTrack->format());
195     setDeviceFormat(mAudioTrack->format());
196 
197     int32_t actualSampleRate = mAudioTrack->getSampleRate();
198     ALOGW_IF(actualSampleRate != getSampleRate(),
199              "open() sampleRate changed from %d to %d",
200              getSampleRate(), actualSampleRate);
201     setSampleRate(actualSampleRate);
202 
203     // We may need to pass the data through a block size adapter to guarantee constant size.
204     if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
205         // This may need to change if we add format conversion before
206         // the block size adaptation.
207         mBlockAdapterBytesPerFrame = getBytesPerFrame();
208         int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
209         mFixedBlockReader.open(callbackSizeBytes);
210         mBlockAdapter = &mFixedBlockReader;
211     } else {
212         mBlockAdapter = nullptr;
213     }
214 
215     setState(AAUDIO_STREAM_STATE_OPEN);
216     setDeviceId(mAudioTrack->getRoutedDeviceId());
217 
218     aaudio_session_id_t actualSessionId =
219             (requestedSessionId == AAUDIO_SESSION_ID_NONE)
220             ? AAUDIO_SESSION_ID_NONE
221             : (aaudio_session_id_t) mAudioTrack->getSessionId();
222     setSessionId(actualSessionId);
223 
224     mInitialBufferCapacity = getBufferCapacity();
225     mInitialFramesPerBurst = getFramesPerBurst();
226 
227     mAudioTrack->addAudioDeviceCallback(this);
228 
229     // Update performance mode based on the actual stream flags.
230     // For example, if the sample rate is not allowed then you won't get a FAST track.
231     audio_output_flags_t actualFlags = mAudioTrack->getFlags();
232     aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
233     // We may not get the RAW flag. But as long as we get the FAST flag we can call it LOW_LATENCY.
234     if ((actualFlags & AUDIO_OUTPUT_FLAG_FAST) != 0) {
235         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
236     } else if ((actualFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
237         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
238     }
239     setPerformanceMode(actualPerformanceMode);
240 
241     setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy
242 
243     // Log warning if we did not get what we asked for.
244     ALOGW_IF(actualFlags != flags,
245              "open() flags changed from 0x%08X to 0x%08X",
246              flags, actualFlags);
247     ALOGW_IF(actualPerformanceMode != perfMode,
248              "open() perfMode changed from %d to %d",
249              perfMode, actualPerformanceMode);
250 
251     return AAUDIO_OK;
252 }
253 
release_l()254 aaudio_result_t AudioStreamTrack::release_l() {
255     if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
256         status_t err = mAudioTrack->removeAudioDeviceCallback(this);
257         ALOGE_IF(err, "%s() removeAudioDeviceCallback returned %d", __func__, err);
258         logReleaseBufferState();
259         // Data callbacks may still be running!
260         return AudioStream::release_l();
261     } else {
262         return AAUDIO_OK; // already released
263     }
264 }
265 
close_l()266 void AudioStreamTrack::close_l() {
267     // Stop callbacks before deleting mFixedBlockReader memory.
268     mAudioTrack.clear();
269     // Do not close mFixedBlockReader because a data callback
270     // thread might still be running if someone else has a reference
271     // to mAudioRecord.
272     // It has a unique_ptr to its buffer so it will clean up by itself.
273     AudioStream::close_l();
274 }
275 
processCallback(int event,void * info)276 void AudioStreamTrack::processCallback(int event, void *info) {
277 
278     switch (event) {
279         case AudioTrack::EVENT_MORE_DATA:
280             processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
281             break;
282 
283             // Stream got rerouted so we disconnect.
284         case AudioTrack::EVENT_NEW_IAUDIOTRACK:
285             // request stream disconnect if the restored AudioTrack has properties not matching
286             // what was requested initially
287             if (mAudioTrack->channelCount() != getSamplesPerFrame()
288                     || mAudioTrack->format() != getFormat()
289                     || mAudioTrack->getSampleRate() != getSampleRate()
290                     || mAudioTrack->getRoutedDeviceId() != getDeviceId()
291                     || getBufferCapacity() != mInitialBufferCapacity
292                     || getFramesPerBurst() != mInitialFramesPerBurst) {
293                 processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
294             }
295             break;
296 
297         default:
298             break;
299     }
300     return;
301 }
302 
requestStart()303 aaudio_result_t AudioStreamTrack::requestStart() {
304     if (mAudioTrack.get() == nullptr) {
305         ALOGE("requestStart() no AudioTrack");
306         return AAUDIO_ERROR_INVALID_STATE;
307     }
308     // Get current position so we can detect when the track is playing.
309     status_t err = mAudioTrack->getPosition(&mPositionWhenStarting);
310     if (err != OK) {
311         return AAudioConvert_androidToAAudioResult(err);
312     }
313 
314     // Enable callback before starting AudioTrack to avoid shutting
315     // down because of a race condition.
316     mCallbackEnabled.store(true);
317     aaudio_stream_state_t originalState = getState();
318     // Set before starting the callback so that we are in the correct state
319     // before updateStateMachine() can be called by the callback.
320     setState(AAUDIO_STREAM_STATE_STARTING);
321     err = mAudioTrack->start();
322     if (err != OK) {
323         mCallbackEnabled.store(false);
324         setState(originalState);
325         return AAudioConvert_androidToAAudioResult(err);
326     }
327     return AAUDIO_OK;
328 }
329 
requestPause()330 aaudio_result_t AudioStreamTrack::requestPause() {
331     if (mAudioTrack.get() == nullptr) {
332         ALOGE("%s() no AudioTrack", __func__);
333         return AAUDIO_ERROR_INVALID_STATE;
334     }
335 
336     setState(AAUDIO_STREAM_STATE_PAUSING);
337     mAudioTrack->pause();
338     mCallbackEnabled.store(false);
339     status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
340     if (err != OK) {
341         return AAudioConvert_androidToAAudioResult(err);
342     }
343     return checkForDisconnectRequest(false);
344 }
345 
requestFlush()346 aaudio_result_t AudioStreamTrack::requestFlush() {
347     if (mAudioTrack.get() == nullptr) {
348         ALOGE("%s() no AudioTrack", __func__);
349         return AAUDIO_ERROR_INVALID_STATE;
350     }
351 
352     setState(AAUDIO_STREAM_STATE_FLUSHING);
353     incrementFramesRead(getFramesWritten() - getFramesRead());
354     mAudioTrack->flush();
355     mFramesRead.reset32(); // service reads frames, service position reset on flush
356     mTimestampPosition.reset32();
357     return AAUDIO_OK;
358 }
359 
requestStop()360 aaudio_result_t AudioStreamTrack::requestStop() {
361     if (mAudioTrack.get() == nullptr) {
362         ALOGE("%s() no AudioTrack", __func__);
363         return AAUDIO_ERROR_INVALID_STATE;
364     }
365 
366     setState(AAUDIO_STREAM_STATE_STOPPING);
367     mFramesRead.catchUpTo(getFramesWritten());
368     mTimestampPosition.catchUpTo(getFramesWritten());
369     mFramesRead.reset32(); // service reads frames, service position reset on stop
370     mTimestampPosition.reset32();
371     mAudioTrack->stop();
372     mCallbackEnabled.store(false);
373     return checkForDisconnectRequest(false);;
374 }
375 
updateStateMachine()376 aaudio_result_t AudioStreamTrack::updateStateMachine()
377 {
378     status_t err;
379     aaudio_wrapping_frames_t position;
380     switch (getState()) {
381     // TODO add better state visibility to AudioTrack
382     case AAUDIO_STREAM_STATE_STARTING:
383         if (mAudioTrack->hasStarted()) {
384             setState(AAUDIO_STREAM_STATE_STARTED);
385         }
386         break;
387     case AAUDIO_STREAM_STATE_PAUSING:
388         if (mAudioTrack->stopped()) {
389             err = mAudioTrack->getPosition(&position);
390             if (err != OK) {
391                 return AAudioConvert_androidToAAudioResult(err);
392             } else if (position == mPositionWhenPausing) {
393                 // Has stream really stopped advancing?
394                 setState(AAUDIO_STREAM_STATE_PAUSED);
395             }
396             mPositionWhenPausing = position;
397         }
398         break;
399     case AAUDIO_STREAM_STATE_FLUSHING:
400         {
401             err = mAudioTrack->getPosition(&position);
402             if (err != OK) {
403                 return AAudioConvert_androidToAAudioResult(err);
404             } else if (position == 0) {
405                 // TODO Advance frames read to match written.
406                 setState(AAUDIO_STREAM_STATE_FLUSHED);
407             }
408         }
409         break;
410     case AAUDIO_STREAM_STATE_STOPPING:
411         if (mAudioTrack->stopped()) {
412             setState(AAUDIO_STREAM_STATE_STOPPED);
413         }
414         break;
415     default:
416         break;
417     }
418     return AAUDIO_OK;
419 }
420 
write(const void * buffer,int32_t numFrames,int64_t timeoutNanoseconds)421 aaudio_result_t AudioStreamTrack::write(const void *buffer,
422                                       int32_t numFrames,
423                                       int64_t timeoutNanoseconds)
424 {
425     int32_t bytesPerFrame = getBytesPerFrame();
426     int32_t numBytes;
427     aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes);
428     if (result != AAUDIO_OK) {
429         return result;
430     }
431 
432     if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
433         return AAUDIO_ERROR_DISCONNECTED;
434     }
435 
436     // TODO add timeout to AudioTrack
437     bool blocking = timeoutNanoseconds > 0;
438     ssize_t bytesWritten = mAudioTrack->write(buffer, numBytes, blocking);
439     if (bytesWritten == WOULD_BLOCK) {
440         return 0;
441     } else if (bytesWritten < 0) {
442         ALOGE("invalid write, returned %d", (int)bytesWritten);
443         // in this context, a DEAD_OBJECT is more likely to be a disconnect notification due to
444         // AudioTrack invalidation
445         if (bytesWritten == DEAD_OBJECT) {
446             setState(AAUDIO_STREAM_STATE_DISCONNECTED);
447             return AAUDIO_ERROR_DISCONNECTED;
448         }
449         return AAudioConvert_androidToAAudioResult(bytesWritten);
450     }
451     int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame);
452     incrementFramesWritten(framesWritten);
453 
454     result = updateStateMachine();
455     if (result != AAUDIO_OK) {
456         return result;
457     }
458 
459     return framesWritten;
460 }
461 
setBufferSize(int32_t requestedFrames)462 aaudio_result_t AudioStreamTrack::setBufferSize(int32_t requestedFrames)
463 {
464     // Do not ask for less than one burst.
465     if (requestedFrames < getFramesPerBurst()) {
466         requestedFrames = getFramesPerBurst();
467     }
468     ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames);
469     if (result < 0) {
470         return AAudioConvert_androidToAAudioResult(result);
471     } else {
472         return result;
473     }
474 }
475 
getBufferSize() const476 int32_t AudioStreamTrack::getBufferSize() const
477 {
478     return static_cast<int32_t>(mAudioTrack->getBufferSizeInFrames());
479 }
480 
getBufferCapacity() const481 int32_t AudioStreamTrack::getBufferCapacity() const
482 {
483     return static_cast<int32_t>(mAudioTrack->frameCount());
484 }
485 
getXRunCount() const486 int32_t AudioStreamTrack::getXRunCount() const
487 {
488     return static_cast<int32_t>(mAudioTrack->getUnderrunCount());
489 }
490 
getFramesPerBurst() const491 int32_t AudioStreamTrack::getFramesPerBurst() const
492 {
493     return static_cast<int32_t>(mAudioTrack->getNotificationPeriodInFrames());
494 }
495 
getFramesRead()496 int64_t AudioStreamTrack::getFramesRead() {
497     aaudio_wrapping_frames_t position;
498     status_t result;
499     switch (getState()) {
500     case AAUDIO_STREAM_STATE_STARTING:
501     case AAUDIO_STREAM_STATE_STARTED:
502     case AAUDIO_STREAM_STATE_STOPPING:
503     case AAUDIO_STREAM_STATE_PAUSING:
504     case AAUDIO_STREAM_STATE_PAUSED:
505         result = mAudioTrack->getPosition(&position);
506         if (result == OK) {
507             mFramesRead.update32(position);
508         }
509         break;
510     default:
511         break;
512     }
513     return AudioStreamLegacy::getFramesRead();
514 }
515 
getTimestamp(clockid_t clockId,int64_t * framePosition,int64_t * timeNanoseconds)516 aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
517                                      int64_t *framePosition,
518                                      int64_t *timeNanoseconds) {
519     ExtendedTimestamp extendedTimestamp;
520     status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
521     if (status == WOULD_BLOCK) {
522         return AAUDIO_ERROR_INVALID_STATE;
523     } if (status != NO_ERROR) {
524         return AAudioConvert_androidToAAudioResult(status);
525     }
526     int64_t position = 0;
527     int64_t nanoseconds = 0;
528     aaudio_result_t result = getBestTimestamp(clockId, &position,
529                                               &nanoseconds, &extendedTimestamp);
530     if (result == AAUDIO_OK) {
531         if (position < getFramesWritten()) {
532             *framePosition = position;
533             *timeNanoseconds = nanoseconds;
534             return result;
535         } else {
536             return AAUDIO_ERROR_INVALID_STATE; // TODO review, documented but not consistent
537         }
538     }
539     return result;
540 }
541 
doSetVolume()542 status_t AudioStreamTrack::doSetVolume() {
543     status_t status = NO_INIT;
544     if (mAudioTrack.get() != nullptr) {
545         float volume = getDuckAndMuteVolume();
546         mAudioTrack->setVolume(volume, volume);
547         status = NO_ERROR;
548     }
549     return status;
550 }
551 
552 #if AAUDIO_USE_VOLUME_SHAPER
553 
554 using namespace android::media::VolumeShaper;
555 
applyVolumeShaper(const VolumeShaper::Configuration & configuration,const VolumeShaper::Operation & operation)556 binder::Status AudioStreamTrack::applyVolumeShaper(
557         const VolumeShaper::Configuration& configuration,
558         const VolumeShaper::Operation& operation) {
559 
560     sp<VolumeShaper::Configuration> spConfiguration = new VolumeShaper::Configuration(configuration);
561     sp<VolumeShaper::Operation> spOperation = new VolumeShaper::Operation(operation);
562 
563     if (mAudioTrack.get() != nullptr) {
564         ALOGD("applyVolumeShaper() from IPlayer");
565         binder::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
566         if (status < 0) { // a non-negative value is the volume shaper id.
567             ALOGE("applyVolumeShaper() failed with status %d", status);
568         }
569         return binder::Status::fromStatusT(status);
570     } else {
571         ALOGD("applyVolumeShaper()"
572                       " no AudioTrack for volume control from IPlayer");
573         return binder::Status::ok();
574     }
575 }
576 #endif
577