AudioStreamInternal.cpp revision 3316d5e6d375a4f09c681205e9094d30a0bfc4a2
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 "AAudio"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include <stdint.h>
22#include <assert.h>
23
24#include <binder/IServiceManager.h>
25#include <utils/Mutex.h>
26
27#include <aaudio/AAudio.h>
28
29#include "AudioClock.h"
30#include "AudioEndpointParcelable.h"
31#include "binding/AAudioStreamRequest.h"
32#include "binding/AAudioStreamConfiguration.h"
33#include "binding/IAAudioService.h"
34#include "binding/AAudioServiceMessage.h"
35
36#include "core/AudioStreamBuilder.h"
37#include "AudioStreamInternal.h"
38
39#define LOG_TIMESTAMPS   0
40
41using android::String16;
42using android::IServiceManager;
43using android::defaultServiceManager;
44using android::interface_cast;
45using android::Mutex;
46
47using namespace aaudio;
48
49static android::Mutex gServiceLock;
50static sp<IAAudioService>  gAAudioService;
51
52#define AAUDIO_SERVICE_NAME   "AAudioService"
53
54// Helper function to get access to the "AAudioService" service.
55// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp
56static const sp<IAAudioService> getAAudioService() {
57    sp<IBinder> binder;
58    Mutex::Autolock _l(gServiceLock);
59    if (gAAudioService == 0) {
60        sp<IServiceManager> sm = defaultServiceManager();
61        // Try several times to get the service.
62        int retries = 4;
63        do {
64            binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while.
65            if (binder != 0) {
66                break;
67            }
68        } while (retries-- > 0);
69
70        if (binder != 0) {
71            // TODO Add linkToDeath() like in frameworks/av/media/libaudioclient/AudioSystem.cpp
72            // TODO Create a DeathRecipient that disconnects all active streams.
73            gAAudioService = interface_cast<IAAudioService>(binder);
74        } else {
75            ALOGE("AudioStreamInternal could not get %s", AAUDIO_SERVICE_NAME);
76        }
77    }
78    return gAAudioService;
79}
80
81AudioStreamInternal::AudioStreamInternal()
82        : AudioStream()
83        , mClockModel()
84        , mAudioEndpoint()
85        , mServiceStreamHandle(AAUDIO_HANDLE_INVALID)
86        , mFramesPerBurst(16)
87{
88}
89
90AudioStreamInternal::~AudioStreamInternal() {
91}
92
93aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
94
95    const sp<IAAudioService>& service = getAAudioService();
96    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
97
98    aaudio_result_t result = AAUDIO_OK;
99    AAudioStreamRequest request;
100    AAudioStreamConfiguration configuration;
101
102    result = AudioStream::open(builder);
103    if (result < 0) {
104        return result;
105    }
106
107    // Build the request to send to the server.
108    request.setUserId(getuid());
109    request.setProcessId(getpid());
110    request.getConfiguration().setDeviceId(getDeviceId());
111    request.getConfiguration().setSampleRate(getSampleRate());
112    request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame());
113    request.getConfiguration().setAudioFormat(getFormat());
114    request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
115    request.dump();
116
117    mServiceStreamHandle = service->openStream(request, configuration);
118    ALOGD("AudioStreamInternal.open(): openStream returned mServiceStreamHandle = 0x%08X",
119         (unsigned int)mServiceStreamHandle);
120    if (mServiceStreamHandle < 0) {
121        result = mServiceStreamHandle;
122        ALOGE("AudioStreamInternal.open(): acquireRealtimeStream aaudio_result_t = 0x%08X", result);
123    } else {
124        result = configuration.validate();
125        if (result != AAUDIO_OK) {
126            close();
127            return result;
128        }
129        // Save results of the open.
130        setSampleRate(configuration.getSampleRate());
131        setSamplesPerFrame(configuration.getSamplesPerFrame());
132        setFormat(configuration.getAudioFormat());
133
134        aaudio::AudioEndpointParcelable parcelable;
135        result = service->getStreamDescription(mServiceStreamHandle, parcelable);
136        if (result != AAUDIO_OK) {
137            ALOGE("AudioStreamInternal.open(): getStreamDescriptor returns %d", result);
138            service->closeStream(mServiceStreamHandle);
139            return result;
140        }
141        // resolve parcelable into a descriptor
142        parcelable.resolve(&mEndpointDescriptor);
143
144        // Configure endpoint based on descriptor.
145        mAudioEndpoint.configure(&mEndpointDescriptor);
146
147        mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
148        assert(mFramesPerBurst >= 16);
149        assert(mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames < 10 * 1024);
150
151        mClockModel.setSampleRate(getSampleRate());
152        mClockModel.setFramesPerBurst(mFramesPerBurst);
153
154        setState(AAUDIO_STREAM_STATE_OPEN);
155    }
156    return result;
157}
158
159aaudio_result_t AudioStreamInternal::close() {
160    ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", mServiceStreamHandle);
161    if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
162        aaudio_handle_t serviceStreamHandle = mServiceStreamHandle;
163        mServiceStreamHandle = AAUDIO_HANDLE_INVALID;
164        const sp<IAAudioService>& aaudioService = getAAudioService();
165        if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
166        aaudioService->closeStream(serviceStreamHandle);
167        return AAUDIO_OK;
168    } else {
169        return AAUDIO_ERROR_INVALID_HANDLE;
170    }
171}
172
173aaudio_result_t AudioStreamInternal::requestStart()
174{
175    int64_t startTime;
176    ALOGD("AudioStreamInternal(): start()");
177    if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
178        return AAUDIO_ERROR_INVALID_STATE;
179    }
180    const sp<IAAudioService>& aaudioService = getAAudioService();
181    if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
182    startTime = AudioClock::getNanoseconds();
183    mClockModel.start(startTime);
184    processTimestamp(0, startTime);
185    setState(AAUDIO_STREAM_STATE_STARTING);
186    return aaudioService->startStream(mServiceStreamHandle);
187}
188
189aaudio_result_t AudioStreamInternal::requestPause()
190{
191    ALOGD("AudioStreamInternal(): pause()");
192    if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
193        return AAUDIO_ERROR_INVALID_STATE;
194    }
195    const sp<IAAudioService>& aaudioService = getAAudioService();
196    if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
197    mClockModel.stop(AudioClock::getNanoseconds());
198    setState(AAUDIO_STREAM_STATE_PAUSING);
199    return aaudioService->pauseStream(mServiceStreamHandle);
200}
201
202aaudio_result_t AudioStreamInternal::requestFlush() {
203    ALOGD("AudioStreamInternal(): flush()");
204    if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
205        return AAUDIO_ERROR_INVALID_STATE;
206    }
207    const sp<IAAudioService>& aaudioService = getAAudioService();
208    if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
209setState(AAUDIO_STREAM_STATE_FLUSHING);
210    return aaudioService->flushStream(mServiceStreamHandle);
211}
212
213void AudioStreamInternal::onFlushFromServer() {
214    ALOGD("AudioStreamInternal(): onFlushFromServer()");
215    int64_t readCounter = mAudioEndpoint.getDownDataReadCounter();
216    int64_t writeCounter = mAudioEndpoint.getDownDataWriteCounter();
217    // Bump offset so caller does not see the retrograde motion in getFramesRead().
218    int64_t framesFlushed = writeCounter - readCounter;
219    mFramesOffsetFromService += framesFlushed;
220    // Flush written frames by forcing writeCounter to readCounter.
221    // This is because we cannot move the read counter in the hardware.
222    mAudioEndpoint.setDownDataWriteCounter(readCounter);
223}
224
225aaudio_result_t AudioStreamInternal::requestStop()
226{
227    // TODO better implementation of requestStop()
228    aaudio_result_t result = requestPause();
229    if (result == AAUDIO_OK) {
230        aaudio_stream_state_t state;
231        result = waitForStateChange(AAUDIO_STREAM_STATE_PAUSING,
232                                    &state,
233                                    500 * AAUDIO_NANOS_PER_MILLISECOND);// TODO temporary code
234        if (result == AAUDIO_OK) {
235            result = requestFlush();
236        }
237    }
238    return result;
239}
240
241aaudio_result_t AudioStreamInternal::registerThread() {
242    ALOGD("AudioStreamInternal(): registerThread()");
243    if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
244        return AAUDIO_ERROR_INVALID_STATE;
245    }
246    const sp<IAAudioService>& aaudioService = getAAudioService();
247    if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
248    return aaudioService->registerAudioThread(mServiceStreamHandle,
249                                         gettid(),
250                                         getPeriodNanoseconds());
251}
252
253aaudio_result_t AudioStreamInternal::unregisterThread() {
254    ALOGD("AudioStreamInternal(): unregisterThread()");
255    if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
256        return AAUDIO_ERROR_INVALID_STATE;
257    }
258    const sp<IAAudioService>& aaudioService = getAAudioService();
259    if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
260    return aaudioService->unregisterAudioThread(mServiceStreamHandle, gettid());
261}
262
263// TODO use aaudio_clockid_t all the way down to AudioClock
264aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
265                           int64_t *framePosition,
266                           int64_t *timeNanoseconds) {
267// TODO implement using real HAL
268    int64_t time = AudioClock::getNanoseconds();
269    *framePosition = mClockModel.convertTimeToPosition(time);
270    *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay
271    return AAUDIO_OK;
272}
273
274aaudio_result_t AudioStreamInternal::updateState() {
275    return processCommands();
276}
277
278#if LOG_TIMESTAMPS
279static void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) {
280    static int64_t oldPosition = 0;
281    static int64_t oldTime = 0;
282    int64_t framePosition = command.timestamp.position;
283    int64_t nanoTime = command.timestamp.timestamp;
284    ALOGD("AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu",
285         (long long) framePosition,
286         (long long) nanoTime);
287    int64_t nanosDelta = nanoTime - oldTime;
288    if (nanosDelta > 0 && oldTime > 0) {
289        int64_t framesDelta = framePosition - oldPosition;
290        int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta;
291        ALOGD("AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta);
292        ALOGD("AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta);
293        ALOGD("AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate);
294    }
295    oldPosition = framePosition;
296    oldTime = nanoTime;
297}
298#endif
299
300aaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) {
301    int64_t framePosition = 0;
302#if LOG_TIMESTAMPS
303    AudioStreamInternal_LogTimestamp(command);
304#endif
305    framePosition = message->timestamp.position;
306    processTimestamp(framePosition, message->timestamp.timestamp);
307    return AAUDIO_OK;
308}
309
310aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) {
311    aaudio_result_t result = AAUDIO_OK;
312    ALOGD("processCommands() got event %d", message->event.event);
313    switch (message->event.event) {
314        case AAUDIO_SERVICE_EVENT_STARTED:
315            ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_STARTED");
316            setState(AAUDIO_STREAM_STATE_STARTED);
317            break;
318        case AAUDIO_SERVICE_EVENT_PAUSED:
319            ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_PAUSED");
320            setState(AAUDIO_STREAM_STATE_PAUSED);
321            break;
322        case AAUDIO_SERVICE_EVENT_FLUSHED:
323            ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED");
324            setState(AAUDIO_STREAM_STATE_FLUSHED);
325            onFlushFromServer();
326            break;
327        case AAUDIO_SERVICE_EVENT_CLOSED:
328            ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_CLOSED");
329            setState(AAUDIO_STREAM_STATE_CLOSED);
330            break;
331        case AAUDIO_SERVICE_EVENT_DISCONNECTED:
332            result = AAUDIO_ERROR_DISCONNECTED;
333            ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED");
334            break;
335        default:
336            ALOGW("WARNING - processCommands() Unrecognized event = %d",
337                 (int) message->event.event);
338            break;
339    }
340    return result;
341}
342
343// Process all the commands coming from the server.
344aaudio_result_t AudioStreamInternal::processCommands() {
345    aaudio_result_t result = AAUDIO_OK;
346
347    while (result == AAUDIO_OK) {
348        AAudioServiceMessage message;
349        if (mAudioEndpoint.readUpCommand(&message) != 1) {
350            break; // no command this time, no problem
351        }
352        switch (message.what) {
353        case AAudioServiceMessage::code::TIMESTAMP:
354            result = onTimestampFromServer(&message);
355            break;
356
357        case AAudioServiceMessage::code::EVENT:
358            result = onEventFromServer(&message);
359            break;
360
361        default:
362            ALOGW("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d",
363                 (int) message.what);
364            result = AAUDIO_ERROR_UNEXPECTED_VALUE;
365            break;
366        }
367    }
368    return result;
369}
370
371// Write the data, block if needed and timeoutMillis > 0
372aaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames,
373                                         int64_t timeoutNanoseconds)
374{
375    aaudio_result_t result = AAUDIO_OK;
376    uint8_t* source = (uint8_t*)buffer;
377    int64_t currentTimeNanos = AudioClock::getNanoseconds();
378    int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds;
379    int32_t framesLeft = numFrames;
380//    ALOGD("AudioStreamInternal::write(%p, %d) at time %08llu , mState = %d ------------------",
381//         buffer, numFrames, (unsigned long long) currentTimeNanos, mState);
382
383    // Write until all the data has been written or until a timeout occurs.
384    while (framesLeft > 0) {
385        // The call to writeNow() will not block. It will just write as much as it can.
386        int64_t wakeTimeNanos = 0;
387        aaudio_result_t framesWritten = writeNow(source, framesLeft,
388                                               currentTimeNanos, &wakeTimeNanos);
389//        ALOGD("AudioStreamInternal::write() writeNow() framesLeft = %d --> framesWritten = %d", framesLeft, framesWritten);
390        if (framesWritten < 0) {
391            result = framesWritten;
392            break;
393        }
394        framesLeft -= (int32_t) framesWritten;
395        source += framesWritten * getBytesPerFrame();
396
397        // Should we block?
398        if (timeoutNanoseconds == 0) {
399            break; // don't block
400        } else if (framesLeft > 0) {
401            //ALOGD("AudioStreamInternal:: original wakeTimeNanos %lld", (long long) wakeTimeNanos);
402            // clip the wake time to something reasonable
403            if (wakeTimeNanos < currentTimeNanos) {
404                wakeTimeNanos = currentTimeNanos;
405            }
406            if (wakeTimeNanos > deadlineNanos) {
407                // If we time out, just return the framesWritten so far.
408                ALOGE("AudioStreamInternal::write(): timed out after %lld nanos", (long long) timeoutNanoseconds);
409                break;
410            }
411
412            //ALOGD("AudioStreamInternal:: sleep until %lld, dur = %lld", (long long) wakeTimeNanos,
413            //        (long long) (wakeTimeNanos - currentTimeNanos));
414            AudioClock::sleepForNanos(wakeTimeNanos - currentTimeNanos);
415            currentTimeNanos = AudioClock::getNanoseconds();
416        }
417    }
418
419    // return error or framesWritten
420    return (result < 0) ? result : numFrames - framesLeft;
421}
422
423// Write as much data as we can without blocking.
424aaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames,
425                                         int64_t currentNanoTime, int64_t *wakeTimePtr) {
426    {
427        aaudio_result_t result = processCommands();
428        if (result != AAUDIO_OK) {
429            return result;
430        }
431    }
432
433    if (mAudioEndpoint.isOutputFreeRunning()) {
434        // Update data queue based on the timing model.
435        int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime);
436        mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter);
437        // If the read index passed the write index then consider it an underrun.
438        if (mAudioEndpoint.getFullFramesAvailable() < 0) {
439            mXRunCount++;
440        }
441    }
442    // TODO else query from endpoint cuz set by actual reader, maybe
443
444    // Write some data to the buffer.
445    int32_t framesWritten = mAudioEndpoint.writeDataNow(buffer, numFrames);
446    if (framesWritten > 0) {
447        incrementFramesWritten(framesWritten);
448    }
449    //ALOGD("AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d",
450    //    numFrames, framesWritten);
451
452    // Calculate an ideal time to wake up.
453    if (wakeTimePtr != nullptr && framesWritten >= 0) {
454        // By default wake up a few milliseconds from now.  // TODO review
455        int64_t wakeTime = currentNanoTime + (2 * AAUDIO_NANOS_PER_MILLISECOND);
456        switch (getState()) {
457            case AAUDIO_STREAM_STATE_OPEN:
458            case AAUDIO_STREAM_STATE_STARTING:
459                if (framesWritten != 0) {
460                    // Don't wait to write more data. Just prime the buffer.
461                    wakeTime = currentNanoTime;
462                }
463                break;
464            case AAUDIO_STREAM_STATE_STARTED:   // When do we expect the next read burst to occur?
465                {
466                    uint32_t burstSize = mFramesPerBurst;
467                    if (burstSize < 32) {
468                        burstSize = 32; // TODO review
469                    }
470
471                    uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize;
472                    wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
473                }
474                break;
475            default:
476                break;
477        }
478        *wakeTimePtr = wakeTime;
479
480    }
481//    ALOGD("AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu",
482//         (unsigned long long)currentNanoTime,
483//         (unsigned long long)mAudioEndpoint.getDownDataReadCounter(),
484//         (unsigned long long)mAudioEndpoint.getDownDataWriteCounter());
485    return framesWritten;
486}
487
488aaudio_result_t AudioStreamInternal::waitForStateChange(aaudio_stream_state_t currentState,
489                                                      aaudio_stream_state_t *nextState,
490                                                      int64_t timeoutNanoseconds)
491
492{
493    aaudio_result_t result = processCommands();
494//    ALOGD("AudioStreamInternal::waitForStateChange() - processCommands() returned %d", result);
495    if (result != AAUDIO_OK) {
496        return result;
497    }
498    // TODO replace this polling with a timed sleep on a futex on the message queue
499    int32_t durationNanos = 5 * AAUDIO_NANOS_PER_MILLISECOND;
500    aaudio_stream_state_t state = getState();
501//    ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state);
502    while (state == currentState && timeoutNanoseconds > 0) {
503        // TODO use futex from service message queue
504        if (durationNanos > timeoutNanoseconds) {
505            durationNanos = timeoutNanoseconds;
506        }
507        AudioClock::sleepForNanos(durationNanos);
508        timeoutNanoseconds -= durationNanos;
509
510        result = processCommands();
511        if (result != AAUDIO_OK) {
512            return result;
513        }
514
515        state = getState();
516//        ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state);
517    }
518    if (nextState != nullptr) {
519        *nextState = state;
520    }
521    return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK;
522}
523
524
525void AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) {
526    mClockModel.processTimestamp( position, time);
527}
528
529aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) {
530    int32_t actualFrames = 0;
531    aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames);
532    if (result < 0) {
533        return result;
534    } else {
535        return (aaudio_result_t) actualFrames;
536    }
537}
538
539int32_t AudioStreamInternal::getBufferSize() const
540{
541    return mAudioEndpoint.getBufferSizeInFrames();
542}
543
544int32_t AudioStreamInternal::getBufferCapacity() const
545{
546    return mAudioEndpoint.getBufferCapacityInFrames();
547}
548
549int32_t AudioStreamInternal::getFramesPerBurst() const
550{
551    return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
552}
553
554int64_t AudioStreamInternal::getFramesRead()
555{
556    int64_t framesRead =
557            mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
558            + mFramesOffsetFromService;
559    // Prevent retrograde motion.
560    if (framesRead < mLastFramesRead) {
561        framesRead = mLastFramesRead;
562    } else {
563        mLastFramesRead = framesRead;
564    }
565    ALOGD("AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead);
566    return framesRead;
567}
568
569// TODO implement getTimestamp
570