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