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