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 <com_android_media_aaudio.h>
26 #include <media/MediaMetricsItem.h>
27 #include <media/TypeConverter.h>
28 #include <mediautils/SchedulingPolicyService.h>
29
30 #include "binding/AAudioServiceMessage.h"
31 #include "core/AudioGlobal.h"
32 #include "utility/AudioClock.h"
33
34 #include "AAudioEndpointManager.h"
35 #include "AAudioService.h"
36 #include "AAudioServiceEndpoint.h"
37 #include "AAudioServiceStreamBase.h"
38
39 using namespace android; // TODO just import names needed
40 using namespace aaudio; // TODO just import names needed
41
42 using content::AttributionSourceState;
43
44 static const int64_t TIMEOUT_NANOS = 3LL * 1000 * 1000 * 1000;
45 // If the stream is idle for more than `IDLE_TIMEOUT_NANOS`, the stream will be put into standby.
46 static const int64_t IDLE_TIMEOUT_NANOS = 3e9;
47
48 /**
49 * Base class for streams in the service.
50 * @return
51 */
52
AAudioServiceStreamBase(AAudioService & audioService)53 AAudioServiceStreamBase::AAudioServiceStreamBase(AAudioService &audioService)
54 : mCommandThread("AACommand")
55 , mAtomicStreamTimestamp()
56 , mAudioService(audioService) {
57 mMmapClient.attributionSource = AttributionSourceState();
58 }
59
~AAudioServiceStreamBase()60 AAudioServiceStreamBase::~AAudioServiceStreamBase() {
61 ALOGD("%s() called", __func__);
62
63 // May not be set if open failed.
64 if (mMetricsId.size() > 0) {
65 mediametrics::LogItem(mMetricsId)
66 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
67 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
68 .record();
69 }
70
71 // If the stream is deleted when OPEN or in use then audio resources will leak.
72 // This would indicate an internal error. So we want to find this ASAP.
73 LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
74 || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED),
75 "service stream %p still open, state = %d",
76 this, getState());
77
78 // Stop the command thread before destroying.
79 stopCommandThread();
80 }
81
dumpHeader()82 std::string AAudioServiceStreamBase::dumpHeader() {
83 return {" T Handle UId Port Run State Format Burst Chan Mask Capacity"
84 " HwFormat HwChan HwRate"};
85 }
86
dump() const87 std::string AAudioServiceStreamBase::dump() const {
88 std::stringstream result;
89
90 result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
91 << std::dec << std::setfill(' ') ;
92 result << std::setw(6) << mMmapClient.attributionSource.uid;
93 result << std::setw(7) << mClientHandle;
94 result << std::setw(4) << (isRunning() ? "yes" : " no");
95 result << std::setw(6) << getState();
96 result << std::setw(7) << getFormat();
97 result << std::setw(6) << mFramesPerBurst;
98 result << std::setw(5) << getSamplesPerFrame();
99 result << std::setw(8) << std::hex << getChannelMask() << std::dec;
100 result << std::setw(9) << getBufferCapacity();
101 result << std::setw(9) << getHardwareFormat();
102 result << std::setw(7) << getHardwareSamplesPerFrame();
103 result << std::setw(7) << getHardwareSampleRate();
104
105 return result.str();
106 }
107
logOpen(aaudio_handle_t streamHandle)108 void AAudioServiceStreamBase::logOpen(aaudio_handle_t streamHandle) {
109 // This is the first log sent from the AAudio Service for a stream.
110 mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM)
111 + std::to_string(streamHandle);
112
113 audio_attributes_t attributes = AAudioServiceEndpoint::getAudioAttributesFrom(this);
114
115 // Once this item is logged by the server, the client with the same PID, UID
116 // can also log properties.
117 mediametrics::LogItem(mMetricsId)
118 .setPid(getOwnerProcessId())
119 .setUid(getOwnerUserId())
120 .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)getOwnerUserId())
121 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN)
122 // the following are immutable
123 .set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, (int32_t)getBufferCapacity())
124 .set(AMEDIAMETRICS_PROP_BURSTFRAMES, (int32_t)getFramesPerBurst())
125 .set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)getSamplesPerFrame())
126 .set(AMEDIAMETRICS_PROP_CONTENTTYPE, toString(attributes.content_type).c_str())
127 .set(AMEDIAMETRICS_PROP_DIRECTION,
128 AudioGlobal_convertDirectionToText(getDirection()))
129 .set(AMEDIAMETRICS_PROP_ENCODING, toString(getFormat()).c_str())
130 .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEID, android::getFirstDeviceId(getDeviceIds()))
131 .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEIDS, android::toString(getDeviceIds()).c_str())
132 .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)getSampleRate())
133 .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)getSessionId())
134 .set(AMEDIAMETRICS_PROP_SOURCE, toString(attributes.source).c_str())
135 .set(AMEDIAMETRICS_PROP_USAGE, toString(attributes.usage).c_str())
136 .record();
137 }
138
open(const aaudio::AAudioStreamRequest & request)139 aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request) {
140 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
141 aaudio_result_t result = AAUDIO_OK;
142
143 mMmapClient.attributionSource = request.getAttributionSource();
144 // TODO b/182392769: use attribution source util
145 mMmapClient.attributionSource.uid = VALUE_OR_FATAL(
146 legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
147 mMmapClient.attributionSource.pid = VALUE_OR_FATAL(
148 legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
149
150 // Limit scope of lock to avoid recursive lock in close().
151 {
152 std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
153 if (mUpMessageQueue != nullptr) {
154 ALOGE("%s() called twice", __func__);
155 return AAUDIO_ERROR_INVALID_STATE;
156 }
157
158 mUpMessageQueue = std::make_shared<SharedRingBuffer>();
159 result = mUpMessageQueue->allocate(sizeof(AAudioServiceMessage),
160 QUEUE_UP_CAPACITY_COMMANDS);
161 if (result != AAUDIO_OK) {
162 goto error;
163 }
164
165 // This is not protected by a lock because the stream cannot be
166 // referenced until the service returns a handle to the client.
167 // So only one thread can open a stream.
168 mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService,
169 request);
170 if (mServiceEndpoint == nullptr) {
171 result = AAUDIO_ERROR_UNAVAILABLE;
172 goto error;
173 }
174 // Save a weak pointer that we will use to access the endpoint.
175 mServiceEndpointWeak = mServiceEndpoint;
176
177 mFramesPerBurst = mServiceEndpoint->getFramesPerBurst();
178 copyFrom(*mServiceEndpoint);
179 }
180
181 // Make sure this object does not get deleted before the run() method
182 // can protect it by making a strong pointer.
183 mCommandQueue.startWaiting();
184 mThreadEnabled = true;
185 incStrong(nullptr); // See run() method.
186 result = mCommandThread.start(this);
187 if (result != AAUDIO_OK) {
188 decStrong(nullptr); // run() can't do it so we have to do it here.
189 goto error;
190 }
191 return result;
192
193 error:
194 closeAndClear();
195 stopCommandThread();
196 return result;
197 }
198
close()199 aaudio_result_t AAudioServiceStreamBase::close() {
200 aaudio_result_t result = sendCommand(CLOSE, nullptr, true /*waitForReply*/, TIMEOUT_NANOS);
201 if (result == AAUDIO_ERROR_ALREADY_CLOSED) {
202 // AAUDIO_ERROR_ALREADY_CLOSED is not a really error but just indicate the stream has
203 // already been closed. In that case, there is no need to close the stream once more.
204 ALOGD("The stream(%d) is already closed", mHandle);
205 return AAUDIO_OK;
206 }
207
208 stopCommandThread();
209
210 return result;
211 }
212
close_l()213 aaudio_result_t AAudioServiceStreamBase::close_l() {
214 if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
215 return AAUDIO_ERROR_ALREADY_CLOSED;
216 }
217
218 // This will stop the stream, just in case it was not already stopped.
219 stop_l();
220
221 return closeAndClear();
222 }
223
startDevice_l()224 aaudio_result_t AAudioServiceStreamBase::startDevice_l() {
225 mClientHandle = AUDIO_PORT_HANDLE_NONE;
226 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
227 if (endpoint == nullptr) {
228 ALOGE("%s() has no endpoint", __func__);
229 return AAUDIO_ERROR_INVALID_STATE;
230 }
231 if (!endpoint->isConnected()) {
232 ALOGE("%s() endpoint was already disconnected", __func__);
233 return AAUDIO_ERROR_DISCONNECTED;
234 }
235 return endpoint->startStream(this, &mClientHandle);
236 }
237
238 /**
239 * Start the flow of audio data.
240 *
241 * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
242 */
start()243 aaudio_result_t AAudioServiceStreamBase::start() {
244 return sendCommand(START, nullptr, true /*waitForReply*/, TIMEOUT_NANOS);
245 }
246
start_l()247 aaudio_result_t AAudioServiceStreamBase::start_l() {
248 const int64_t beginNs = AudioClock::getNanoseconds();
249 aaudio_result_t result = AAUDIO_OK;
250
251 if (auto state = getState();
252 state == AAUDIO_STREAM_STATE_CLOSED || isDisconnected_l()) {
253 ALOGW("%s() already CLOSED, returns INVALID_STATE, handle = %d",
254 __func__, getHandle());
255 return AAUDIO_ERROR_INVALID_STATE;
256 }
257
258 if (mStandby) {
259 ALOGW("%s() the stream is standby, return ERROR_STANDBY, "
260 "expecting the client call exitStandby before start", __func__);
261 return AAUDIO_ERROR_STANDBY;
262 }
263
264 mediametrics::Defer defer([&] {
265 mediametrics::LogItem(mMetricsId)
266 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
267 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
268 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
269 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
270 .record(); });
271
272 if (isRunning()) {
273 return result;
274 }
275
276 setFlowing(false);
277 setSuspended(false);
278
279 // Start with fresh presentation timestamps.
280 mAtomicStreamTimestamp.clear();
281
282 mClientHandle = AUDIO_PORT_HANDLE_NONE;
283 result = startDevice_l();
284 if (result != AAUDIO_OK) goto error;
285
286 // This should happen at the end of the start.
287 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED, static_cast<int64_t>(mClientHandle));
288 setState(AAUDIO_STREAM_STATE_STARTED);
289
290 return result;
291
292 error:
293 disconnect_l();
294 return result;
295 }
296
pause()297 aaudio_result_t AAudioServiceStreamBase::pause() {
298 return sendCommand(PAUSE, nullptr, true /*waitForReply*/, TIMEOUT_NANOS);
299 }
300
pause_l()301 aaudio_result_t AAudioServiceStreamBase::pause_l() {
302 aaudio_result_t result = AAUDIO_OK;
303 if (!isRunning()) {
304 return result;
305 }
306 const int64_t beginNs = AudioClock::getNanoseconds();
307
308 mediametrics::Defer defer([&] {
309 mediametrics::LogItem(mMetricsId)
310 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_PAUSE)
311 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
312 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
313 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
314 .record(); });
315
316 setState(AAUDIO_STREAM_STATE_PAUSING);
317
318 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
319 if (endpoint == nullptr) {
320 ALOGE("%s() has no endpoint", __func__);
321 result = AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking
322 return result;
323 }
324 result = endpoint->stopStream(this, mClientHandle);
325 if (result != AAUDIO_OK) {
326 ALOGE("%s() mServiceEndpoint returned %d, %s", __func__, result, getTypeText());
327 disconnect_l(); // TODO should we return or pause Base first?
328 }
329
330 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
331 setState(AAUDIO_STREAM_STATE_PAUSED);
332 return result;
333 }
334
stop()335 aaudio_result_t AAudioServiceStreamBase::stop() {
336 return sendCommand(STOP, nullptr, true /*waitForReply*/, TIMEOUT_NANOS);
337 }
338
stop_l()339 aaudio_result_t AAudioServiceStreamBase::stop_l() {
340 aaudio_result_t result = AAUDIO_OK;
341 if (!isRunning()) {
342 ALOGW("%s() stream not running, returning early", __func__);
343 return result;
344 }
345 const int64_t beginNs = AudioClock::getNanoseconds();
346
347 mediametrics::Defer defer([&] {
348 mediametrics::LogItem(mMetricsId)
349 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
350 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
351 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
352 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
353 .record(); });
354
355 setState(AAUDIO_STREAM_STATE_STOPPING);
356
357 if (result != AAUDIO_OK) {
358 disconnect_l();
359 return result;
360 }
361
362 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
363 if (endpoint == nullptr) {
364 ALOGE("%s() has no endpoint", __func__);
365 result = AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking
366 return result;
367 }
368 // TODO wait for data to be played out
369 result = endpoint->stopStream(this, mClientHandle);
370 if (result != AAUDIO_OK) {
371 ALOGE("%s() stopStream returned %d, %s", __func__, result, getTypeText());
372 disconnect_l();
373 // TODO what to do with result here?
374 }
375
376 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
377 setState(AAUDIO_STREAM_STATE_STOPPED);
378 return result;
379 }
380
flush()381 aaudio_result_t AAudioServiceStreamBase::flush() {
382 return sendCommand(FLUSH, nullptr, true /*waitForReply*/, TIMEOUT_NANOS);
383 }
384
flush_l()385 aaudio_result_t AAudioServiceStreamBase::flush_l() {
386 aaudio_result_t result = AAudio_isFlushAllowed(getState());
387 if (result != AAUDIO_OK) {
388 return result;
389 }
390 const int64_t beginNs = AudioClock::getNanoseconds();
391
392 mediametrics::Defer defer([&] {
393 mediametrics::LogItem(mMetricsId)
394 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH)
395 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
396 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
397 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
398 .record(); });
399
400 // Data will get flushed when the client receives the FLUSHED event.
401 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
402 setState(AAUDIO_STREAM_STATE_FLUSHED);
403 return AAUDIO_OK;
404 }
405
406 // implement Runnable, periodically send timestamps to client and process commands from queue.
407 // Enter standby mode if idle for a while.
408 __attribute__((no_sanitize("integer")))
run()409 void AAudioServiceStreamBase::run() {
410 ALOGD("%s() %s entering >>>>>>>>>>>>>> COMMANDS", __func__, getTypeText());
411 // Hold onto the ref counted stream until the end.
412 android::sp<AAudioServiceStreamBase> holdStream(this);
413 TimestampScheduler timestampScheduler;
414 int64_t nextTimestampReportTime;
415 int64_t nextDataReportTime;
416 // When to try to enter standby.
417 int64_t standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
418 // Balance the incStrong from when the thread was launched.
419 holdStream->decStrong(nullptr);
420
421 // Taking mLock while starting the thread. All the operation must be able to
422 // run with holding the lock.
423 std::scoped_lock<std::mutex> _l(mLock);
424
425 int32_t loopCount = 0;
426 while (mThreadEnabled.load()) {
427 loopCount++;
428 int64_t timeoutNanos = -1; // wait forever
429 if (isDisconnected_l() || isIdle_l()) {
430 if (isStandbyImplemented() && !isStandby_l()) {
431 // If not in standby mode, wait until standby time.
432 timeoutNanos = standbyTime - AudioClock::getNanoseconds();
433 timeoutNanos = std::max<int64_t>(0, timeoutNanos);
434 }
435 // Otherwise, keep `timeoutNanos` as -1 to wait forever until next command.
436 } else if (isRunning()) {
437 timeoutNanos = std::min(nextTimestampReportTime, nextDataReportTime)
438 - AudioClock::getNanoseconds();
439 timeoutNanos = std::max<int64_t>(0, timeoutNanos);
440 }
441 auto command = mCommandQueue.waitForCommand(timeoutNanos);
442 if (!mThreadEnabled) {
443 // Break the loop if the thread is disabled.
444 break;
445 }
446
447 // Is it time to send timestamps?
448 if (isRunning() && !isDisconnected_l()) {
449 auto currentTimestamp = AudioClock::getNanoseconds();
450 if (currentTimestamp >= nextDataReportTime) {
451 reportData_l();
452 nextDataReportTime = nextDataReportTime_l();
453 }
454 if (currentTimestamp >= nextTimestampReportTime) {
455 // It is time to update timestamp.
456 if (sendCurrentTimestamp_l() != AAUDIO_OK) {
457 ALOGE("Failed to send current timestamp, stop updating timestamp");
458 disconnect_l();
459 }
460 nextTimestampReportTime = timestampScheduler.nextAbsoluteTime();
461 }
462 }
463
464 // Is it time to enter standby?
465 if ((isIdle_l() || isDisconnected_l())
466 && isStandbyImplemented()
467 && !isStandby_l()
468 && (AudioClock::getNanoseconds() >= standbyTime)) {
469 ALOGD("%s() call standby_l(), %d loops", __func__, loopCount);
470 aaudio_result_t result = standby_l();
471 if (result != AAUDIO_OK) {
472 ALOGW("Failed to enter standby, error = %d", result);
473 // Try again later.
474 standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
475 }
476 }
477
478 if (command != nullptr) {
479 ALOGD("%s() got COMMAND opcode %d after %d loops",
480 __func__, command->operationCode, loopCount);
481 std::scoped_lock<std::mutex> _commandLock(command->lock);
482 switch (command->operationCode) {
483 case START:
484 command->result = start_l();
485 timestampScheduler.setBurstPeriod(mFramesPerBurst, getSampleRate());
486 timestampScheduler.start(AudioClock::getNanoseconds());
487 nextTimestampReportTime = timestampScheduler.nextAbsoluteTime();
488 nextDataReportTime = nextDataReportTime_l();
489 break;
490 case PAUSE:
491 command->result = pause_l();
492 standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
493 break;
494 case STOP:
495 command->result = stop_l();
496 standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
497 break;
498 case FLUSH:
499 command->result = flush_l();
500 break;
501 case CLOSE:
502 command->result = close_l();
503 break;
504 case DISCONNECT:
505 disconnect_l();
506 break;
507 case REGISTER_AUDIO_THREAD: {
508 auto param = (RegisterAudioThreadParam *) command->parameter.get();
509 command->result =
510 param == nullptr ? AAUDIO_ERROR_ILLEGAL_ARGUMENT
511 : registerAudioThread_l(param->mOwnerPid,
512 param->mClientThreadId,
513 param->mPriority);
514 }
515 break;
516 case UNREGISTER_AUDIO_THREAD: {
517 auto param = (UnregisterAudioThreadParam *) command->parameter.get();
518 command->result =
519 param == nullptr ? AAUDIO_ERROR_ILLEGAL_ARGUMENT
520 : unregisterAudioThread_l(param->mClientThreadId);
521 }
522 break;
523 case GET_DESCRIPTION: {
524 auto param = (GetDescriptionParam *) command->parameter.get();
525 command->result = param == nullptr ? AAUDIO_ERROR_ILLEGAL_ARGUMENT
526 : getDescription_l(param->mParcelable);
527 }
528 break;
529 case EXIT_STANDBY: {
530 auto param = (ExitStandbyParam *) command->parameter.get();
531 command->result = param == nullptr ? AAUDIO_ERROR_ILLEGAL_ARGUMENT
532 : exitStandby_l(param->mParcelable);
533 standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
534 } break;
535 case START_CLIENT: {
536 auto param = (StartClientParam *) command->parameter.get();
537 command->result = param == nullptr ? AAUDIO_ERROR_ILLEGAL_ARGUMENT
538 : startClient_l(param->mClient,
539 param->mAttr,
540 param->mClientHandle);
541 } break;
542 case STOP_CLIENT: {
543 auto param = (StopClientParam *) command->parameter.get();
544 command->result = param == nullptr ? AAUDIO_ERROR_ILLEGAL_ARGUMENT
545 : stopClient_l(param->mClientHandle);
546 } break;
547 default:
548 ALOGE("Invalid command op code: %d", command->operationCode);
549 break;
550 }
551 if (command->isWaitingForReply) {
552 command->isWaitingForReply = false;
553 command->conditionVariable.notify_one();
554 }
555 }
556 }
557 ALOGD("%s() %s exiting after %d loops <<<<<<<<<<<<<< COMMANDS",
558 __func__, getTypeText(), loopCount);
559 }
560
disconnect()561 void AAudioServiceStreamBase::disconnect() {
562 sendCommand(DISCONNECT);
563 }
564
disconnect_l()565 void AAudioServiceStreamBase::disconnect_l() {
566 if (!isDisconnected_l() && getState() != AAUDIO_STREAM_STATE_CLOSED) {
567
568 mediametrics::LogItem(mMetricsId)
569 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
570 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
571 .record();
572
573 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
574 setDisconnected_l(true);
575 }
576 }
577
registerAudioThread(pid_t clientThreadId,int priority)578 aaudio_result_t AAudioServiceStreamBase::registerAudioThread(pid_t clientThreadId, int priority) {
579 const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
580 return sendCommand(REGISTER_AUDIO_THREAD,
581 std::make_shared<RegisterAudioThreadParam>(ownerPid, clientThreadId, priority),
582 true /*waitForReply*/,
583 TIMEOUT_NANOS);
584 }
585
registerAudioThread_l(pid_t ownerPid,pid_t clientThreadId,int priority)586 aaudio_result_t AAudioServiceStreamBase::registerAudioThread_l(
587 pid_t ownerPid, pid_t clientThreadId, int priority) {
588 aaudio_result_t result = AAUDIO_OK;
589 if (getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
590 ALOGE("AAudioService::registerAudioThread(), thread already registered");
591 result = AAUDIO_ERROR_INVALID_STATE;
592 } else {
593 setRegisteredThread(clientThreadId);
594 int err = android::requestPriority(ownerPid, clientThreadId,
595 priority, true /* isForApp */);
596 if (err != 0) {
597 ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
598 clientThreadId, errno, priority);
599 result = AAUDIO_ERROR_INTERNAL;
600 }
601 }
602 return result;
603 }
604
unregisterAudioThread(pid_t clientThreadId)605 aaudio_result_t AAudioServiceStreamBase::unregisterAudioThread(pid_t clientThreadId) {
606 return sendCommand(UNREGISTER_AUDIO_THREAD,
607 std::make_shared<UnregisterAudioThreadParam>(clientThreadId),
608 true /*waitForReply*/,
609 TIMEOUT_NANOS);
610 }
611
unregisterAudioThread_l(pid_t clientThreadId)612 aaudio_result_t AAudioServiceStreamBase::unregisterAudioThread_l(pid_t clientThreadId) {
613 aaudio_result_t result = AAUDIO_OK;
614 if (getRegisteredThread() != clientThreadId) {
615 ALOGE("%s(), wrong thread", __func__);
616 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
617 } else {
618 setRegisteredThread(0);
619 }
620 return result;
621 }
622
setState(aaudio_stream_state_t state)623 void AAudioServiceStreamBase::setState(aaudio_stream_state_t state) {
624 // CLOSED is a final state.
625 if (mState != AAUDIO_STREAM_STATE_CLOSED) {
626 mState = state;
627 } else {
628 ALOGW_IF(mState != state, "%s(%d) when already CLOSED", __func__, state);
629 }
630 }
631
sendServiceEvent(aaudio_service_event_t event,double dataDouble)632 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
633 double dataDouble) {
634 AAudioServiceMessage command;
635 command.what = AAudioServiceMessage::code::EVENT;
636 command.event.event = event;
637 command.event.dataDouble = dataDouble;
638 return writeUpMessageQueue(&command);
639 }
640
sendServiceEvent(aaudio_service_event_t event,int64_t dataLong)641 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
642 int64_t dataLong) {
643 AAudioServiceMessage command;
644 command.what = AAudioServiceMessage::code::EVENT;
645 command.event.event = event;
646 command.event.dataLong = dataLong;
647 return writeUpMessageQueue(&command);
648 }
649
isUpMessageQueueBusy()650 bool AAudioServiceStreamBase::isUpMessageQueueBusy() {
651 std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
652 if (mUpMessageQueue == nullptr) {
653 ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
654 return true;
655 }
656 // Is it half full or more
657 return mUpMessageQueue->getFractionalFullness() >= 0.5;
658 }
659
writeUpMessageQueue(AAudioServiceMessage * command)660 aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
661 std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
662 if (mUpMessageQueue == nullptr) {
663 ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
664 return AAUDIO_ERROR_NULL;
665 }
666 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
667 if (count != 1) {
668 ALOGW("%s(): Queue full. Did client stop? Suspending stream. what = %u, %s",
669 __func__, static_cast<unsigned>(command->what), getTypeText());
670 setSuspended(true);
671 return AAUDIO_ERROR_WOULD_BLOCK;
672 } else {
673 if (isSuspended()) {
674 ALOGW("%s(): Queue no longer full. Un-suspending the stream.", __func__);
675 setSuspended(false);
676 }
677 return AAUDIO_OK;
678 }
679 }
680
sendXRunCount(int32_t xRunCount)681 aaudio_result_t AAudioServiceStreamBase::sendXRunCount(int32_t xRunCount) {
682 return sendServiceEvent(AAUDIO_SERVICE_EVENT_XRUN, (int64_t) xRunCount);
683 }
684
sendCurrentTimestamp_l()685 aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp_l() {
686 AAudioServiceMessage command;
687 // It is not worth filling up the queue with timestamps.
688 // That can cause the stream to get suspended.
689 // So just drop the timestamp if the queue is getting full.
690 if (isUpMessageQueueBusy()) {
691 return AAUDIO_OK;
692 }
693
694 // Send a timestamp for the clock model.
695 aaudio_result_t result = getFreeRunningPosition_l(&command.timestamp.position,
696 &command.timestamp.timestamp);
697 if (result == AAUDIO_OK) {
698 ALOGV("%s() SERVICE %8lld at %lld", __func__,
699 (long long) command.timestamp.position,
700 (long long) command.timestamp.timestamp);
701 command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE;
702 result = writeUpMessageQueue(&command);
703
704 if (result == AAUDIO_OK) {
705 // Send a hardware timestamp for presentation time.
706 result = getHardwareTimestamp_l(&command.timestamp.position,
707 &command.timestamp.timestamp);
708 if (result == AAUDIO_OK) {
709 ALOGV("%s() HARDWARE %8lld at %lld", __func__,
710 (long long) command.timestamp.position,
711 (long long) command.timestamp.timestamp);
712 command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE;
713 result = writeUpMessageQueue(&command);
714 }
715 }
716 }
717
718 if (result == AAUDIO_ERROR_UNAVAILABLE) { // TODO review best error code
719 result = AAUDIO_OK; // just not available yet, try again later
720 }
721 return result;
722 }
723
724 /**
725 * Get an immutable description of the in-memory queues
726 * used to communicate with the underlying HAL or Service.
727 */
getDescription(AudioEndpointParcelable & parcelable)728 aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
729 return sendCommand(
730 GET_DESCRIPTION,
731 std::make_shared<GetDescriptionParam>(&parcelable),
732 true /*waitForReply*/,
733 TIMEOUT_NANOS);
734 }
735
getDescription_l(AudioEndpointParcelable * parcelable)736 aaudio_result_t AAudioServiceStreamBase::getDescription_l(AudioEndpointParcelable* parcelable) {
737 {
738 std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
739 if (mUpMessageQueue == nullptr) {
740 ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
741 return AAUDIO_ERROR_NULL;
742 }
743 // Gather information on the message queue.
744 mUpMessageQueue->fillParcelable(parcelable,
745 parcelable->mUpMessageQueueParcelable);
746 }
747 return getAudioDataDescription_l(parcelable);
748 }
749
exitStandby(AudioEndpointParcelable * parcelable)750 aaudio_result_t AAudioServiceStreamBase::exitStandby(AudioEndpointParcelable *parcelable) {
751 auto command = std::make_shared<AAudioCommand>(
752 EXIT_STANDBY,
753 std::make_shared<ExitStandbyParam>(parcelable),
754 true /*waitForReply*/,
755 TIMEOUT_NANOS);
756 return mCommandQueue.sendCommand(command);
757 }
758
sendStartClientCommand(const android::AudioClient & client,const audio_attributes_t * attr,audio_port_handle_t * clientHandle)759 aaudio_result_t AAudioServiceStreamBase::sendStartClientCommand(const android::AudioClient &client,
760 const audio_attributes_t *attr,
761 audio_port_handle_t *clientHandle) {
762 auto command = std::make_shared<AAudioCommand>(
763 START_CLIENT,
764 std::make_shared<StartClientParam>(client, attr, clientHandle),
765 true /*waitForReply*/,
766 TIMEOUT_NANOS);
767 return mCommandQueue.sendCommand(command);
768 }
769
sendStopClientCommand(audio_port_handle_t clientHandle)770 aaudio_result_t AAudioServiceStreamBase::sendStopClientCommand(audio_port_handle_t clientHandle) {
771 auto command = std::make_shared<AAudioCommand>(
772 STOP_CLIENT,
773 std::make_shared<StopClientParam>(clientHandle),
774 true /*waitForReply*/,
775 TIMEOUT_NANOS);
776 return mCommandQueue.sendCommand(command);
777 }
778
onVolumeChanged(float volume)779 void AAudioServiceStreamBase::onVolumeChanged(float volume) {
780 sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume);
781 }
782
sendCommand(aaudio_command_opcode opCode,std::shared_ptr<AAudioCommandParam> param,bool waitForReply,int64_t timeoutNanos)783 aaudio_result_t AAudioServiceStreamBase::sendCommand(aaudio_command_opcode opCode,
784 std::shared_ptr<AAudioCommandParam> param,
785 bool waitForReply,
786 int64_t timeoutNanos) {
787 return mCommandQueue.sendCommand(std::make_shared<AAudioCommand>(
788 opCode, param, waitForReply, timeoutNanos));
789 }
790
closeAndClear()791 aaudio_result_t AAudioServiceStreamBase::closeAndClear() {
792 aaudio_result_t result = AAUDIO_OK;
793 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
794 if (endpoint == nullptr) {
795 result = AAUDIO_ERROR_INVALID_STATE;
796 } else {
797 endpoint->unregisterStream(this);
798 AAudioEndpointManager &endpointManager = AAudioEndpointManager::getInstance();
799 endpointManager.closeEndpoint(endpoint);
800
801 // AAudioService::closeStream() prevents two threads from closing at the same time.
802 mServiceEndpoint.clear(); // endpoint will hold the pointer after this method returns.
803 }
804
805 setState(AAUDIO_STREAM_STATE_CLOSED);
806
807 mediametrics::LogItem(mMetricsId)
808 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CLOSE)
809 .record();
810 return result;
811 }
812
stopCommandThread()813 void AAudioServiceStreamBase::stopCommandThread() {
814 bool threadEnabled = true;
815 if (mThreadEnabled.compare_exchange_strong(threadEnabled, false)) {
816 mCommandQueue.stopWaiting();
817 mCommandThread.stop();
818 }
819 }
820