• 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 <com_android_media_aaudio.h>
26 #include <system/audio.h>
27 #include <system/aaudio/AAudio.h>
28 
29 #include "core/AudioGlobal.h"
30 #include "legacy/AudioStreamLegacy.h"
31 #include "legacy/AudioStreamTrack.h"
32 #include "utility/AudioClock.h"
33 #include "utility/FixedBlockReader.h"
34 
35 using namespace android;
36 using namespace aaudio;
37 
38 using android::content::AttributionSourceState;
39 
40 // Arbitrary and somewhat generous number of bursts.
41 #define DEFAULT_BURSTS_PER_BUFFER_CAPACITY     8
42 
43 /*
44  * Create a stream that uses the AudioTrack.
45  */
AudioStreamTrack()46 AudioStreamTrack::AudioStreamTrack()
47     : AudioStreamLegacy()
48     , mFixedBlockReader(*this)
49 {
50 }
51 
~AudioStreamTrack()52 AudioStreamTrack::~AudioStreamTrack()
53 {
54     const aaudio_stream_state_t state = getState();
55     bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED);
56     ALOGE_IF(bad, "stream not closed, in state %d", state);
57 }
58 
open(const AudioStreamBuilder & builder)59 aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
60 {
61     if (!com::android::media::aaudio::offload_support() &&
62         builder.getPerformanceMode() == AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED) {
63         return AAUDIO_ERROR_UNIMPLEMENTED;
64     }
65     aaudio_result_t result = AAUDIO_OK;
66 
67     result = AudioStream::open(builder);
68     if (result != OK) {
69         return result;
70     }
71 
72     const aaudio_session_id_t requestedSessionId = builder.getSessionId();
73     const audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
74 
75     audio_channel_mask_t channelMask =
76             AAudio_getChannelMaskForOpen(getChannelMask(), getSamplesPerFrame(), false /*isInput*/);
77 
78     // Set flags based on selected parameters.
79     audio_output_flags_t flags;
80     aaudio_performance_mode_t perfMode = getPerformanceMode();
81     switch(perfMode) {
82         case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: {
83             // Bypass the normal mixer and go straight to the FAST mixer.
84             // Some Usages need RAW mode so they can get the lowest possible latency.
85             // Other Usages should avoid RAW because it can interfere with
86             // dual sink routing or other features.
87             bool usageBenefitsFromRaw = getUsage() == AAUDIO_USAGE_GAME ||
88                     getUsage() == AAUDIO_USAGE_MEDIA;
89             // If an app does not ask for a sessionId then there will be no effects.
90             // So we can use the use RAW flag.
91             flags = (audio_output_flags_t) (((requestedSessionId == AAUDIO_SESSION_ID_NONE)
92                                              && usageBenefitsFromRaw)
93                                             ? (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW)
94                                             : (AUDIO_OUTPUT_FLAG_FAST));
95         }
96             break;
97 
98         case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
99             // This uses a mixer that wakes up less often than the FAST mixer.
100             flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
101             break;
102 
103         case AAUDIO_PERFORMANCE_MODE_NONE:
104         default:
105             // No flags. Use a normal mixer in front of the FAST mixer.
106             flags = AUDIO_OUTPUT_FLAG_NONE;
107             break;
108     }
109 
110     size_t frameCount = (size_t)builder.getBufferCapacity();
111 
112     // To avoid glitching, let AudioFlinger pick the optimal burst size.
113     int32_t notificationFrames = 0;
114 
115     const audio_format_t format = (getFormat() == AUDIO_FORMAT_DEFAULT)
116             ? AUDIO_FORMAT_PCM_FLOAT
117             : getFormat();
118 
119     // Setup the callback if there is one.
120     wp<AudioTrack::IAudioTrackCallback> callback;
121     // Note that TRANSFER_SYNC does not allow FAST track
122     AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC;
123     if (builder.getDataCallbackProc() != nullptr) {
124         streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK;
125         callback = wp<AudioTrack::IAudioTrackCallback>::fromExisting(this);
126 
127         // If the total buffer size is unspecified then base the size on the burst size.
128         if (frameCount == 0
129                 && ((flags & AUDIO_OUTPUT_FLAG_FAST) != 0)) {
130             // Take advantage of a special trick that allows us to create a buffer
131             // that is some multiple of the burst size.
132             notificationFrames = 0 - DEFAULT_BURSTS_PER_BUFFER_CAPACITY;
133         }
134     } else if (getPerformanceMode() == AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED) {
135         streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC_NOTIF_CALLBACK;
136         callback = wp<AudioTrack::IAudioTrackCallback>::fromExisting(this);
137     }
138     mCallbackBufferSize = builder.getFramesPerDataCallback();
139 
140     ALOGD("open(), request notificationFrames = %d, frameCount = %u",
141           notificationFrames, (uint)frameCount);
142 
143     // Don't call mAudioTrack->setDeviceId() because it will be overwritten by set()!
144     audio_port_handle_t selectedDeviceId = getFirstDeviceId(getDeviceIds());
145 
146     const audio_content_type_t contentType =
147             AAudioConvert_contentTypeToInternal(builder.getContentType());
148     const audio_usage_t usage =
149             AAudioConvert_usageToInternal(builder.getUsage());
150     const audio_flags_mask_t attributesFlags = AAudio_computeAudioFlagsMask(
151                                                             builder.getAllowedCapturePolicy(),
152                                                             builder.getSpatializationBehavior(),
153                                                             builder.isContentSpatialized(),
154                                                             flags);
155 
156     const std::string tags = getTagsAsString();
157     audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
158     attributes.content_type = contentType;
159     attributes.usage = usage;
160     attributes.flags = attributesFlags;
161     if (!tags.empty()) {
162         strncpy(attributes.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
163         attributes.tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1] = '\0';
164     }
165 
166     audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
167     if (getPerformanceMode() == AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED) {
168         audio_config_t config = AUDIO_CONFIG_INITIALIZER;
169         config.format = format;
170         config.channel_mask = channelMask;
171         config.sample_rate = getSampleRate();
172         audio_direct_mode_t directMode = AUDIO_DIRECT_NOT_SUPPORTED;
173         if (status_t status = AudioSystem::getDirectPlaybackSupport(
174                 &attributes, &config, &directMode);
175             status != NO_ERROR) {
176             ALOGE("%s, failed to query direct support, error=%d", __func__, status);
177             return status;
178         }
179         static const audio_direct_mode_t offloadMode = static_cast<audio_direct_mode_t>(
180                 AUDIO_DIRECT_OFFLOAD_SUPPORTED | AUDIO_DIRECT_OFFLOAD_GAPLESS_SUPPORTED);
181         if ((directMode & offloadMode) == AUDIO_DIRECT_NOT_SUPPORTED) {
182             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
183         }
184         flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
185         frameCount = 0;
186         offloadInfo.format = format;
187         offloadInfo.sample_rate = getSampleRate();
188         offloadInfo.channel_mask = channelMask;
189         offloadInfo.has_video = false;
190         offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
191     }
192 
193     mAudioTrack = new AudioTrack();
194     // TODO b/182392769: use attribution source util
195     mAudioTrack->set(
196             AUDIO_STREAM_DEFAULT,  // ignored because we pass attributes below
197             getSampleRate(),
198             format,
199             channelMask,
200             frameCount,
201             flags,
202             callback,
203             notificationFrames,
204             nullptr,       // DEFAULT sharedBuffer*/,
205             false,   // DEFAULT threadCanCallJava
206             sessionId,
207             streamTransferType,
208             getPerformanceMode() == AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED
209                     ? &offloadInfo : nullptr,
210             AttributionSourceState(), // DEFAULT uid and pid
211             &attributes,
212             // WARNING - If doNotReconnect set true then audio stops after plugging and unplugging
213             // headphones a few times.
214             false,   // DEFAULT doNotReconnect,
215             1.0f,    // DEFAULT maxRequiredSpeed
216             selectedDeviceId
217     );
218 
219     // Set it here so it can be logged by the destructor if the open failed.
220     mAudioTrack->setCallerName(kCallerName);
221 
222     // Did we get a valid track?
223     status_t status = mAudioTrack->initCheck();
224     if (status != NO_ERROR) {
225         safeReleaseClose();
226         ALOGE("open(), initCheck() returned %d", status);
227         return AAudioConvert_androidToAAudioResult(status);
228     }
229 
230     mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
231             + std::to_string(mAudioTrack->getPortId());
232     android::mediametrics::LogItem(mMetricsId)
233             .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
234                  AudioGlobal_convertPerformanceModeToText(builder.getPerformanceMode()))
235             .set(AMEDIAMETRICS_PROP_SHARINGMODE,
236                  AudioGlobal_convertSharingModeToText(builder.getSharingMode()))
237             .set(AMEDIAMETRICS_PROP_ENCODINGCLIENT,
238                  android::toString(getFormat()).c_str()).record();
239 
240     doSetVolume();
241 
242     // Get the actual values from the AudioTrack.
243     setChannelMask(AAudioConvert_androidToAAudioChannelMask(
244         mAudioTrack->channelMask(), false /*isInput*/,
245         AAudio_isChannelIndexMask(getChannelMask())));
246     setFormat(mAudioTrack->format());
247     setDeviceFormat(mAudioTrack->format());
248     setSampleRate(mAudioTrack->getSampleRate());
249     setBufferCapacity(getBufferCapacityFromDevice());
250     setFramesPerBurst(getFramesPerBurstFromDevice());
251 
252     // Use the same values for device values.
253     setDeviceSamplesPerFrame(getSamplesPerFrame());
254     setDeviceSampleRate(mAudioTrack->getSampleRate());
255     setDeviceBufferCapacity(getBufferCapacityFromDevice());
256     setDeviceFramesPerBurst(getFramesPerBurstFromDevice());
257 
258     setHardwareSamplesPerFrame(mAudioTrack->getHalChannelCount());
259     setHardwareSampleRate(mAudioTrack->getHalSampleRate());
260     setHardwareFormat(mAudioTrack->getHalFormat());
261 
262     // We may need to pass the data through a block size adapter to guarantee constant size.
263     if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
264         // This may need to change if we add format conversion before
265         // the block size adaptation.
266         mBlockAdapterBytesPerFrame = getBytesPerFrame();
267         int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
268         mFixedBlockReader.open(callbackSizeBytes);
269         mBlockAdapter = &mFixedBlockReader;
270     } else {
271         mBlockAdapter = nullptr;
272     }
273 
274     setDeviceIds(mAudioTrack->getRoutedDeviceIds());
275 
276     aaudio_session_id_t actualSessionId =
277             (requestedSessionId == AAUDIO_SESSION_ID_NONE)
278             ? AAUDIO_SESSION_ID_NONE
279             : (aaudio_session_id_t) mAudioTrack->getSessionId();
280     setSessionId(actualSessionId);
281 
282     mAudioTrack->addAudioDeviceCallback(this);
283 
284     // Update performance mode based on the actual stream flags.
285     // For example, if the sample rate is not allowed then you won't get a FAST track.
286     audio_output_flags_t actualFlags = mAudioTrack->getFlags();
287     aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
288     // We may not get the RAW flag. But as long as we get the FAST flag we can call it LOW_LATENCY.
289     if ((actualFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != AUDIO_OUTPUT_FLAG_NONE) {
290         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED;
291     } else if ((actualFlags & AUDIO_OUTPUT_FLAG_FAST) != 0) {
292         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
293     } else if ((actualFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
294         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
295     }
296     setPerformanceMode(actualPerformanceMode);
297 
298     setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy
299 
300     // Log if we did not get what we asked for.
301     ALOGD_IF(actualFlags != flags,
302              "open() flags changed from 0x%08X to 0x%08X",
303              flags, actualFlags);
304     ALOGD_IF(actualPerformanceMode != perfMode,
305              "open() perfMode changed from %d to %d",
306              perfMode, actualPerformanceMode);
307 
308     if (getState() != AAUDIO_STREAM_STATE_UNINITIALIZED) {
309         ALOGE("%s - Open canceled since state = %d", __func__, getState());
310         if (isDisconnected())
311         {
312             ALOGE("%s - Opening while state is disconnected", __func__);
313             safeReleaseClose();
314             return AAUDIO_ERROR_DISCONNECTED;
315         }
316         safeReleaseClose();
317         return AAUDIO_ERROR_INVALID_STATE;
318     }
319 
320     setState(AAUDIO_STREAM_STATE_OPEN);
321     return AAUDIO_OK;
322 }
323 
release_l()324 aaudio_result_t AudioStreamTrack::release_l() {
325     if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
326         status_t err = mAudioTrack->removeAudioDeviceCallback(this);
327         ALOGE_IF(err, "%s() removeAudioDeviceCallback returned %d", __func__, err);
328         logReleaseBufferState();
329         // Data callbacks may still be running!
330         return AudioStream::release_l();
331     } else {
332         return AAUDIO_OK; // already released
333     }
334 }
335 
close_l()336 void AudioStreamTrack::close_l() {
337     // The callbacks are normally joined in the AudioTrack destructor.
338     // But if another object has a reference to the AudioTrack then
339     // it will not get deleted here.
340     // So we should join callbacks explicitly before returning.
341     // Unlock around the join to avoid deadlocks if the callback tries to lock.
342     // This can happen if the callback returns AAUDIO_CALLBACK_RESULT_STOP
343     mStreamLock.unlock();
344     mAudioTrack->stopAndJoinCallbacks();
345     mStreamLock.lock();
346     mAudioTrack.clear();
347     // Do not close mFixedBlockReader. It has a unique_ptr to its buffer
348     // so it will clean up by itself.
349     AudioStream::close_l();
350 }
351 
352 
onNewIAudioTrack()353 void AudioStreamTrack::onNewIAudioTrack() {
354     // Stream got rerouted so we disconnect.
355     // request stream disconnect if the restored AudioTrack has properties not matching
356     // what was requested initially
357     if (mAudioTrack->channelCount() != getSamplesPerFrame()
358           || mAudioTrack->format() != getFormat()
359           || mAudioTrack->getSampleRate() != getSampleRate()
360           || !areDeviceIdsEqual(mAudioTrack->getRoutedDeviceIds(), getDeviceIds())
361           || getBufferCapacityFromDevice() != getBufferCapacity()
362           || getFramesPerBurstFromDevice() != getFramesPerBurst()) {
363         AudioStreamLegacy::onNewIAudioTrack();
364     }
365 }
366 
requestStart_l()367 aaudio_result_t AudioStreamTrack::requestStart_l() {
368     if (mAudioTrack.get() == nullptr) {
369         ALOGE("requestStart() no AudioTrack");
370         return AAUDIO_ERROR_INVALID_STATE;
371     }
372     // Get current position so we can detect when the track is playing.
373     status_t err = mAudioTrack->getPosition(&mPositionWhenStarting);
374     if (err != OK) {
375         return AAudioConvert_androidToAAudioResult(err);
376     }
377 
378     // Enable callback before starting AudioTrack to avoid shutting
379     // down because of a race condition.
380     mCallbackEnabled.store(true);
381     aaudio_stream_state_t originalState = getState();
382     // Set before starting the callback so that we are in the correct state
383     // before updateStateMachine() can be called by the callback.
384     setState(AAUDIO_STREAM_STATE_STARTING);
385     err = mAudioTrack->start();
386     if (err != OK) {
387         mCallbackEnabled.store(false);
388         setState(originalState);
389         return AAudioConvert_androidToAAudioResult(err);
390     }
391     mOffloadEosPending = false;
392     return AAUDIO_OK;
393 }
394 
requestPause_l()395 aaudio_result_t AudioStreamTrack::requestPause_l() {
396     if (mAudioTrack.get() == nullptr) {
397         ALOGE("%s() no AudioTrack", __func__);
398         return AAUDIO_ERROR_INVALID_STATE;
399     }
400 
401     setState(AAUDIO_STREAM_STATE_PAUSING);
402     mAudioTrack->pause();
403     mCallbackEnabled.store(false);
404     status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
405     if (err != OK) {
406         return AAudioConvert_androidToAAudioResult(err);
407     }
408     return checkForDisconnectRequest(false);
409 }
410 
requestFlush_l()411 aaudio_result_t AudioStreamTrack::requestFlush_l() {
412     if (mAudioTrack.get() == nullptr) {
413         ALOGE("%s() no AudioTrack", __func__);
414         return AAUDIO_ERROR_INVALID_STATE;
415     }
416 
417     setState(AAUDIO_STREAM_STATE_FLUSHING);
418     incrementFramesRead(getFramesWritten() - getFramesRead());
419     mAudioTrack->flush();
420     mFramesRead.reset32(); // service reads frames, service position reset on flush
421     mTimestampPosition.reset32();
422     return AAUDIO_OK;
423 }
424 
requestStop_l()425 aaudio_result_t AudioStreamTrack::requestStop_l() {
426     if (mAudioTrack.get() == nullptr) {
427         ALOGE("%s() no AudioTrack", __func__);
428         return AAUDIO_ERROR_INVALID_STATE;
429     }
430 
431     setState(AAUDIO_STREAM_STATE_STOPPING);
432     mFramesRead.catchUpTo(getFramesWritten());
433     mTimestampPosition.catchUpTo(getFramesWritten());
434     mFramesRead.reset32(); // service reads frames, service position reset on stop
435     mTimestampPosition.reset32();
436     mAudioTrack->stop();
437     mCallbackEnabled.store(false);
438     return checkForDisconnectRequest(false);;
439 }
440 
processCommands()441 aaudio_result_t AudioStreamTrack::processCommands() {
442     status_t err;
443     aaudio_wrapping_frames_t position;
444     switch (getState()) {
445     // TODO add better state visibility to AudioTrack
446     case AAUDIO_STREAM_STATE_STARTING:
447         if (mAudioTrack->hasStarted()) {
448             setState(AAUDIO_STREAM_STATE_STARTED);
449         }
450         break;
451     case AAUDIO_STREAM_STATE_PAUSING:
452         if (mAudioTrack->stopped()) {
453             err = mAudioTrack->getPosition(&position);
454             if (err != OK) {
455                 return AAudioConvert_androidToAAudioResult(err);
456             } else if (position == mPositionWhenPausing) {
457                 // Has stream really stopped advancing?
458                 setState(AAUDIO_STREAM_STATE_PAUSED);
459             }
460             mPositionWhenPausing = position;
461         }
462         break;
463     case AAUDIO_STREAM_STATE_FLUSHING:
464         {
465             err = mAudioTrack->getPosition(&position);
466             if (err != OK) {
467                 return AAudioConvert_androidToAAudioResult(err);
468             } else if (position == 0) {
469                 setState(AAUDIO_STREAM_STATE_FLUSHED);
470             }
471         }
472         break;
473     case AAUDIO_STREAM_STATE_STOPPING:
474         if (mAudioTrack->stopped()) {
475             if (getPerformanceMode() == AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED) {
476                 // For offload mode, the state will be updated as `STOPPED` from
477                 // stream end callback.
478                 break;
479             }
480             setState(AAUDIO_STREAM_STATE_STOPPED);
481         }
482         break;
483     default:
484         break;
485     }
486     return AAUDIO_OK;
487 }
488 
write(const void * buffer,int32_t numFrames,int64_t timeoutNanoseconds)489 aaudio_result_t AudioStreamTrack::write(const void *buffer,
490                                       int32_t numFrames,
491                                       int64_t timeoutNanoseconds)
492 {
493     int32_t bytesPerFrame = getBytesPerFrame();
494     int32_t numBytes;
495     aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes);
496     if (result != AAUDIO_OK) {
497         return result;
498     }
499 
500     if (isDisconnected()) {
501         return AAUDIO_ERROR_DISCONNECTED;
502     }
503 
504     // TODO add timeout to AudioTrack
505     bool blocking = timeoutNanoseconds > 0;
506     ssize_t bytesWritten = mAudioTrack->write(buffer, numBytes, blocking);
507     if (bytesWritten == WOULD_BLOCK) {
508         return 0;
509     } else if (bytesWritten < 0) {
510         ALOGE("invalid write, returned %d", (int)bytesWritten);
511         // in this context, a DEAD_OBJECT is more likely to be a disconnect notification due to
512         // AudioTrack invalidation
513         if (bytesWritten == DEAD_OBJECT) {
514             setDisconnected();
515             return AAUDIO_ERROR_DISCONNECTED;
516         }
517         return AAudioConvert_androidToAAudioResult(bytesWritten);
518     }
519     int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame);
520     incrementFramesWritten(framesWritten);
521 
522     result = updateStateMachine();
523     if (result != AAUDIO_OK) {
524         return result;
525     }
526 
527     return framesWritten;
528 }
529 
setBufferSize(int32_t requestedFrames)530 aaudio_result_t AudioStreamTrack::setBufferSize(int32_t requestedFrames)
531 {
532     // Do not ask for less than one burst.
533     if (requestedFrames < getFramesPerBurst()) {
534         requestedFrames = getFramesPerBurst();
535     }
536     ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames);
537     if (result < 0) {
538         return AAudioConvert_androidToAAudioResult(result);
539     } else {
540         return result;
541     }
542 }
543 
getBufferSize() const544 int32_t AudioStreamTrack::getBufferSize() const
545 {
546     return static_cast<int32_t>(mAudioTrack->getBufferSizeInFrames());
547 }
548 
getBufferCapacityFromDevice() const549 int32_t AudioStreamTrack::getBufferCapacityFromDevice() const
550 {
551     return static_cast<int32_t>(mAudioTrack->frameCount());
552 }
553 
getXRunCount() const554 int32_t AudioStreamTrack::getXRunCount() const
555 {
556     return static_cast<int32_t>(mAudioTrack->getUnderrunCount());
557 }
558 
getFramesPerBurstFromDevice() const559 int32_t AudioStreamTrack::getFramesPerBurstFromDevice() const {
560     return static_cast<int32_t>(mAudioTrack->getNotificationPeriodInFrames());
561 }
562 
getFramesRead()563 int64_t AudioStreamTrack::getFramesRead() {
564     aaudio_wrapping_frames_t position;
565     status_t result;
566     switch (getState()) {
567     case AAUDIO_STREAM_STATE_STARTING:
568     case AAUDIO_STREAM_STATE_STARTED:
569     case AAUDIO_STREAM_STATE_STOPPING:
570     case AAUDIO_STREAM_STATE_PAUSING:
571     case AAUDIO_STREAM_STATE_PAUSED:
572         result = mAudioTrack->getPosition(&position);
573         if (result == OK) {
574             mFramesRead.update32((int32_t)position);
575         }
576         break;
577     default:
578         break;
579     }
580     return AudioStreamLegacy::getFramesRead();
581 }
582 
getTimestamp(clockid_t clockId,int64_t * framePosition,int64_t * timeNanoseconds)583 aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
584                                      int64_t *framePosition,
585                                      int64_t *timeNanoseconds) {
586     ExtendedTimestamp extendedTimestamp;
587     status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
588     if (status == WOULD_BLOCK) {
589         return AAUDIO_ERROR_INVALID_STATE;
590     } if (status != NO_ERROR) {
591         return AAudioConvert_androidToAAudioResult(status);
592     }
593     int64_t position = 0;
594     int64_t nanoseconds = 0;
595     aaudio_result_t result = getBestTimestamp(clockId, &position,
596                                               &nanoseconds, &extendedTimestamp);
597     if (result == AAUDIO_OK) {
598         if (position < getFramesWritten()) {
599             *framePosition = position;
600             *timeNanoseconds = nanoseconds;
601             return result;
602         } else {
603             return AAUDIO_ERROR_INVALID_STATE; // TODO review, documented but not consistent
604         }
605     }
606     return result;
607 }
608 
doSetVolume()609 status_t AudioStreamTrack::doSetVolume() {
610     status_t status = NO_INIT;
611     if (mAudioTrack.get() != nullptr) {
612         float volume = getDuckAndMuteVolume();
613         mAudioTrack->setVolume(volume, volume);
614         status = NO_ERROR;
615     }
616     return status;
617 }
618 
registerPlayerBase()619 void AudioStreamTrack::registerPlayerBase() {
620     AudioStream::registerPlayerBase();
621 
622     if (mAudioTrack == nullptr) {
623         ALOGW("%s: cannot set piid, AudioTrack is null", __func__);
624         return;
625     }
626     mAudioTrack->setPlayerIId(mPlayerBase->getPlayerIId());
627 }
628 
systemStopInternal_l()629 aaudio_result_t AudioStreamTrack::systemStopInternal_l() {
630     if (aaudio_result_t result = AudioStream::systemStopInternal_l(); result != AAUDIO_OK) {
631         return result;
632     }
633     mOffloadEosPending = false;
634     return AAUDIO_OK;
635 }
636 
setOffloadDelayPadding(int32_t delayInFrames,int32_t paddingInFrames)637 aaudio_result_t AudioStreamTrack::setOffloadDelayPadding(
638         int32_t delayInFrames, int32_t paddingInFrames) {
639     if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED ||
640         audio_is_linear_pcm(getFormat())) {
641         return AAUDIO_ERROR_UNIMPLEMENTED;
642     }
643     if (mAudioTrack == nullptr) {
644         return AAUDIO_ERROR_INVALID_STATE;
645     }
646     AudioParameter param = AudioParameter();
647     param.addInt(String8(AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES),  delayInFrames);
648     param.addInt(String8(AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES),  paddingInFrames);
649     mAudioTrack->setParameters(param.toString());
650     mOffloadDelayFrames.store(delayInFrames);
651     mOffloadPaddingFrames.store(paddingInFrames);
652     return AAUDIO_OK;
653 }
654 
getOffloadDelay()655 int32_t AudioStreamTrack::getOffloadDelay() {
656     if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED ||
657         audio_is_linear_pcm(getFormat())) {
658         return AAUDIO_ERROR_UNIMPLEMENTED;
659     }
660     if (mAudioTrack == nullptr) {
661         return AAUDIO_ERROR_INVALID_STATE;
662     }
663     return mOffloadDelayFrames.load();
664 }
665 
getOffloadPadding()666 int32_t AudioStreamTrack::getOffloadPadding() {
667     if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED ||
668         audio_is_linear_pcm(getFormat())) {
669         return AAUDIO_ERROR_UNIMPLEMENTED;
670     }
671     if (mAudioTrack == nullptr) {
672         return AAUDIO_ERROR_INVALID_STATE;
673     }
674     return mOffloadPaddingFrames.load();
675 }
676 
setOffloadEndOfStream()677 aaudio_result_t AudioStreamTrack::setOffloadEndOfStream() {
678     if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED) {
679         return AAUDIO_ERROR_UNIMPLEMENTED;
680     }
681     if (mAudioTrack == nullptr) {
682         return AAUDIO_ERROR_INVALID_STATE;
683     }
684     std::lock_guard<std::mutex> lock(mStreamLock);
685     if (aaudio_result_t result = safeStop_l(); result != AAUDIO_OK) {
686         return result;
687     }
688     mOffloadEosPending = true;
689     setState(AAUDIO_STREAM_STATE_STOPPING);
690     return AAUDIO_OK;
691 }
692 
collidesWithCallback() const693 bool AudioStreamTrack::collidesWithCallback() const {
694     if (AudioStream::collidesWithCallback()) {
695         return true;
696     }
697     pid_t thisThread = gettid();
698     return mPresentationEndCallbackThread.load() == thisThread;
699 }
700 
onStreamEnd()701 void AudioStreamTrack::onStreamEnd() {
702     if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED) {
703         return;
704     }
705     if (getState() == AAUDIO_STREAM_STATE_STOPPING) {
706         std::lock_guard<std::mutex> lock(mStreamLock);
707         if (mOffloadEosPending) {
708             requestStart_l();
709         } else {
710             setState(AAUDIO_STREAM_STATE_STOPPED);
711         }
712         mOffloadEosPending = false;
713     }
714     maybeCallPresentationEndCallback();
715 }
716 
maybeCallPresentationEndCallback()717 void AudioStreamTrack::maybeCallPresentationEndCallback() {
718     if (mPresentationEndCallbackProc != nullptr) {
719         pid_t expected = CALLBACK_THREAD_NONE;
720         if (mPresentationEndCallbackThread.compare_exchange_strong(expected, gettid())) {
721             (*mPresentationEndCallbackProc)(
722                     (AAudioStream *) this, mPresentationEndCallbackUserData);
723             mPresentationEndCallbackThread.store(CALLBACK_THREAD_NONE);
724         } else {
725             ALOGW("%s() error callback already running!", __func__);
726         }
727     }
728 }
729 
730 #if AAUDIO_USE_VOLUME_SHAPER
731 
732 using namespace android::media::VolumeShaper;
733 
applyVolumeShaper(const VolumeShaper::Configuration & configuration,const VolumeShaper::Operation & operation)734 binder::Status AudioStreamTrack::applyVolumeShaper(
735         const VolumeShaper::Configuration& configuration,
736         const VolumeShaper::Operation& operation) {
737 
738     sp<VolumeShaper::Configuration> spConfiguration = new VolumeShaper::Configuration(configuration);
739     sp<VolumeShaper::Operation> spOperation = new VolumeShaper::Operation(operation);
740 
741     if (mAudioTrack.get() != nullptr) {
742         ALOGD("applyVolumeShaper() from IPlayer");
743         binder::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
744         if (status < 0) { // a non-negative value is the volume shaper id.
745             ALOGE("applyVolumeShaper() failed with status %d", status);
746         }
747         return aidl_utils::binderStatusFromStatusT(status);
748     } else {
749         ALOGD("applyVolumeShaper()"
750                       " no AudioTrack for volume control from IPlayer");
751         return binder::Status::ok();
752     }
753 }
754 #endif
755