1e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar/*
2e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * Copyright 2017 The Android Open Source Project
3e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar *
4e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * you may not use this file except in compliance with the License.
6e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * You may obtain a copy of the License at
7e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar *
8e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar *
10e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * Unless required by applicable law or agreed to in writing, software
11e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * See the License for the specific language governing permissions and
14e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar * limitations under the License.
15e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar */
16e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
17e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar#define LOG_TAG "AudioStreamLegacy"
181e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas//#define LOG_NDEBUG 0
191e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas#include <utils/Log.h>
201e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas
211e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas#include <stdint.h>
221e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas#include <utils/String16.h>
231e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas#include <media/AudioTrack.h>
241e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas#include <aaudio/AAudio.h>
251e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas
261e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas#include "core/AudioStream.h"
271e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas#include "legacy/AudioStreamLegacy.h"
28e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
29e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyarusing namespace android;
30e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyarusing namespace aaudio;
31e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
32e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit BoyarAudioStreamLegacy::AudioStreamLegacy()
33e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        : AudioStream(), mDeviceCallback(new StreamDeviceCallback(this)) {
34e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
35c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette
36e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit BoyarAudioStreamLegacy::~AudioStreamLegacy() {
37e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
38e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
39e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar// Called from AudioTrack.cpp or AudioRecord.cpp
40e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyarstatic void AudioStreamLegacy_callback(int event, void* userData, void *info) {
41e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    AudioStreamLegacy *streamLegacy = (AudioStreamLegacy *) userData;
42e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    streamLegacy->processCallback(event, info);
43e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
44e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
45e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyaraaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
46e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    return AudioStreamLegacy_callback;
47e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
48e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
49e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar// Implement FixedBlockProcessor
50e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyarint32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
51e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    int32_t frameCount = numBytes / getBytesPerFrame();
52e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    // Call using the AAudio callback interface.
53e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    AAudioStream_dataCallback appCallback = getDataCallbackProc();
54e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    return (*appCallback)(
55e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            (AAudioStream *) this,
56e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            getDataCallbackUserData(),
57e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            buffer,
58e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            frameCount);
59e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
60e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
61e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyarvoid AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
62e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    aaudio_data_callback_result_t callbackResult;
63e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
64e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    if (!mCallbackEnabled.load()) {
65e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        return;
66e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    }
67e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
68e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    switch (opcode) {
69e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
70e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
71e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                // Note that this code assumes an AudioTrack::Buffer is the same as
72e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                // AudioRecord::Buffer
7313a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                // TODO define our own AudioBuffer and pass it from the subclasses.
7413a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
7513a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                if (audioBuffer->frameCount == 0) return;
7613a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar
7713a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                // If the caller specified an exact size then use a block size adapter.
78e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                if (mBlockAdapter != nullptr) {
79e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                    int32_t byteCount = audioBuffer->frameCount * getBytesPerFrame();
8013a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                    callbackResult = mBlockAdapter->processVariableBlock(
81e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                            (uint8_t *) audioBuffer->raw, byteCount);
82e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                } else {
83e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                    // Call using the AAudio callback interface.
84e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                    callbackResult = (*getDataCallbackProc())(
85e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                            (AAudioStream *) this,
8613a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                            getDataCallbackUserData(),
8713a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                            audioBuffer->raw,
8813a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                            audioBuffer->frameCount
8913a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                            );
9013a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                }
9113a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
9213a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                    audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
9313a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                    incrementClientFrameCounter(audioBuffer->frameCount);
9413a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                } else {
9513a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                    audioBuffer->size = 0;
9613a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                }
9713a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                break;
9813a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar            }
9913a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar        }
10013a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar        /// FALL THROUGH
101e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
102e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            // Stream got rerouted so we disconnect.
103e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        case AAUDIO_CALLBACK_OPERATION_DISCONNECTED: {
104e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            setState(AAUDIO_STREAM_STATE_DISCONNECTED);
105e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            ALOGD("processCallbackCommon() stream disconnected");
10613a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar            if (getErrorCallbackProc() != nullptr) {
10713a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                (*getErrorCallbackProc())(
10813a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                        (AAudioStream *) this,
10913a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                        getErrorCallbackUserData(),
11013a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                        AAUDIO_ERROR_DISCONNECTED
11113a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar                        );
11213a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar            }
11313a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar            mCallbackEnabled.store(false);
11413a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar        }
11513a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar            break;
11613a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar
11713a0acc0df34344c0b4fd4b494a64e7dcf195b56Yigit Boyar        default:
118e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            break;
119e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    }
120e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
121e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
122e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyaraaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
123e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                                                   int64_t *framePosition,
124e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                                                   int64_t *timeNanoseconds,
125e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                                                   ExtendedTimestamp *extendedTimestamp) {
126e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    int timebase;
127e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    switch (clockId) {
128e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        case CLOCK_BOOTTIME:
129e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
130e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            break;
131e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        case CLOCK_MONOTONIC:
132e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
133e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            break;
134e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        default:
135e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
136e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
137e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            break;
138e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    }
139e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
140e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    return AAudioConvert_androidToAAudioResult(status);
141e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
142e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar
143e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyarvoid AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
144e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar{
145e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
146e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
147e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
148e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
149e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        // if we have a data callback and the stream is active, send the error callback from
150e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        // data callback thread when it sees the DISCONNECTED state
151e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        if (!isDataCallbackActive() && getErrorCallbackProc() != nullptr) {
152e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            (*getErrorCallbackProc())(
153e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                    (AAudioStream *) this,
154e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                    getErrorCallbackUserData(),
155e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                    AAUDIO_ERROR_DISCONNECTED
156e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar                    );
157e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        }
158e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    }
159e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    setDeviceId(deviceId);
160e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar}
161e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar