• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <media/MediaMetricsItem.h>
26 #include <media/TypeConverter.h>
27 #include <mediautils/SchedulingPolicyService.h>
28 
29 #include "binding/AAudioServiceMessage.h"
30 #include "core/AudioGlobal.h"
31 #include "utility/AudioClock.h"
32 
33 #include "AAudioEndpointManager.h"
34 #include "AAudioService.h"
35 #include "AAudioServiceEndpoint.h"
36 #include "AAudioServiceStreamBase.h"
37 #include "TimestampScheduler.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 /**
45  * Base class for streams in the service.
46  * @return
47  */
48 
AAudioServiceStreamBase(AAudioService & audioService)49 AAudioServiceStreamBase::AAudioServiceStreamBase(AAudioService &audioService)
50         : mTimestampThread("AATime")
51         , mAtomicStreamTimestamp()
52         , mAudioService(audioService) {
53     mMmapClient.attributionSource = AttributionSourceState();
54 }
55 
~AAudioServiceStreamBase()56 AAudioServiceStreamBase::~AAudioServiceStreamBase() {
57     ALOGD("%s() called", __func__);
58 
59     // May not be set if open failed.
60     if (mMetricsId.size() > 0) {
61         mediametrics::LogItem(mMetricsId)
62                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
63                 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
64                 .record();
65     }
66 
67     // If the stream is deleted when OPEN or in use then audio resources will leak.
68     // This would indicate an internal error. So we want to find this ASAP.
69     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
70                         || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED),
71                         "service stream %p still open, state = %d",
72                         this, getState());
73 }
74 
dumpHeader()75 std::string AAudioServiceStreamBase::dumpHeader() {
76     return std::string("    T   Handle   UId   Port Run State Format Burst Chan Capacity");
77 }
78 
dump() const79 std::string AAudioServiceStreamBase::dump() const {
80     std::stringstream result;
81 
82     result << "    0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
83            << std::dec << std::setfill(' ') ;
84     result << std::setw(6) << mMmapClient.attributionSource.uid;
85     result << std::setw(7) << mClientHandle;
86     result << std::setw(4) << (isRunning() ? "yes" : " no");
87     result << std::setw(6) << getState();
88     result << std::setw(7) << getFormat();
89     result << std::setw(6) << mFramesPerBurst;
90     result << std::setw(5) << getSamplesPerFrame();
91     result << std::setw(9) << getBufferCapacity();
92 
93     return result.str();
94 }
95 
logOpen(aaudio_handle_t streamHandle)96 void AAudioServiceStreamBase::logOpen(aaudio_handle_t streamHandle) {
97     // This is the first log sent from the AAudio Service for a stream.
98     mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM)
99             + std::to_string(streamHandle);
100 
101     audio_attributes_t attributes = AAudioServiceEndpoint::getAudioAttributesFrom(this);
102 
103     // Once this item is logged by the server, the client with the same PID, UID
104     // can also log properties.
105     mediametrics::LogItem(mMetricsId)
106         .setPid(getOwnerProcessId())
107         .setUid(getOwnerUserId())
108         .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)getOwnerUserId())
109         .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN)
110         // the following are immutable
111         .set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, (int32_t)getBufferCapacity())
112         .set(AMEDIAMETRICS_PROP_BURSTFRAMES, (int32_t)getFramesPerBurst())
113         .set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)getSamplesPerFrame())
114         .set(AMEDIAMETRICS_PROP_CONTENTTYPE, toString(attributes.content_type).c_str())
115         .set(AMEDIAMETRICS_PROP_DIRECTION,
116                 AudioGlobal_convertDirectionToText(getDirection()))
117         .set(AMEDIAMETRICS_PROP_ENCODING, toString(getFormat()).c_str())
118         .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEID, (int32_t)getDeviceId())
119         .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)getSampleRate())
120         .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)getSessionId())
121         .set(AMEDIAMETRICS_PROP_SOURCE, toString(attributes.source).c_str())
122         .set(AMEDIAMETRICS_PROP_USAGE, toString(attributes.usage).c_str())
123         .record();
124 }
125 
open(const aaudio::AAudioStreamRequest & request)126 aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request) {
127     AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
128     aaudio_result_t result = AAUDIO_OK;
129 
130     mMmapClient.attributionSource = request.getAttributionSource();
131     // TODO b/182392769: use attribution source util
132     mMmapClient.attributionSource.uid = VALUE_OR_FATAL(
133         legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
134     mMmapClient.attributionSource.pid = VALUE_OR_FATAL(
135         legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
136 
137     // Limit scope of lock to avoid recursive lock in close().
138     {
139         std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
140         if (mUpMessageQueue != nullptr) {
141             ALOGE("%s() called twice", __func__);
142             return AAUDIO_ERROR_INVALID_STATE;
143         }
144 
145         mUpMessageQueue = std::make_shared<SharedRingBuffer>();
146         result = mUpMessageQueue->allocate(sizeof(AAudioServiceMessage),
147                                            QUEUE_UP_CAPACITY_COMMANDS);
148         if (result != AAUDIO_OK) {
149             goto error;
150         }
151 
152         // This is not protected by a lock because the stream cannot be
153         // referenced until the service returns a handle to the client.
154         // So only one thread can open a stream.
155         mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService,
156                                                          request);
157         if (mServiceEndpoint == nullptr) {
158             result = AAUDIO_ERROR_UNAVAILABLE;
159             goto error;
160         }
161         // Save a weak pointer that we will use to access the endpoint.
162         mServiceEndpointWeak = mServiceEndpoint;
163 
164         mFramesPerBurst = mServiceEndpoint->getFramesPerBurst();
165         copyFrom(*mServiceEndpoint);
166     }
167     return result;
168 
169 error:
170     close();
171     return result;
172 }
173 
close()174 aaudio_result_t AAudioServiceStreamBase::close() {
175     std::lock_guard<std::mutex> lock(mLock);
176     return close_l();
177 }
178 
close_l()179 aaudio_result_t AAudioServiceStreamBase::close_l() {
180     if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
181         return AAUDIO_OK;
182     }
183 
184     // This will call stopTimestampThread() and also stop the stream,
185     // just in case it was not already stopped.
186     stop_l();
187 
188     aaudio_result_t result = AAUDIO_OK;
189     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
190     if (endpoint == nullptr) {
191         result = AAUDIO_ERROR_INVALID_STATE;
192     } else {
193         endpoint->unregisterStream(this);
194         AAudioEndpointManager &endpointManager = AAudioEndpointManager::getInstance();
195         endpointManager.closeEndpoint(endpoint);
196 
197         // AAudioService::closeStream() prevents two threads from closing at the same time.
198         mServiceEndpoint.clear(); // endpoint will hold the pointer after this method returns.
199     }
200 
201     setState(AAUDIO_STREAM_STATE_CLOSED);
202 
203     mediametrics::LogItem(mMetricsId)
204         .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CLOSE)
205         .record();
206     return result;
207 }
208 
startDevice()209 aaudio_result_t AAudioServiceStreamBase::startDevice() {
210     mClientHandle = AUDIO_PORT_HANDLE_NONE;
211     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
212     if (endpoint == nullptr) {
213         ALOGE("%s() has no endpoint", __func__);
214         return AAUDIO_ERROR_INVALID_STATE;
215     }
216     return endpoint->startStream(this, &mClientHandle);
217 }
218 
219 /**
220  * Start the flow of audio data.
221  *
222  * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
223  */
start()224 aaudio_result_t AAudioServiceStreamBase::start() {
225     std::lock_guard<std::mutex> lock(mLock);
226 
227     const int64_t beginNs = AudioClock::getNanoseconds();
228     aaudio_result_t result = AAUDIO_OK;
229 
230     if (auto state = getState();
231         state == AAUDIO_STREAM_STATE_CLOSED || isDisconnected_l()) {
232         ALOGW("%s() already CLOSED, returns INVALID_STATE, handle = %d",
233                 __func__, getHandle());
234         return AAUDIO_ERROR_INVALID_STATE;
235     }
236 
237     mediametrics::Defer defer([&] {
238         mediametrics::LogItem(mMetricsId)
239             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
240             .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
241             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
242             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
243             .record(); });
244 
245     if (isRunning()) {
246         return result;
247     }
248 
249     setFlowing(false);
250     setSuspended(false);
251 
252     // Start with fresh presentation timestamps.
253     mAtomicStreamTimestamp.clear();
254 
255     mClientHandle = AUDIO_PORT_HANDLE_NONE;
256     result = startDevice();
257     if (result != AAUDIO_OK) goto error;
258 
259     // This should happen at the end of the start.
260     sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
261     setState(AAUDIO_STREAM_STATE_STARTED);
262     mThreadEnabled.store(true);
263     // Make sure this object does not get deleted before the run() method
264     // can protect it by making a strong pointer.
265     incStrong(nullptr); // See run() method.
266     result = mTimestampThread.start(this);
267     if (result != AAUDIO_OK) {
268         decStrong(nullptr); // run() can't do it so we have to do it here.
269         goto error;
270     }
271 
272     return result;
273 
274 error:
275     disconnect_l();
276     return result;
277 }
278 
pause()279 aaudio_result_t AAudioServiceStreamBase::pause() {
280     std::lock_guard<std::mutex> lock(mLock);
281     return pause_l();
282 }
283 
pause_l()284 aaudio_result_t AAudioServiceStreamBase::pause_l() {
285     aaudio_result_t result = AAUDIO_OK;
286     if (!isRunning()) {
287         return result;
288     }
289     const int64_t beginNs = AudioClock::getNanoseconds();
290 
291     mediametrics::Defer defer([&] {
292         mediametrics::LogItem(mMetricsId)
293             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_PAUSE)
294             .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
295             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
296             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
297             .record(); });
298 
299     result = stopTimestampThread();
300     if (result != AAUDIO_OK) {
301         disconnect_l();
302         return result;
303     }
304 
305     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
306     if (endpoint == nullptr) {
307         ALOGE("%s() has no endpoint", __func__);
308         result =  AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking
309         return result;
310     }
311     result = endpoint->stopStream(this, mClientHandle);
312     if (result != AAUDIO_OK) {
313         ALOGE("%s() mServiceEndpoint returned %d, %s", __func__, result, getTypeText());
314         disconnect_l(); // TODO should we return or pause Base first?
315     }
316 
317     sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
318     setState(AAUDIO_STREAM_STATE_PAUSED);
319     return result;
320 }
321 
stop()322 aaudio_result_t AAudioServiceStreamBase::stop() {
323     std::lock_guard<std::mutex> lock(mLock);
324     return stop_l();
325 }
326 
stop_l()327 aaudio_result_t AAudioServiceStreamBase::stop_l() {
328     aaudio_result_t result = AAUDIO_OK;
329     if (!isRunning()) {
330         return result;
331     }
332     const int64_t beginNs = AudioClock::getNanoseconds();
333 
334     mediametrics::Defer defer([&] {
335         mediametrics::LogItem(mMetricsId)
336             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
337             .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
338             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
339             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
340             .record(); });
341 
342     setState(AAUDIO_STREAM_STATE_STOPPING);
343 
344     // Temporarily unlock because we are joining the timestamp thread and it may try
345     // to acquire mLock.
346     mLock.unlock();
347     result = stopTimestampThread();
348     mLock.lock();
349 
350     if (result != AAUDIO_OK) {
351         disconnect_l();
352         return result;
353     }
354 
355     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
356     if (endpoint == nullptr) {
357         ALOGE("%s() has no endpoint", __func__);
358         result =  AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking
359         return result;
360     }
361     // TODO wait for data to be played out
362     result = endpoint->stopStream(this, mClientHandle);
363     if (result != AAUDIO_OK) {
364         ALOGE("%s() stopStream returned %d, %s", __func__, result, getTypeText());
365         disconnect_l();
366         // TODO what to do with result here?
367     }
368 
369     sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
370     setState(AAUDIO_STREAM_STATE_STOPPED);
371     return result;
372 }
373 
stopTimestampThread()374 aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() {
375     aaudio_result_t result = AAUDIO_OK;
376     // clear flag that tells thread to loop
377     if (mThreadEnabled.exchange(false)) {
378         result = mTimestampThread.stop();
379     }
380     return result;
381 }
382 
flush()383 aaudio_result_t AAudioServiceStreamBase::flush() {
384     std::lock_guard<std::mutex> lock(mLock);
385     aaudio_result_t result = AAudio_isFlushAllowed(getState());
386     if (result != AAUDIO_OK) {
387         return result;
388     }
389     const int64_t beginNs = AudioClock::getNanoseconds();
390 
391     mediametrics::Defer defer([&] {
392         mediametrics::LogItem(mMetricsId)
393             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH)
394             .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
395             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
396             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
397             .record(); });
398 
399     // Data will get flushed when the client receives the FLUSHED event.
400     sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
401     setState(AAUDIO_STREAM_STATE_FLUSHED);
402     return AAUDIO_OK;
403 }
404 
405 // implement Runnable, periodically send timestamps to client
406 __attribute__((no_sanitize("integer")))
run()407 void AAudioServiceStreamBase::run() {
408     ALOGD("%s() %s entering >>>>>>>>>>>>>> TIMESTAMPS", __func__, getTypeText());
409     // Hold onto the ref counted stream until the end.
410     android::sp<AAudioServiceStreamBase> holdStream(this);
411     TimestampScheduler timestampScheduler;
412     // Balance the incStrong from when the thread was launched.
413     holdStream->decStrong(nullptr);
414 
415     timestampScheduler.setBurstPeriod(mFramesPerBurst, getSampleRate());
416     timestampScheduler.start(AudioClock::getNanoseconds());
417     int64_t nextTime = timestampScheduler.nextAbsoluteTime();
418     int32_t loopCount = 0;
419     aaudio_result_t result = AAUDIO_OK;
420     while(mThreadEnabled.load()) {
421         loopCount++;
422         if (AudioClock::getNanoseconds() >= nextTime) {
423             result = sendCurrentTimestamp();
424             if (result != AAUDIO_OK) {
425                 ALOGE("%s() timestamp thread got result = %d", __func__, result);
426                 break;
427             }
428             nextTime = timestampScheduler.nextAbsoluteTime();
429         } else  {
430             // Sleep until it is time to send the next timestamp.
431             // TODO Wait for a signal with a timeout so that we can stop more quickly.
432             AudioClock::sleepUntilNanoTime(nextTime);
433         }
434     }
435     // This was moved from the calls in stop_l() and pause_l(), which could cause a deadlock
436     // if it resulted in a call to disconnect.
437     if (result == AAUDIO_OK) {
438         (void) sendCurrentTimestamp();
439     }
440     ALOGD("%s() %s exiting after %d loops <<<<<<<<<<<<<< TIMESTAMPS",
441           __func__, getTypeText(), loopCount);
442 }
443 
disconnect()444 void AAudioServiceStreamBase::disconnect() {
445     std::lock_guard<std::mutex> lock(mLock);
446     disconnect_l();
447 }
448 
disconnect_l()449 void AAudioServiceStreamBase::disconnect_l() {
450     if (!isDisconnected_l() && getState() != AAUDIO_STREAM_STATE_CLOSED) {
451 
452         mediametrics::LogItem(mMetricsId)
453             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
454             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
455             .record();
456 
457         sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
458         setDisconnected_l(true);
459     }
460 }
461 
registerAudioThread(pid_t clientThreadId,int priority)462 aaudio_result_t AAudioServiceStreamBase::registerAudioThread(pid_t clientThreadId,
463         int priority) {
464     std::lock_guard<std::mutex> lock(mLock);
465     aaudio_result_t result = AAUDIO_OK;
466     if (getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
467         ALOGE("AAudioService::registerAudioThread(), thread already registered");
468         result = AAUDIO_ERROR_INVALID_STATE;
469     } else {
470         const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
471         setRegisteredThread(clientThreadId);
472         int err = android::requestPriority(ownerPid, clientThreadId,
473                                            priority, true /* isForApp */);
474         if (err != 0) {
475             ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
476                   clientThreadId, errno, priority);
477             result = AAUDIO_ERROR_INTERNAL;
478         }
479     }
480     return result;
481 }
482 
unregisterAudioThread(pid_t clientThreadId)483 aaudio_result_t AAudioServiceStreamBase::unregisterAudioThread(pid_t clientThreadId) {
484     std::lock_guard<std::mutex> lock(mLock);
485     aaudio_result_t result = AAUDIO_OK;
486     if (getRegisteredThread() != clientThreadId) {
487         ALOGE("%s(), wrong thread", __func__);
488         result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
489     } else {
490         setRegisteredThread(0);
491     }
492     return result;
493 }
494 
setState(aaudio_stream_state_t state)495 void AAudioServiceStreamBase::setState(aaudio_stream_state_t state) {
496     // CLOSED is a final state.
497     if (mState != AAUDIO_STREAM_STATE_CLOSED) {
498         mState = state;
499     } else {
500         ALOGW_IF(mState != state, "%s(%d) when already CLOSED", __func__, state);
501     }
502 }
503 
sendServiceEvent(aaudio_service_event_t event,double dataDouble)504 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
505                                                           double  dataDouble) {
506     AAudioServiceMessage command;
507     command.what = AAudioServiceMessage::code::EVENT;
508     command.event.event = event;
509     command.event.dataDouble = dataDouble;
510     return writeUpMessageQueue(&command);
511 }
512 
sendServiceEvent(aaudio_service_event_t event,int64_t dataLong)513 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
514                                                           int64_t dataLong) {
515     AAudioServiceMessage command;
516     command.what = AAudioServiceMessage::code::EVENT;
517     command.event.event = event;
518     command.event.dataLong = dataLong;
519     return writeUpMessageQueue(&command);
520 }
521 
isUpMessageQueueBusy()522 bool AAudioServiceStreamBase::isUpMessageQueueBusy() {
523     std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
524     if (mUpMessageQueue == nullptr) {
525         ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
526         return true;
527     }
528     // Is it half full or more
529     return mUpMessageQueue->getFractionalFullness() >= 0.5;
530 }
531 
writeUpMessageQueue(AAudioServiceMessage * command)532 aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
533     std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
534     if (mUpMessageQueue == nullptr) {
535         ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
536         return AAUDIO_ERROR_NULL;
537     }
538     int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
539     if (count != 1) {
540         ALOGW("%s(): Queue full. Did client stop? Suspending stream. what = %u, %s",
541               __func__, command->what, getTypeText());
542         setSuspended(true);
543         return AAUDIO_ERROR_WOULD_BLOCK;
544     } else {
545         return AAUDIO_OK;
546     }
547 }
548 
sendXRunCount(int32_t xRunCount)549 aaudio_result_t AAudioServiceStreamBase::sendXRunCount(int32_t xRunCount) {
550     return sendServiceEvent(AAUDIO_SERVICE_EVENT_XRUN, (int64_t) xRunCount);
551 }
552 
sendCurrentTimestamp()553 aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
554     AAudioServiceMessage command;
555     // It is not worth filling up the queue with timestamps.
556     // That can cause the stream to get suspended.
557     // So just drop the timestamp if the queue is getting full.
558     if (isUpMessageQueueBusy()) {
559         return AAUDIO_OK;
560     }
561 
562     // Send a timestamp for the clock model.
563     aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
564                                                     &command.timestamp.timestamp);
565     if (result == AAUDIO_OK) {
566         ALOGV("%s() SERVICE  %8lld at %lld", __func__,
567               (long long) command.timestamp.position,
568               (long long) command.timestamp.timestamp);
569         command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE;
570         result = writeUpMessageQueue(&command);
571 
572         if (result == AAUDIO_OK) {
573             // Send a hardware timestamp for presentation time.
574             result = getHardwareTimestamp(&command.timestamp.position,
575                                           &command.timestamp.timestamp);
576             if (result == AAUDIO_OK) {
577                 ALOGV("%s() HARDWARE %8lld at %lld", __func__,
578                       (long long) command.timestamp.position,
579                       (long long) command.timestamp.timestamp);
580                 command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE;
581                 result = writeUpMessageQueue(&command);
582             }
583         }
584     }
585 
586     if (result == AAUDIO_ERROR_UNAVAILABLE) { // TODO review best error code
587         result = AAUDIO_OK; // just not available yet, try again later
588     }
589     return result;
590 }
591 
592 /**
593  * Get an immutable description of the in-memory queues
594  * used to communicate with the underlying HAL or Service.
595  */
getDescription(AudioEndpointParcelable & parcelable)596 aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
597     std::lock_guard<std::mutex> lock(mLock);
598     {
599         std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
600         if (mUpMessageQueue == nullptr) {
601             ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
602             return AAUDIO_ERROR_NULL;
603         }
604         // Gather information on the message queue.
605         mUpMessageQueue->fillParcelable(parcelable,
606                                         parcelable.mUpMessageQueueParcelable);
607     }
608     return getAudioDataDescription(parcelable);
609 }
610 
onVolumeChanged(float volume)611 void AAudioServiceStreamBase::onVolumeChanged(float volume) {
612     sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume);
613 }
614