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