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