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