1 /*
2  * Copyright 2015 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 "AAudioStream"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <atomic>
22 #include <stdint.h>
23 
24 #include <media/MediaMetricsItem.h>
25 
26 #include <aaudio/AAudio.h>
27 
28 #include "AudioStreamBuilder.h"
29 #include "AudioStream.h"
30 #include "AudioClock.h"
31 #include "AudioGlobal.h"
32 
33 namespace aaudio {
34 
35 // Sequential number assigned to streams solely for debugging purposes.
AAudio_getNextStreamId()36 static aaudio_stream_id_t AAudio_getNextStreamId() {
37     static std::atomic <aaudio_stream_id_t> nextStreamId{1};
38     return nextStreamId++;
39 }
40 
AudioStream()41 AudioStream::AudioStream()
42         : mPlayerBase(new MyPlayerBase(this))
43         , mStreamId(AAudio_getNextStreamId())
44         {
45     // mThread is a pthread_t of unknown size so we need memset.
46     memset(&mThread, 0, sizeof(mThread));
47     setPeriodNanoseconds(0);
48 }
49 
~AudioStream()50 AudioStream::~AudioStream() {
51     // If the stream is deleted when OPEN or in use then audio resources will leak.
52     // This would indicate an internal error. So we want to find this ASAP.
53     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
54                           || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
55                           || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
56                         "~AudioStream() - still in use, state = %s",
57                         AudioGlobal_convertStreamStateToText(getState()));
58 
59     mPlayerBase->clearParentReference(); // remove reference to this AudioStream
60 }
61 
open(const AudioStreamBuilder & builder)62 aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
63 {
64     // Call here as well because the AAudioService will call this without calling build().
65     aaudio_result_t result = builder.validate();
66     if (result != AAUDIO_OK) {
67         return result;
68     }
69 
70     // Copy parameters from the Builder because the Builder may be deleted after this call.
71     // TODO AudioStream should be a subclass of AudioStreamParameters
72     mSamplesPerFrame = builder.getSamplesPerFrame();
73     mSampleRate = builder.getSampleRate();
74     mDeviceId = builder.getDeviceId();
75     mFormat = builder.getFormat();
76     mSharingMode = builder.getSharingMode();
77     mSharingModeMatchRequired = builder.isSharingModeMatchRequired();
78     mPerformanceMode = builder.getPerformanceMode();
79 
80     mUsage = builder.getUsage();
81     if (mUsage == AAUDIO_UNSPECIFIED) {
82         mUsage = AAUDIO_USAGE_MEDIA;
83     }
84     mContentType = builder.getContentType();
85     if (mContentType == AAUDIO_UNSPECIFIED) {
86         mContentType = AAUDIO_CONTENT_TYPE_MUSIC;
87     }
88     mInputPreset = builder.getInputPreset();
89     if (mInputPreset == AAUDIO_UNSPECIFIED) {
90         mInputPreset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
91     }
92     mAllowedCapturePolicy = builder.getAllowedCapturePolicy();
93     if (mAllowedCapturePolicy == AAUDIO_UNSPECIFIED) {
94         mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
95     }
96     mIsPrivacySensitive = builder.isPrivacySensitive();
97 
98     // callbacks
99     mFramesPerDataCallback = builder.getFramesPerDataCallback();
100     mDataCallbackProc = builder.getDataCallbackProc();
101     mErrorCallbackProc = builder.getErrorCallbackProc();
102     mDataCallbackUserData = builder.getDataCallbackUserData();
103     mErrorCallbackUserData = builder.getErrorCallbackUserData();
104 
105     return AAUDIO_OK;
106 }
107 
logOpen()108 void AudioStream::logOpen() {
109     if (mMetricsId.size() > 0) {
110         android::mediametrics::LogItem(mMetricsId)
111                 .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
112                      AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
113                 .set(AMEDIAMETRICS_PROP_SHARINGMODE,
114                      AudioGlobal_convertSharingModeToText(getSharingMode()))
115                 .record();
116     }
117 }
118 
logReleaseBufferState()119 void AudioStream::logReleaseBufferState() {
120     if (mMetricsId.size() > 0) {
121         android::mediametrics::LogItem(mMetricsId)
122                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RELEASE)
123                 .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, (int32_t) getBufferSize())
124                 .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getXRunCount())
125                 .record();
126     }
127 }
128 
systemStart()129 aaudio_result_t AudioStream::systemStart() {
130     std::lock_guard<std::mutex> lock(mStreamLock);
131 
132     if (collidesWithCallback()) {
133         ALOGE("%s cannot be called from a callback!", __func__);
134         return AAUDIO_ERROR_INVALID_STATE;
135     }
136 
137     switch (getState()) {
138         // Is this a good time to start?
139         case AAUDIO_STREAM_STATE_OPEN:
140         case AAUDIO_STREAM_STATE_PAUSING:
141         case AAUDIO_STREAM_STATE_PAUSED:
142         case AAUDIO_STREAM_STATE_STOPPING:
143         case AAUDIO_STREAM_STATE_STOPPED:
144         case AAUDIO_STREAM_STATE_FLUSHING:
145         case AAUDIO_STREAM_STATE_FLUSHED:
146             break; // Proceed with starting.
147 
148         // Already started?
149         case AAUDIO_STREAM_STATE_STARTING:
150         case AAUDIO_STREAM_STATE_STARTED:
151             ALOGW("%s() stream was already started, state = %s", __func__,
152                   AudioGlobal_convertStreamStateToText(getState()));
153             return AAUDIO_ERROR_INVALID_STATE;
154 
155         // Don't start when the stream is dead!
156         case AAUDIO_STREAM_STATE_DISCONNECTED:
157         case AAUDIO_STREAM_STATE_CLOSING:
158         case AAUDIO_STREAM_STATE_CLOSED:
159         default:
160             ALOGW("%s() stream is dead, state = %s", __func__,
161                   AudioGlobal_convertStreamStateToText(getState()));
162             return AAUDIO_ERROR_INVALID_STATE;
163     }
164 
165     aaudio_result_t result = requestStart();
166     if (result == AAUDIO_OK) {
167         // We only call this for logging in "dumpsys audio". So ignore return code.
168         (void) mPlayerBase->start();
169     }
170     return result;
171 }
172 
systemPause()173 aaudio_result_t AudioStream::systemPause() {
174     std::lock_guard<std::mutex> lock(mStreamLock);
175 
176     if (!isPauseSupported()) {
177         return AAUDIO_ERROR_UNIMPLEMENTED;
178     }
179 
180     if (collidesWithCallback()) {
181         ALOGE("%s cannot be called from a callback!", __func__);
182         return AAUDIO_ERROR_INVALID_STATE;
183     }
184 
185     switch (getState()) {
186         // Proceed with pausing.
187         case AAUDIO_STREAM_STATE_STARTING:
188         case AAUDIO_STREAM_STATE_STARTED:
189         case AAUDIO_STREAM_STATE_DISCONNECTED:
190             break;
191 
192             // Transition from one inactive state to another.
193         case AAUDIO_STREAM_STATE_OPEN:
194         case AAUDIO_STREAM_STATE_STOPPED:
195         case AAUDIO_STREAM_STATE_FLUSHED:
196             setState(AAUDIO_STREAM_STATE_PAUSED);
197             return AAUDIO_OK;
198 
199             // Redundant?
200         case AAUDIO_STREAM_STATE_PAUSING:
201         case AAUDIO_STREAM_STATE_PAUSED:
202             return AAUDIO_OK;
203 
204             // Don't interfere with transitional states or when closed.
205         case AAUDIO_STREAM_STATE_STOPPING:
206         case AAUDIO_STREAM_STATE_FLUSHING:
207         case AAUDIO_STREAM_STATE_CLOSING:
208         case AAUDIO_STREAM_STATE_CLOSED:
209         default:
210             ALOGW("%s() stream not running, state = %s",
211                   __func__, AudioGlobal_convertStreamStateToText(getState()));
212             return AAUDIO_ERROR_INVALID_STATE;
213     }
214 
215     aaudio_result_t result = requestPause();
216     if (result == AAUDIO_OK) {
217         // We only call this for logging in "dumpsys audio". So ignore return code.
218         (void) mPlayerBase->pause();
219     }
220     return result;
221 }
222 
safeFlush()223 aaudio_result_t AudioStream::safeFlush() {
224     if (!isFlushSupported()) {
225         ALOGE("flush not supported for this stream");
226         return AAUDIO_ERROR_UNIMPLEMENTED;
227     }
228 
229     std::lock_guard<std::mutex> lock(mStreamLock);
230     if (collidesWithCallback()) {
231         ALOGE("stream cannot be flushed from a callback!");
232         return AAUDIO_ERROR_INVALID_STATE;
233     }
234 
235     aaudio_result_t result = AAudio_isFlushAllowed(getState());
236     if (result != AAUDIO_OK) {
237         return result;
238     }
239 
240     return requestFlush();
241 }
242 
systemStopFromCallback()243 aaudio_result_t AudioStream::systemStopFromCallback() {
244     std::lock_guard<std::mutex> lock(mStreamLock);
245     aaudio_result_t result = safeStop();
246     if (result == AAUDIO_OK) {
247         // We only call this for logging in "dumpsys audio". So ignore return code.
248         (void) mPlayerBase->stop();
249     }
250     return result;
251 }
252 
systemStopFromApp()253 aaudio_result_t AudioStream::systemStopFromApp() {
254     std::lock_guard<std::mutex> lock(mStreamLock);
255     if (collidesWithCallback()) {
256         ALOGE("stream cannot be stopped by calling from a callback!");
257         return AAUDIO_ERROR_INVALID_STATE;
258     }
259     aaudio_result_t result = safeStop();
260     if (result == AAUDIO_OK) {
261         // We only call this for logging in "dumpsys audio". So ignore return code.
262         (void) mPlayerBase->stop();
263     }
264     return result;
265 }
266 
267 // This must be called under mStreamLock.
safeStop()268 aaudio_result_t AudioStream::safeStop() {
269 
270     switch (getState()) {
271         // Proceed with stopping.
272         case AAUDIO_STREAM_STATE_STARTING:
273         case AAUDIO_STREAM_STATE_STARTED:
274         case AAUDIO_STREAM_STATE_DISCONNECTED:
275             break;
276 
277         // Transition from one inactive state to another.
278         case AAUDIO_STREAM_STATE_OPEN:
279         case AAUDIO_STREAM_STATE_PAUSED:
280         case AAUDIO_STREAM_STATE_FLUSHED:
281             setState(AAUDIO_STREAM_STATE_STOPPED);
282             return AAUDIO_OK;
283 
284         // Redundant?
285         case AAUDIO_STREAM_STATE_STOPPING:
286         case AAUDIO_STREAM_STATE_STOPPED:
287             return AAUDIO_OK;
288 
289         // Don't interfere with transitional states or when closed.
290         case AAUDIO_STREAM_STATE_PAUSING:
291         case AAUDIO_STREAM_STATE_FLUSHING:
292         case AAUDIO_STREAM_STATE_CLOSING:
293         case AAUDIO_STREAM_STATE_CLOSED:
294         default:
295             ALOGW("%s() stream not running, state = %s", __func__,
296                   AudioGlobal_convertStreamStateToText(getState()));
297             return AAUDIO_ERROR_INVALID_STATE;
298     }
299 
300     return requestStop();
301 }
302 
safeRelease()303 aaudio_result_t AudioStream::safeRelease() {
304     // This get temporarily unlocked in the release() when joining callback threads.
305     std::lock_guard<std::mutex> lock(mStreamLock);
306     if (collidesWithCallback()) {
307         ALOGE("%s cannot be called from a callback!", __func__);
308         return AAUDIO_ERROR_INVALID_STATE;
309     }
310     if (getState() == AAUDIO_STREAM_STATE_CLOSING) {
311         return AAUDIO_OK;
312     }
313     return release_l();
314 }
315 
setState(aaudio_stream_state_t state)316 void AudioStream::setState(aaudio_stream_state_t state) {
317     ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
318     // Track transition to DISCONNECTED state.
319     if (state == AAUDIO_STREAM_STATE_DISCONNECTED && mState != state) {
320         android::mediametrics::LogItem(mMetricsId)
321                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
322                 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
323                 .record();
324     }
325     // CLOSED is a final state
326     if (mState == AAUDIO_STREAM_STATE_CLOSED) {
327         ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
328 
329     // Once CLOSING, we can only move to CLOSED state.
330     } else if (mState == AAUDIO_STREAM_STATE_CLOSING
331                && state != AAUDIO_STREAM_STATE_CLOSED) {
332         ALOGE("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
333 
334     // Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
335     } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
336                && !(state == AAUDIO_STREAM_STATE_CLOSING
337                    || state == AAUDIO_STREAM_STATE_CLOSED)) {
338         ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
339 
340     } else {
341         mState = state;
342     }
343 }
344 
waitForStateChange(aaudio_stream_state_t currentState,aaudio_stream_state_t * nextState,int64_t timeoutNanoseconds)345 aaudio_result_t AudioStream::waitForStateChange(aaudio_stream_state_t currentState,
346                                                 aaudio_stream_state_t *nextState,
347                                                 int64_t timeoutNanoseconds)
348 {
349     aaudio_result_t result = updateStateMachine();
350     if (result != AAUDIO_OK) {
351         return result;
352     }
353 
354     int64_t durationNanos = 20 * AAUDIO_NANOS_PER_MILLISECOND; // arbitrary
355     aaudio_stream_state_t state = getState();
356     while (state == currentState && timeoutNanoseconds > 0) {
357         if (durationNanos > timeoutNanoseconds) {
358             durationNanos = timeoutNanoseconds;
359         }
360         AudioClock::sleepForNanos(durationNanos);
361         timeoutNanoseconds -= durationNanos;
362 
363         aaudio_result_t result = updateStateMachine();
364         if (result != AAUDIO_OK) {
365             return result;
366         }
367 
368         state = getState();
369     }
370     if (nextState != nullptr) {
371         *nextState = state;
372     }
373     return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK;
374 }
375 
376 // This registers the callback thread with the server before
377 // passing control to the app. This gives the server an opportunity to boost
378 // the thread's performance characteristics.
wrapUserThread()379 void* AudioStream::wrapUserThread() {
380     void* procResult = nullptr;
381     mThreadRegistrationResult = registerThread();
382     if (mThreadRegistrationResult == AAUDIO_OK) {
383         // Run callback loop. This may take a very long time.
384         procResult = mThreadProc(mThreadArg);
385         mThreadRegistrationResult = unregisterThread();
386     }
387     return procResult;
388 }
389 
390 // This is the entry point for the new thread created by createThread().
391 // It converts the 'C' function call to a C++ method call.
AudioStream_internalThreadProc(void * threadArg)392 static void* AudioStream_internalThreadProc(void* threadArg) {
393     AudioStream *audioStream = (AudioStream *) threadArg;
394     return audioStream->wrapUserThread();
395 }
396 
397 // This is not exposed in the API.
398 // But it is still used internally to implement callbacks for MMAP mode.
createThread(int64_t periodNanoseconds,aaudio_audio_thread_proc_t threadProc,void * threadArg)399 aaudio_result_t AudioStream::createThread(int64_t periodNanoseconds,
400                                      aaudio_audio_thread_proc_t threadProc,
401                                      void* threadArg)
402 {
403     if (mHasThread) {
404         ALOGE("createThread() - mHasThread already true");
405         return AAUDIO_ERROR_INVALID_STATE;
406     }
407     if (threadProc == nullptr) {
408         return AAUDIO_ERROR_NULL;
409     }
410     // Pass input parameters to the background thread.
411     mThreadProc = threadProc;
412     mThreadArg = threadArg;
413     setPeriodNanoseconds(periodNanoseconds);
414     int err = pthread_create(&mThread, nullptr, AudioStream_internalThreadProc, this);
415     if (err != 0) {
416         android::status_t status = -errno;
417         ALOGE("createThread() - pthread_create() failed, %d", status);
418         return AAudioConvert_androidToAAudioResult(status);
419     } else {
420         // TODO Use AAudioThread or maybe AndroidThread
421         // Name the thread with an increasing index, "AAudio_#", for debugging.
422         static std::atomic<uint32_t> nextThreadIndex{1};
423         char name[16]; // max length for a pthread_name
424         uint32_t index = nextThreadIndex++;
425         // Wrap the index so that we do not hit the 16 char limit
426         // and to avoid hard-to-read large numbers.
427         index = index % 100000;  // arbitrary
428         snprintf(name, sizeof(name), "AAudio_%u", index);
429         err = pthread_setname_np(mThread, name);
430         ALOGW_IF((err != 0), "Could not set name of AAudio thread. err = %d", err);
431 
432         mHasThread = true;
433         return AAUDIO_OK;
434     }
435 }
436 
437 // This must be called under mStreamLock.
joinThread(void ** returnArg,int64_t timeoutNanoseconds __unused)438 aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds __unused)
439 {
440     if (!mHasThread) {
441         ALOGE("joinThread() - but has no thread");
442         return AAUDIO_ERROR_INVALID_STATE;
443     }
444     aaudio_result_t result = AAUDIO_OK;
445     // If the callback is stopping the stream because the app passed back STOP
446     // then we don't need to join(). The thread is already about to exit.
447     if (pthread_self() != mThread) {
448         // Called from an app thread. Not the callback.
449         // Unlock because the callback may be trying to stop the stream but is blocked.
450         mStreamLock.unlock();
451 #if 0
452         // TODO implement equivalent of pthread_timedjoin_np()
453         struct timespec abstime;
454         int err = pthread_timedjoin_np(mThread, returnArg, &abstime);
455 #else
456         int err = pthread_join(mThread, returnArg);
457 #endif
458         mStreamLock.lock();
459         if (err) {
460             ALOGE("%s() pthread_join() returns err = %d", __func__, err);
461             result = AAudioConvert_androidToAAudioResult(-err);
462         }
463     }
464     // This must be set false so that the callback thread can be created
465     // when the stream is restarted.
466     mHasThread = false;
467     return (result != AAUDIO_OK) ? result : mThreadRegistrationResult;
468 }
469 
maybeCallDataCallback(void * audioData,int32_t numFrames)470 aaudio_data_callback_result_t AudioStream::maybeCallDataCallback(void *audioData,
471                                                                  int32_t numFrames) {
472     aaudio_data_callback_result_t result = AAUDIO_CALLBACK_RESULT_STOP;
473     AAudioStream_dataCallback dataCallback = getDataCallbackProc();
474     if (dataCallback != nullptr) {
475         // Store thread ID of caller to detect stop() and close() calls from callback.
476         pid_t expected = CALLBACK_THREAD_NONE;
477         if (mDataCallbackThread.compare_exchange_strong(expected, gettid())) {
478             result = (*dataCallback)(
479                     (AAudioStream *) this,
480                     getDataCallbackUserData(),
481                     audioData,
482                     numFrames);
483             mDataCallbackThread.store(CALLBACK_THREAD_NONE);
484         } else {
485             ALOGW("%s() data callback already running!", __func__);
486         }
487     }
488     return result;
489 }
490 
maybeCallErrorCallback(aaudio_result_t result)491 void AudioStream::maybeCallErrorCallback(aaudio_result_t result) {
492     AAudioStream_errorCallback errorCallback = getErrorCallbackProc();
493     if (errorCallback != nullptr) {
494         // Store thread ID of caller to detect stop() and close() calls from callback.
495         pid_t expected = CALLBACK_THREAD_NONE;
496         if (mErrorCallbackThread.compare_exchange_strong(expected, gettid())) {
497             (*errorCallback)(
498                     (AAudioStream *) this,
499                     getErrorCallbackUserData(),
500                     result);
501             mErrorCallbackThread.store(CALLBACK_THREAD_NONE);
502         } else {
503             ALOGW("%s() error callback already running!", __func__);
504         }
505     }
506 }
507 
508 // Is this running on the same thread as a callback?
509 // Note: This cannot be implemented using a thread_local because that would
510 // require using a thread_local variable that is shared between streams.
511 // So a thread_local variable would prevent stopping or closing stream A from
512 // a callback on stream B, which is currently legal and not so terrible.
collidesWithCallback() const513 bool AudioStream::collidesWithCallback() const {
514     pid_t thisThread = gettid();
515     // Compare the current thread ID with the thread ID of the callback
516     // threads to see it they match. If so then this code is being
517     // called from one of the stream callback functions.
518     return ((mErrorCallbackThread.load() == thisThread)
519             || (mDataCallbackThread.load() == thisThread));
520 }
521 
522 #if AAUDIO_USE_VOLUME_SHAPER
applyVolumeShaper(const android::media::VolumeShaper::Configuration & configuration __unused,const android::media::VolumeShaper::Operation & operation __unused)523 android::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
524         const android::media::VolumeShaper::Configuration& configuration __unused,
525         const android::media::VolumeShaper::Operation& operation __unused) {
526     ALOGW("applyVolumeShaper() is not supported");
527     return android::media::VolumeShaper::Status::ok();
528 }
529 #endif
530 
setDuckAndMuteVolume(float duckAndMuteVolume)531 void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
532     ALOGD("%s() to %f", __func__, duckAndMuteVolume);
533     mDuckAndMuteVolume = duckAndMuteVolume;
534     doSetVolume(); // apply this change
535 }
536 
MyPlayerBase(AudioStream * parent)537 AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
538 }
539 
~MyPlayerBase()540 AudioStream::MyPlayerBase::~MyPlayerBase() {
541 }
542 
registerWithAudioManager()543 void AudioStream::MyPlayerBase::registerWithAudioManager() {
544     if (!mRegistered) {
545         init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(mParent->getUsage()));
546         mRegistered = true;
547     }
548 }
549 
unregisterWithAudioManager()550 void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
551     if (mRegistered) {
552         baseDestroy();
553         mRegistered = false;
554     }
555 }
556 
destroy()557 void AudioStream::MyPlayerBase::destroy() {
558     unregisterWithAudioManager();
559 }
560 
561 }  // namespace aaudio
562