1 /* 2 * Copyright (C) 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 "AAudioServiceStreamBase" 18 //#define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include <iomanip> 22 #include <iostream> 23 #include <mutex> 24 25 #include "binding/IAAudioService.h" 26 #include "binding/AAudioServiceMessage.h" 27 #include "utility/AudioClock.h" 28 29 #include "AAudioEndpointManager.h" 30 #include "AAudioService.h" 31 #include "AAudioServiceEndpoint.h" 32 #include "AAudioServiceStreamBase.h" 33 #include "TimestampScheduler.h" 34 35 using namespace android; // TODO just import names needed 36 using namespace aaudio; // TODO just import names needed 37 38 /** 39 * Base class for streams in the service. 40 * @return 41 */ 42 43 AAudioServiceStreamBase::AAudioServiceStreamBase(AAudioService &audioService) 44 : mUpMessageQueue(nullptr) 45 , mTimestampThread("AATime") 46 , mAtomicTimestamp() 47 , mAudioService(audioService) { 48 mMmapClient.clientUid = -1; 49 mMmapClient.clientPid = -1; 50 mMmapClient.packageName = String16(""); 51 } 52 53 AAudioServiceStreamBase::~AAudioServiceStreamBase() { 54 ALOGD("~AAudioServiceStreamBase() destroying %p", this); 55 // If the stream is deleted when OPEN or in use then audio resources will leak. 56 // This would indicate an internal error. So we want to find this ASAP. 57 LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED 58 || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED 59 || getState() == AAUDIO_STREAM_STATE_DISCONNECTED), 60 "service stream still open, state = %d", getState()); 61 } 62 63 std::string AAudioServiceStreamBase::dumpHeader() { 64 return std::string(" T Handle UId Port Run State Format Burst Chan Capacity"); 65 } 66 67 std::string AAudioServiceStreamBase::dump() const { 68 std::stringstream result; 69 70 result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle 71 << std::dec << std::setfill(' ') ; 72 result << std::setw(6) << mMmapClient.clientUid; 73 result << std::setw(7) << mClientHandle; 74 result << std::setw(4) << (isRunning() ? "yes" : " no"); 75 result << std::setw(6) << getState(); 76 result << std::setw(7) << getFormat(); 77 result << std::setw(6) << mFramesPerBurst; 78 result << std::setw(5) << getSamplesPerFrame(); 79 result << std::setw(9) << getBufferCapacity(); 80 81 return result.str(); 82 } 83 84 aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request, 85 aaudio_sharing_mode_t sharingMode) { 86 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance(); 87 aaudio_result_t result = AAUDIO_OK; 88 89 mMmapClient.clientUid = request.getUserId(); 90 mMmapClient.clientPid = request.getProcessId(); 91 mMmapClient.packageName.setTo(String16("")); // TODO What should we do here? 92 93 // Limit scope of lock to avoid recursive lock in close(). 94 { 95 std::lock_guard<std::mutex> lock(mUpMessageQueueLock); 96 if (mUpMessageQueue != nullptr) { 97 ALOGE("%s() called twice", __func__); 98 return AAUDIO_ERROR_INVALID_STATE; 99 } 100 101 mUpMessageQueue = new SharedRingBuffer(); 102 result = mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), 103 QUEUE_UP_CAPACITY_COMMANDS); 104 if (result != AAUDIO_OK) { 105 goto error; 106 } 107 108 // This is not protected by a lock because the stream cannot be 109 // referenced until the service returns a handle to the client. 110 // So only one thread can open a stream. 111 mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, 112 request, 113 sharingMode); 114 if (mServiceEndpoint == nullptr) { 115 ALOGE("%s() openEndpoint() failed", __func__); 116 result = AAUDIO_ERROR_UNAVAILABLE; 117 goto error; 118 } 119 // Save a weak pointer that we will use to access the endpoint. 120 mServiceEndpointWeak = mServiceEndpoint; 121 122 mFramesPerBurst = mServiceEndpoint->getFramesPerBurst(); 123 copyFrom(*mServiceEndpoint); 124 } 125 return result; 126 127 error: 128 close(); 129 return result; 130 } 131 132 aaudio_result_t AAudioServiceStreamBase::close() { 133 aaudio_result_t result = AAUDIO_OK; 134 if (getState() == AAUDIO_STREAM_STATE_CLOSED) { 135 return AAUDIO_OK; 136 } 137 138 stop(); 139 140 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); 141 if (endpoint == nullptr) { 142 result = AAUDIO_ERROR_INVALID_STATE; 143 } else { 144 endpoint->unregisterStream(this); 145 AAudioEndpointManager &endpointManager = AAudioEndpointManager::getInstance(); 146 endpointManager.closeEndpoint(endpoint); 147 148 // AAudioService::closeStream() prevents two threads from closing at the same time. 149 mServiceEndpoint.clear(); // endpoint will hold the pointer until this method returns. 150 } 151 152 { 153 std::lock_guard<std::mutex> lock(mUpMessageQueueLock); 154 stopTimestampThread(); 155 delete mUpMessageQueue; 156 mUpMessageQueue = nullptr; 157 } 158 159 setState(AAUDIO_STREAM_STATE_CLOSED); 160 return result; 161 } 162 163 aaudio_result_t AAudioServiceStreamBase::startDevice() { 164 mClientHandle = AUDIO_PORT_HANDLE_NONE; 165 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); 166 if (endpoint == nullptr) { 167 ALOGE("%s() has no endpoint", __func__); 168 return AAUDIO_ERROR_INVALID_STATE; 169 } 170 return endpoint->startStream(this, &mClientHandle); 171 } 172 173 /** 174 * Start the flow of audio data. 175 * 176 * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete. 177 */ 178 aaudio_result_t AAudioServiceStreamBase::start() { 179 aaudio_result_t result = AAUDIO_OK; 180 181 if (isRunning()) { 182 return AAUDIO_OK; 183 } 184 185 setFlowing(false); 186 187 // Start with fresh presentation timestamps. 188 mAtomicTimestamp.clear(); 189 190 mClientHandle = AUDIO_PORT_HANDLE_NONE; 191 result = startDevice(); 192 if (result != AAUDIO_OK) goto error; 193 194 // This should happen at the end of the start. 195 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED); 196 setState(AAUDIO_STREAM_STATE_STARTED); 197 mThreadEnabled.store(true); 198 result = mTimestampThread.start(this); 199 if (result != AAUDIO_OK) goto error; 200 201 return result; 202 203 error: 204 disconnect(); 205 return result; 206 } 207 208 aaudio_result_t AAudioServiceStreamBase::pause() { 209 aaudio_result_t result = AAUDIO_OK; 210 if (!isRunning()) { 211 return result; 212 } 213 214 // Send it now because the timestamp gets rounded up when stopStream() is called below. 215 // Also we don't need the timestamps while we are shutting down. 216 sendCurrentTimestamp(); 217 218 result = stopTimestampThread(); 219 if (result != AAUDIO_OK) { 220 disconnect(); 221 return result; 222 } 223 224 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); 225 if (endpoint == nullptr) { 226 ALOGE("%s() has no endpoint", __func__); 227 return AAUDIO_ERROR_INVALID_STATE; 228 } 229 result = endpoint->stopStream(this, mClientHandle); 230 if (result != AAUDIO_OK) { 231 ALOGE("%s() mServiceEndpoint returned %d, %s", __func__, result, getTypeText()); 232 disconnect(); // TODO should we return or pause Base first? 233 } 234 235 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED); 236 setState(AAUDIO_STREAM_STATE_PAUSED); 237 return result; 238 } 239 240 aaudio_result_t AAudioServiceStreamBase::stop() { 241 aaudio_result_t result = AAUDIO_OK; 242 if (!isRunning()) { 243 return result; 244 } 245 246 setState(AAUDIO_STREAM_STATE_STOPPING); 247 248 // Send it now because the timestamp gets rounded up when stopStream() is called below. 249 // Also we don't need the timestamps while we are shutting down. 250 sendCurrentTimestamp(); // warning - this calls a virtual function 251 result = stopTimestampThread(); 252 if (result != AAUDIO_OK) { 253 disconnect(); 254 return result; 255 } 256 257 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); 258 if (endpoint == nullptr) { 259 ALOGE("%s() has no endpoint", __func__); 260 return AAUDIO_ERROR_INVALID_STATE; 261 } 262 // TODO wait for data to be played out 263 result = endpoint->stopStream(this, mClientHandle); 264 if (result != AAUDIO_OK) { 265 ALOGE("%s() stopStream returned %d, %s", __func__, result, getTypeText()); 266 disconnect(); 267 // TODO what to do with result here? 268 } 269 270 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED); 271 setState(AAUDIO_STREAM_STATE_STOPPED); 272 return result; 273 } 274 275 aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() { 276 aaudio_result_t result = AAUDIO_OK; 277 // clear flag that tells thread to loop 278 if (mThreadEnabled.exchange(false)) { 279 result = mTimestampThread.stop(); 280 } 281 return result; 282 } 283 284 aaudio_result_t AAudioServiceStreamBase::flush() { 285 aaudio_result_t result = AAudio_isFlushAllowed(getState()); 286 if (result != AAUDIO_OK) { 287 return result; 288 } 289 290 // Data will get flushed when the client receives the FLUSHED event. 291 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED); 292 setState(AAUDIO_STREAM_STATE_FLUSHED); 293 return AAUDIO_OK; 294 } 295 296 // implement Runnable, periodically send timestamps to client 297 void AAudioServiceStreamBase::run() { 298 ALOGD("%s() %s entering >>>>>>>>>>>>>> TIMESTAMPS", __func__, getTypeText()); 299 TimestampScheduler timestampScheduler; 300 timestampScheduler.setBurstPeriod(mFramesPerBurst, getSampleRate()); 301 timestampScheduler.start(AudioClock::getNanoseconds()); 302 int64_t nextTime = timestampScheduler.nextAbsoluteTime(); 303 while(mThreadEnabled.load()) { 304 if (AudioClock::getNanoseconds() >= nextTime) { 305 aaudio_result_t result = sendCurrentTimestamp(); 306 if (result != AAUDIO_OK) { 307 break; 308 } 309 nextTime = timestampScheduler.nextAbsoluteTime(); 310 } else { 311 // Sleep until it is time to send the next timestamp. 312 // TODO Wait for a signal with a timeout so that we can stop more quickly. 313 AudioClock::sleepUntilNanoTime(nextTime); 314 } 315 } 316 ALOGD("%s() %s exiting <<<<<<<<<<<<<< TIMESTAMPS", __func__, getTypeText()); 317 } 318 319 void AAudioServiceStreamBase::disconnect() { 320 if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) { 321 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED); 322 setState(AAUDIO_STREAM_STATE_DISCONNECTED); 323 } 324 } 325 326 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event, 327 double dataDouble) { 328 AAudioServiceMessage command; 329 command.what = AAudioServiceMessage::code::EVENT; 330 command.event.event = event; 331 command.event.dataDouble = dataDouble; 332 return writeUpMessageQueue(&command); 333 } 334 335 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event, 336 int64_t dataLong) { 337 AAudioServiceMessage command; 338 command.what = AAudioServiceMessage::code::EVENT; 339 command.event.event = event; 340 command.event.dataLong = dataLong; 341 return writeUpMessageQueue(&command); 342 } 343 344 aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) { 345 std::lock_guard<std::mutex> lock(mUpMessageQueueLock); 346 if (mUpMessageQueue == nullptr) { 347 ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__); 348 return AAUDIO_ERROR_NULL; 349 } 350 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1); 351 if (count != 1) { 352 ALOGE("%s(): Queue full. Did client die? %s", __func__, getTypeText()); 353 return AAUDIO_ERROR_WOULD_BLOCK; 354 } else { 355 return AAUDIO_OK; 356 } 357 } 358 359 aaudio_result_t AAudioServiceStreamBase::sendXRunCount(int32_t xRunCount) { 360 return sendServiceEvent(AAUDIO_SERVICE_EVENT_XRUN, (int64_t) xRunCount); 361 } 362 363 aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() { 364 AAudioServiceMessage command; 365 // Send a timestamp for the clock model. 366 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position, 367 &command.timestamp.timestamp); 368 if (result == AAUDIO_OK) { 369 ALOGV("%s() SERVICE %8lld at %lld", __func__, 370 (long long) command.timestamp.position, 371 (long long) command.timestamp.timestamp); 372 command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE; 373 result = writeUpMessageQueue(&command); 374 375 if (result == AAUDIO_OK) { 376 // Send a hardware timestamp for presentation time. 377 result = getHardwareTimestamp(&command.timestamp.position, 378 &command.timestamp.timestamp); 379 if (result == AAUDIO_OK) { 380 ALOGV("%s() HARDWARE %8lld at %lld", __func__, 381 (long long) command.timestamp.position, 382 (long long) command.timestamp.timestamp); 383 command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE; 384 result = writeUpMessageQueue(&command); 385 } 386 } 387 } 388 389 if (result == AAUDIO_ERROR_UNAVAILABLE) { // TODO review best error code 390 result = AAUDIO_OK; // just not available yet, try again later 391 } 392 return result; 393 } 394 395 /** 396 * Get an immutable description of the in-memory queues 397 * used to communicate with the underlying HAL or Service. 398 */ 399 aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) { 400 { 401 std::lock_guard<std::mutex> lock(mUpMessageQueueLock); 402 if (mUpMessageQueue == nullptr) { 403 ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__); 404 return AAUDIO_ERROR_NULL; 405 } 406 // Gather information on the message queue. 407 mUpMessageQueue->fillParcelable(parcelable, 408 parcelable.mUpMessageQueueParcelable); 409 } 410 return getAudioDataDescription(parcelable); 411 } 412 413 void AAudioServiceStreamBase::onVolumeChanged(float volume) { 414 sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume); 415 } 416 417 int32_t AAudioServiceStreamBase::incrementServiceReferenceCount_l() { 418 return ++mCallingCount; 419 } 420 421 int32_t AAudioServiceStreamBase::decrementServiceReferenceCount_l() { 422 int32_t count = --mCallingCount; 423 // Each call to increment should be balanced with one call to decrement. 424 assert(count >= 0); 425 return count; 426 } 427