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(mDeviceCallback);
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         mAudioTrack->removeAudioDeviceCallback(mDeviceCallback);
257         logReleaseBufferState();
258         // TODO Investigate why clear() causes a hang in test_various.cpp
259         // if I call close() from a data callback.
260         // But the same thing in AudioRecord is OK!
261         // mAudioTrack.clear();
262         mFixedBlockReader.close();
263         return AudioStream::release_l();
264     } else {
265         return AAUDIO_OK; // already released
266     }
267 }
268 
processCallback(int event,void * info)269 void AudioStreamTrack::processCallback(int event, void *info) {
270 
271     switch (event) {
272         case AudioTrack::EVENT_MORE_DATA:
273             processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
274             break;
275 
276             // Stream got rerouted so we disconnect.
277         case AudioTrack::EVENT_NEW_IAUDIOTRACK:
278             // request stream disconnect if the restored AudioTrack has properties not matching
279             // what was requested initially
280             if (mAudioTrack->channelCount() != getSamplesPerFrame()
281                     || mAudioTrack->format() != getFormat()
282                     || mAudioTrack->getSampleRate() != getSampleRate()
283                     || mAudioTrack->getRoutedDeviceId() != getDeviceId()
284                     || getBufferCapacity() != mInitialBufferCapacity
285                     || getFramesPerBurst() != mInitialFramesPerBurst) {
286                 processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
287             }
288             break;
289 
290         default:
291             break;
292     }
293     return;
294 }
295 
requestStart()296 aaudio_result_t AudioStreamTrack::requestStart() {
297     if (mAudioTrack.get() == nullptr) {
298         ALOGE("requestStart() no AudioTrack");
299         return AAUDIO_ERROR_INVALID_STATE;
300     }
301     // Get current position so we can detect when the track is playing.
302     status_t err = mAudioTrack->getPosition(&mPositionWhenStarting);
303     if (err != OK) {
304         return AAudioConvert_androidToAAudioResult(err);
305     }
306 
307     // Enable callback before starting AudioTrack to avoid shutting
308     // down because of a race condition.
309     mCallbackEnabled.store(true);
310     aaudio_stream_state_t originalState = getState();
311     // Set before starting the callback so that we are in the correct state
312     // before updateStateMachine() can be called by the callback.
313     setState(AAUDIO_STREAM_STATE_STARTING);
314     err = mAudioTrack->start();
315     if (err != OK) {
316         mCallbackEnabled.store(false);
317         setState(originalState);
318         return AAudioConvert_androidToAAudioResult(err);
319     }
320     return AAUDIO_OK;
321 }
322 
requestPause()323 aaudio_result_t AudioStreamTrack::requestPause() {
324     if (mAudioTrack.get() == nullptr) {
325         ALOGE("%s() no AudioTrack", __func__);
326         return AAUDIO_ERROR_INVALID_STATE;
327     }
328 
329     setState(AAUDIO_STREAM_STATE_PAUSING);
330     mAudioTrack->pause();
331     mCallbackEnabled.store(false);
332     status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
333     if (err != OK) {
334         return AAudioConvert_androidToAAudioResult(err);
335     }
336     return checkForDisconnectRequest(false);
337 }
338 
requestFlush()339 aaudio_result_t AudioStreamTrack::requestFlush() {
340     if (mAudioTrack.get() == nullptr) {
341         ALOGE("%s() no AudioTrack", __func__);
342         return AAUDIO_ERROR_INVALID_STATE;
343     }
344 
345     setState(AAUDIO_STREAM_STATE_FLUSHING);
346     incrementFramesRead(getFramesWritten() - getFramesRead());
347     mAudioTrack->flush();
348     mFramesRead.reset32(); // service reads frames, service position reset on flush
349     mTimestampPosition.reset32();
350     return AAUDIO_OK;
351 }
352 
requestStop()353 aaudio_result_t AudioStreamTrack::requestStop() {
354     if (mAudioTrack.get() == nullptr) {
355         ALOGE("%s() no AudioTrack", __func__);
356         return AAUDIO_ERROR_INVALID_STATE;
357     }
358 
359     setState(AAUDIO_STREAM_STATE_STOPPING);
360     mFramesRead.catchUpTo(getFramesWritten());
361     mTimestampPosition.catchUpTo(getFramesWritten());
362     mFramesRead.reset32(); // service reads frames, service position reset on stop
363     mTimestampPosition.reset32();
364     mAudioTrack->stop();
365     mCallbackEnabled.store(false);
366     return checkForDisconnectRequest(false);;
367 }
368 
updateStateMachine()369 aaudio_result_t AudioStreamTrack::updateStateMachine()
370 {
371     status_t err;
372     aaudio_wrapping_frames_t position;
373     switch (getState()) {
374     // TODO add better state visibility to AudioTrack
375     case AAUDIO_STREAM_STATE_STARTING:
376         if (mAudioTrack->hasStarted()) {
377             setState(AAUDIO_STREAM_STATE_STARTED);
378         }
379         break;
380     case AAUDIO_STREAM_STATE_PAUSING:
381         if (mAudioTrack->stopped()) {
382             err = mAudioTrack->getPosition(&position);
383             if (err != OK) {
384                 return AAudioConvert_androidToAAudioResult(err);
385             } else if (position == mPositionWhenPausing) {
386                 // Has stream really stopped advancing?
387                 setState(AAUDIO_STREAM_STATE_PAUSED);
388             }
389             mPositionWhenPausing = position;
390         }
391         break;
392     case AAUDIO_STREAM_STATE_FLUSHING:
393         {
394             err = mAudioTrack->getPosition(&position);
395             if (err != OK) {
396                 return AAudioConvert_androidToAAudioResult(err);
397             } else if (position == 0) {
398                 // TODO Advance frames read to match written.
399                 setState(AAUDIO_STREAM_STATE_FLUSHED);
400             }
401         }
402         break;
403     case AAUDIO_STREAM_STATE_STOPPING:
404         if (mAudioTrack->stopped()) {
405             setState(AAUDIO_STREAM_STATE_STOPPED);
406         }
407         break;
408     default:
409         break;
410     }
411     return AAUDIO_OK;
412 }
413 
write(const void * buffer,int32_t numFrames,int64_t timeoutNanoseconds)414 aaudio_result_t AudioStreamTrack::write(const void *buffer,
415                                       int32_t numFrames,
416                                       int64_t timeoutNanoseconds)
417 {
418     int32_t bytesPerFrame = getBytesPerFrame();
419     int32_t numBytes;
420     aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes);
421     if (result != AAUDIO_OK) {
422         return result;
423     }
424 
425     if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
426         return AAUDIO_ERROR_DISCONNECTED;
427     }
428 
429     // TODO add timeout to AudioTrack
430     bool blocking = timeoutNanoseconds > 0;
431     ssize_t bytesWritten = mAudioTrack->write(buffer, numBytes, blocking);
432     if (bytesWritten == WOULD_BLOCK) {
433         return 0;
434     } else if (bytesWritten < 0) {
435         ALOGE("invalid write, returned %d", (int)bytesWritten);
436         // in this context, a DEAD_OBJECT is more likely to be a disconnect notification due to
437         // AudioTrack invalidation
438         if (bytesWritten == DEAD_OBJECT) {
439             setState(AAUDIO_STREAM_STATE_DISCONNECTED);
440             return AAUDIO_ERROR_DISCONNECTED;
441         }
442         return AAudioConvert_androidToAAudioResult(bytesWritten);
443     }
444     int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame);
445     incrementFramesWritten(framesWritten);
446 
447     result = updateStateMachine();
448     if (result != AAUDIO_OK) {
449         return result;
450     }
451 
452     return framesWritten;
453 }
454 
setBufferSize(int32_t requestedFrames)455 aaudio_result_t AudioStreamTrack::setBufferSize(int32_t requestedFrames)
456 {
457     // Do not ask for less than one burst.
458     if (requestedFrames < getFramesPerBurst()) {
459         requestedFrames = getFramesPerBurst();
460     }
461     ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames);
462     if (result < 0) {
463         return AAudioConvert_androidToAAudioResult(result);
464     } else {
465         return result;
466     }
467 }
468 
getBufferSize() const469 int32_t AudioStreamTrack::getBufferSize() const
470 {
471     return static_cast<int32_t>(mAudioTrack->getBufferSizeInFrames());
472 }
473 
getBufferCapacity() const474 int32_t AudioStreamTrack::getBufferCapacity() const
475 {
476     return static_cast<int32_t>(mAudioTrack->frameCount());
477 }
478 
getXRunCount() const479 int32_t AudioStreamTrack::getXRunCount() const
480 {
481     return static_cast<int32_t>(mAudioTrack->getUnderrunCount());
482 }
483 
getFramesPerBurst() const484 int32_t AudioStreamTrack::getFramesPerBurst() const
485 {
486     return static_cast<int32_t>(mAudioTrack->getNotificationPeriodInFrames());
487 }
488 
getFramesRead()489 int64_t AudioStreamTrack::getFramesRead() {
490     aaudio_wrapping_frames_t position;
491     status_t result;
492     switch (getState()) {
493     case AAUDIO_STREAM_STATE_STARTING:
494     case AAUDIO_STREAM_STATE_STARTED:
495     case AAUDIO_STREAM_STATE_STOPPING:
496     case AAUDIO_STREAM_STATE_PAUSING:
497     case AAUDIO_STREAM_STATE_PAUSED:
498         result = mAudioTrack->getPosition(&position);
499         if (result == OK) {
500             mFramesRead.update32(position);
501         }
502         break;
503     default:
504         break;
505     }
506     return AudioStreamLegacy::getFramesRead();
507 }
508 
getTimestamp(clockid_t clockId,int64_t * framePosition,int64_t * timeNanoseconds)509 aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
510                                      int64_t *framePosition,
511                                      int64_t *timeNanoseconds) {
512     ExtendedTimestamp extendedTimestamp;
513     status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
514     if (status == WOULD_BLOCK) {
515         return AAUDIO_ERROR_INVALID_STATE;
516     } if (status != NO_ERROR) {
517         return AAudioConvert_androidToAAudioResult(status);
518     }
519     int64_t position = 0;
520     int64_t nanoseconds = 0;
521     aaudio_result_t result = getBestTimestamp(clockId, &position,
522                                               &nanoseconds, &extendedTimestamp);
523     if (result == AAUDIO_OK) {
524         if (position < getFramesWritten()) {
525             *framePosition = position;
526             *timeNanoseconds = nanoseconds;
527             return result;
528         } else {
529             return AAUDIO_ERROR_INVALID_STATE; // TODO review, documented but not consistent
530         }
531     }
532     return result;
533 }
534 
doSetVolume()535 status_t AudioStreamTrack::doSetVolume() {
536     status_t status = NO_INIT;
537     if (mAudioTrack.get() != nullptr) {
538         float volume = getDuckAndMuteVolume();
539         mAudioTrack->setVolume(volume, volume);
540         status = NO_ERROR;
541     }
542     return status;
543 }
544 
545 #if AAUDIO_USE_VOLUME_SHAPER
546 
547 using namespace android::media::VolumeShaper;
548 
applyVolumeShaper(const VolumeShaper::Configuration & configuration,const VolumeShaper::Operation & operation)549 binder::Status AudioStreamTrack::applyVolumeShaper(
550         const VolumeShaper::Configuration& configuration,
551         const VolumeShaper::Operation& operation) {
552 
553     sp<VolumeShaper::Configuration> spConfiguration = new VolumeShaper::Configuration(configuration);
554     sp<VolumeShaper::Operation> spOperation = new VolumeShaper::Operation(operation);
555 
556     if (mAudioTrack.get() != nullptr) {
557         ALOGD("applyVolumeShaper() from IPlayer");
558         binder::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
559         if (status < 0) { // a non-negative value is the volume shaper id.
560             ALOGE("applyVolumeShaper() failed with status %d", status);
561         }
562         return binder::Status::fromStatusT(status);
563     } else {
564         ALOGD("applyVolumeShaper()"
565                       " no AudioTrack for volume control from IPlayer");
566         return binder::Status::ok();
567     }
568 }
569 #endif
570