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