AudioStreamInternal.cpp revision e572f469de5dca1078a79d3d80e5b04f96ae7505
1204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk/* 2204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * Copyright (C) 2016 The Android Open Source Project 3204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * 4204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 5204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * you may not use this file except in compliance with the License. 6204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * You may obtain a copy of the License at 7204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * 8204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * http://www.apache.org/licenses/LICENSE-2.0 9204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * 10204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * Unless required by applicable law or agreed to in writing, software 11204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * distributed under the License is distributed on an "AS IS" BASIS, 12204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * See the License for the specific language governing permissions and 14204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk * limitations under the License. 15204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk */ 16204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#define LOG_TAG "AAudio" 18204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk//#define LOG_NDEBUG 0 19204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <utils/Log.h> 20204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 21c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <stdint.h> 22204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <assert.h> 23204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 24204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <binder/IServiceManager.h> 25204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h> 27e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <utils/String16.h> 28204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 29c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AudioClock.h" 30c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AudioEndpointParcelable.h" 31c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/AAudioStreamRequest.h" 32c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/AAudioStreamConfiguration.h" 33c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/IAAudioService.h" 345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include "binding/AAudioServiceMessage.h" 35e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#include "core/AudioStreamBuilder.h" 36c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "fifo/FifoBuffer.h" 37e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#include "utility/LinearRamp.h" 38204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 39c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AudioStreamInternal.h" 40204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 41204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#define LOG_TIMESTAMPS 0 42204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 43204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::String16; 44dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkusing android::Mutex; 45c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkusing android::WrappingBuffer; 46204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 48204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 49e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define MIN_TIMEOUT_NANOS (1000 * AAUDIO_NANOS_PER_MILLISECOND) 50e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 51e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Wait at least this many times longer than the operation should take. 52e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define MIN_TIMEOUT_OPERATIONS 4 53e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 5471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk//static int64_t s_logCounter = 0; 5571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk//#define MYLOG_CONDITION (mInService == true && s_logCounter++ < 500) 5671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk//#define MYLOG_CONDITION (s_logCounter++ < 500000) 5771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#define MYLOG_CONDITION (1) 58204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 59c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil BurkAudioStreamInternal::AudioStreamInternal(AAudioServiceInterface &serviceInterface, bool inService) 60204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk : AudioStream() 61204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mClockModel() 62204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mAudioEndpoint() 635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk , mServiceStreamHandle(AAUDIO_HANDLE_INVALID) 64204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mFramesPerBurst(16) 65c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk , mServiceInterface(serviceInterface) 6671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk , mInService(inService) { 67204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 68204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 69204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::~AudioStreamInternal() { 70204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 71204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { 73204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamRequest request; 765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamConfiguration configuration; 77204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 78204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = AudioStream::open(builder); 79204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result < 0) { 80204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 81204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 82204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 83c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // We have to do volume scaling. So we prefer FLOAT format. 84c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (getFormat() == AAUDIO_UNSPECIFIED) { 85c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk setFormat(AAUDIO_FORMAT_PCM_FLOAT); 86c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 8771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // Request FLOAT for the shared mixer. 8871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk request.getConfiguration().setAudioFormat(AAUDIO_FORMAT_PCM_FLOAT); 89c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 90dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // Build the request to send to the server. 91204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setUserId(getuid()); 92204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setProcessId(getpid()); 93c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk request.setDirection(getDirection()); 9471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk request.setSharingModeMatchRequired(isSharingModeMatchRequired()); 95c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 96204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setDeviceId(getDeviceId()); 97204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSampleRate(getSampleRate()); 98204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame()); 9971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk request.getConfiguration().setSharingMode(getSharingMode()); 10071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 1013df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk request.getConfiguration().setBufferCapacity(builder.getBufferCapacity()); 102204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 103c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceStreamHandle = mServiceInterface.openStream(request, configuration); 104204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle < 0) { 105204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = mServiceStreamHandle; 10671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal.open(): %s openStream() returned %d", getLocationName(), result); 107204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 108204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = configuration.validate(); 1095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 110204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk close(); 111204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 112204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 113204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Save results of the open. 114204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSampleRate(configuration.getSampleRate()); 115204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSamplesPerFrame(configuration.getSamplesPerFrame()); 116c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk setDeviceId(configuration.getDeviceId()); 117204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 118c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Save device format so we can do format conversion and volume scaling together. 119c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mDeviceFormat = configuration.getAudioFormat(); 120c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 121c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable); 1225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 12371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal.open(): %s getStreamDescriptor returns %d", 12471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk getLocationName(), result); 125c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 126204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 127204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 128c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 129204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // resolve parcelable into a descriptor 130c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk result = mEndPointParcelable.resolve(&mEndpointDescriptor); 131c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (result != AAUDIO_OK) { 132c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk ALOGE("AudioStreamInternal.open(): resolve() returns %d", result); 133c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 134c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return result; 135c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 136204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 137204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Configure endpoint based on descriptor. 138204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.configure(&mEndpointDescriptor); 139204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 140204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 14171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int32_t capacity = mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames; 14271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 14371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.open() %s framesPerBurst = %d, capacity = %d", 14471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk getLocationName(), mFramesPerBurst, capacity); 14571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // Validate result from server. 14671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) { 14771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStream::open(): framesPerBurst out of range = %d", mFramesPerBurst); 14871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 14971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 15071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (capacity < mFramesPerBurst || capacity > 32 * 1024) { 15171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStream::open(): bufferCapacity out of range = %d", capacity); 15271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 15371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 154204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 155204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setSampleRate(getSampleRate()); 156204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setFramesPerBurst(mFramesPerBurst); 157204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 158e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (getDataCallbackProc()) { 159e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackFrames = builder.getFramesPerDataCallback(); 160e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackFrames > getBufferCapacity() / 2) { 16171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal.open(): framesPerCallback too large = %d, capacity = %d", 16271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mCallbackFrames, getBufferCapacity()); 163c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 164e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 165e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 166e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else if (mCallbackFrames < 0) { 167e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk ALOGE("AudioStreamInternal.open(): framesPerCallback negative"); 168c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 169e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 170e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 171e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 172e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackFrames == AAUDIO_UNSPECIFIED) { 173e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackFrames = mFramesPerBurst; 174e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 175e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 176e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int32_t bytesPerFrame = getSamplesPerFrame() 177e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * AAudioConvert_formatToSizeInBytes(getFormat()); 178e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame; 179e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBuffer = new uint8_t[callbackBufferSize]; 180e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 181e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 1825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 183204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 184204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 185204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 186204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1875ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::close() { 18871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", 18971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 1905ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { 1915ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; 1925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk mServiceStreamHandle = AAUDIO_HANDLE_INVALID; 193c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 194c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(serviceStreamHandle); 195e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk delete[] mCallbackBuffer; 196c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mEndPointParcelable.close(); 197204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 1985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_HANDLE; 199204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 200204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 201204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 202c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 203e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Render audio in the application callback and then write the data to the stream. 204e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid *AudioStreamInternal::callbackLoop() { 205e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk aaudio_result_t result = AAUDIO_OK; 206e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE; 207e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AAudioStream_dataCallback appCallback = getDataCallbackProc(); 208e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (appCallback == nullptr) return NULL; 209e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 210677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // result might be a frame count 211677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk while (mCallbackEnabled.load() && isPlaying() && (result >= 0)) { 212e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Call application using the AAudio callback interface. 213e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackResult = (*appCallback)( 214e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk (AAudioStream *) this, 215e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk getDataCallbackUserData(), 216e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBuffer, 217e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackFrames); 218e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 219e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) { 220677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // Write audio data to stream. 221e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames); 222677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk 223677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // This is a BLOCKING WRITE! 224e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk result = write(mCallbackBuffer, mCallbackFrames, timeoutNanos); 225677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk if ((result != mCallbackFrames)) { 226677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk ALOGE("AudioStreamInternal(): callbackLoop: write() returned %d", result); 227677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk if (result >= 0) { 228677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // Only wrote some of the frames requested. Must have timed out. 229677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk result = AAUDIO_ERROR_TIMEOUT; 230677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk } 231e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (getErrorCallbackProc() != nullptr) { 232e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk (*getErrorCallbackProc())( 233e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk (AAudioStream *) this, 234e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk getErrorCallbackUserData(), 235677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk result); 236e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 237e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 238e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 239e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) { 240677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk ALOGD("AudioStreamInternal(): callback returned AAUDIO_CALLBACK_RESULT_STOP"); 241e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 242e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 243e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 244e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 245677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk ALOGD("AudioStreamInternal(): callbackLoop() exiting, result = %d, isPlaying() = %d", 246e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk result, (int) isPlaying()); 247e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return NULL; // TODO review 248e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 249e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 250e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkstatic void *aaudio_callback_thread_proc(void *context) 251e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{ 252e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioStreamInternal *stream = (AudioStreamInternal *)context; 253677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk //LOGD("AudioStreamInternal(): oboe_callback_thread, stream = %p", stream); 254e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (stream != NULL) { 255e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return stream->callbackLoop(); 256e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 257e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return NULL; 258e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 259e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 260e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 2615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStart() 262204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 2633316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t startTime; 26471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): start()"); 2655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2665ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 267204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 268c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 2693316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk startTime = AudioClock::getNanoseconds(); 270204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.start(startTime); 271204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(0, startTime); 2725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 273c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);; 274e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 275e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (result == AAUDIO_OK && getDataCallbackProc() != nullptr) { 276e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Launch the callback loop thread. 277e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int64_t periodNanos = mCallbackFrames 278e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * AAUDIO_NANOS_PER_SECOND 279e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk / getSampleRate(); 280e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackEnabled.store(true); 281e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk result = createThread(periodNanos, aaudio_callback_thread_proc, this); 282e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 283e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return result; 284204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 285204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 286e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkint64_t AudioStreamInternal::calculateReasonableTimeout(int32_t framesPerOperation) { 287e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 288e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Wait for at least a second or some number of callbacks to join the thread. 28971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int64_t timeoutNanoseconds = (MIN_TIMEOUT_OPERATIONS 29071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk * framesPerOperation 29171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk * AAUDIO_NANOS_PER_SECOND) 29271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk / getSampleRate(); 293e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (timeoutNanoseconds < MIN_TIMEOUT_NANOS) { // arbitrary number of seconds 294e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk timeoutNanoseconds = MIN_TIMEOUT_NANOS; 295e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 296e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return timeoutNanoseconds; 297e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 298e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 299e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::stopCallback() 300e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{ 301e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (isDataCallbackActive()) { 302e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackEnabled.store(false); 303e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return joinThread(NULL, calculateReasonableTimeout(mCallbackFrames)); 304e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 305e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_OK; 306e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 307e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 308e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 309e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::requestPauseInternal() 310204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 3115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 31271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal(): requestPauseInternal() mServiceStreamHandle invalid = 0x%08X", 31371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 3145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 315204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 316c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 3173316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk mClockModel.stop(AudioClock::getNanoseconds()); 3185ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSING); 31971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return mServiceInterface.pauseStream(mServiceStreamHandle); 320204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 321204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 322e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::requestPause() 323e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{ 32471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestPause()", getLocationName()); 325e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk aaudio_result_t result = stopCallback(); 326e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (result != AAUDIO_OK) { 327e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return result; 328e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 32971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk result = requestPauseInternal(); 33071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD("AudioStreamInternal(): requestPause() returns %d", result); 33171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return result; 332e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 333e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 3345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestFlush() { 33571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): requestFlush()"); 3365ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 33771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal(): requestFlush() mServiceStreamHandle invalid = 0x%08X", 33871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 3395ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 340204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 341c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 342e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk setState(AAUDIO_STREAM_STATE_FLUSHING); 343c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mServiceInterface.flushStream(mServiceStreamHandle); 344204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 345204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 346204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::onFlushFromServer() { 34771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): onFlushFromServer()"); 3483316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t readCounter = mAudioEndpoint.getDownDataReadCounter(); 3493316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t writeCounter = mAudioEndpoint.getDownDataWriteCounter(); 35071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 351204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Bump offset so caller does not see the retrograde motion in getFramesRead(). 3523316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framesFlushed = writeCounter - readCounter; 353204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesOffsetFromService += framesFlushed; 35471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 355204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Flush written frames by forcing writeCounter to readCounter. 356204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // This is because we cannot move the read counter in the hardware. 357204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataWriteCounter(readCounter); 358204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 359204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 36071f35bb687476694882a617ba4a810a0bb56fe23Phil Burkaaudio_result_t AudioStreamInternal::requestStopInternal() 36171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk{ 36271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 36371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal(): requestStopInternal() mServiceStreamHandle invalid = 0x%08X", 36471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 36571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return AAUDIO_ERROR_INVALID_STATE; 36671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 36771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 36871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mClockModel.stop(AudioClock::getNanoseconds()); 36971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk setState(AAUDIO_STREAM_STATE_STOPPING); 37071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return mServiceInterface.stopStream(mServiceStreamHandle); 37171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk} 37271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 3735ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStop() 374204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 37571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestStop()", getLocationName()); 37671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk aaudio_result_t result = stopCallback(); 37771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (result != AAUDIO_OK) { 37871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return result; 379204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 38071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk result = requestStopInternal(); 38171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD("AudioStreamInternal(): requestStop() returns %d", result); 382204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 383204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 384204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::registerThread() { 3865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 3875ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 388204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 389c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mServiceInterface.registerAudioThread(mServiceStreamHandle, 390c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk getpid(), 391c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk gettid(), 392c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk getPeriodNanoseconds()); 393204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 394204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::unregisterThread() { 3965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 3975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 398204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 399c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, getpid(), gettid()); 400204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 401204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId, 4033316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t *framePosition, 4043316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t *timeNanoseconds) { 405e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // TODO implement using real HAL 4063316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t time = AudioClock::getNanoseconds(); 407204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *framePosition = mClockModel.convertTimeToPosition(time); 4085ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay 4095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 410204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 411204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 412e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::updateStateWhileWaiting() { 413e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (isDataCallbackActive()) { 414e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_OK; // state is getting updated by the callback thread read/write call 415e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 416204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return processCommands(); 417204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 418204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 419204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 4205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) { 421204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static int64_t oldPosition = 0; 4223316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk static int64_t oldTime = 0; 423204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framePosition = command.timestamp.position; 4243316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t nanoTime = command.timestamp.timestamp; 42571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu", 426204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) framePosition, 427204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) nanoTime); 428204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t nanosDelta = nanoTime - oldTime; 429204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nanosDelta > 0 && oldTime > 0) { 430204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framesDelta = framePosition - oldPosition; 4315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta; 43271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta); 43371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta); 43471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate); 435204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 436204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldPosition = framePosition; 437204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldTime = nanoTime; 438204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 439204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 440204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) { 4423316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framePosition = 0; 443204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 444204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioStreamInternal_LogTimestamp(command); 445204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 446204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framePosition = message->timestamp.position; 447204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(framePosition, message->timestamp.timestamp); 4485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 449204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 450204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) { 4525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 45371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got event %d", message->event.event); 454204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message->event.event) { 4555ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_STARTED: 45671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STARTED"); 4575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 458204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_PAUSED: 46071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_PAUSED"); 4615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSED); 462204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 46371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk case AAUDIO_SERVICE_EVENT_STOPPED: 46471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STOPPED"); 46571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk setState(AAUDIO_STREAM_STATE_STOPPED); 46671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk break; 4675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_FLUSHED: 46871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED"); 4695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_FLUSHED); 470204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk onFlushFromServer(); 471204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_CLOSED: 47371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_CLOSED"); 4745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 475204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_DISCONNECTED: 4775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_DISCONNECTED; 478c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk setState(AAUDIO_STREAM_STATE_DISCONNECTED); 4795ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED"); 480204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 481c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk case AAUDIO_SERVICE_EVENT_VOLUME: 482e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk mVolumeRamp.setTarget((float) message->event.dataDouble); 483e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() AAUDIO_SERVICE_EVENT_VOLUME %f", 484e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk message->event.dataDouble); 485c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk break; 486204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 487204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - processCommands() Unrecognized event = %d", 488204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message->event.event); 489204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 490204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 491204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 492204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 493204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 494204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Process all the commands coming from the server. 4955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::processCommands() { 4965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 497204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk while (result == AAUDIO_OK) { 49971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::processCommands() - looping, %d", result); 5005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioServiceMessage message; 501204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.readUpCommand(&message) != 1) { 502204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // no command this time, no problem 503204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 504204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message.what) { 5055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::TIMESTAMP: 506204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onTimestampFromServer(&message); 507204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 508204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::EVENT: 510204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onEventFromServer(&message); 511204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 512204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 513204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 51471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d", 515204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message.what); 5165ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_UNEXPECTED_VALUE; 517204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 518204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 519204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 520204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 521204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 522204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 523204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write the data, block if needed and timeoutMillis > 0 5245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames, 5253316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 526204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 5275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 528c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t loopCount = 0; 529204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint8_t* source = (uint8_t*)buffer; 5303316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t currentTimeNanos = AudioClock::getNanoseconds(); 5313316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds; 532204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesLeft = numFrames; 533204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 534204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write until all the data has been written or until a timeout occurs. 535204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (framesLeft > 0) { 536204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // The call to writeNow() will not block. It will just write as much as it can. 5373316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t wakeTimeNanos = 0; 5385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t framesWritten = writeNow(source, framesLeft, 539204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos, &wakeTimeNanos); 540204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten < 0) { 541c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk ALOGE("AudioStreamInternal::write() loop: writeNow returned %d", framesWritten); 542204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = framesWritten; 543204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 544204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 545204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesLeft -= (int32_t) framesWritten; 546204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk source += framesWritten * getBytesPerFrame(); 547204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 548204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Should we block? 549204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (timeoutNanoseconds == 0) { 550204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // don't block 551204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else if (framesLeft > 0) { 552204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // clip the wake time to something reasonable 553204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos < currentTimeNanos) { 554204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTimeNanos = currentTimeNanos; 555204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 556204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos > deadlineNanos) { 557204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If we time out, just return the framesWritten so far. 558c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk ALOGE("AudioStreamInternal::write(): timed out after %lld nanos", 559c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk (long long) timeoutNanoseconds); 560204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 561204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 562204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 56371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos; 56471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk AudioClock::sleepForNanos(sleepForNanos); 565204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos = AudioClock::getNanoseconds(); 566204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 567204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 568204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 569204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // return error or framesWritten 570c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk (void) loopCount; 571204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return (result < 0) ? result : numFrames - framesLeft; 572204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 573204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 574204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write as much data as we can without blocking. 5755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames, 5763316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t currentNanoTime, int64_t *wakeTimePtr) { 577c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 578204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 5795ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = processCommands(); 5805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 581204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 582204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 583204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 584204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 585204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.isOutputFreeRunning()) { 58671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - update read counter"); 587204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Update data queue based on the timing model. 588204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime); 589204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter); 590204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 591204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO else query from endpoint cuz set by actual reader, maybe 592204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 593c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // If the read index passed the write index then consider it an underrun. 594c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (mAudioEndpoint.getFullFramesAvailable() < 0) { 595c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mXRunCount++; 596204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 597c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 598c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Write some data to the buffer. 59971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - writeNowWithConversion(%d)", numFrames); 600c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesWritten = writeNowWithConversion(buffer, numFrames); 60171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d", 602204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // numFrames, framesWritten); 603204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 604204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Calculate an ideal time to wake up. 605204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimePtr != nullptr && framesWritten >= 0) { 606204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // By default wake up a few milliseconds from now. // TODO review 607c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND); 608c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk aaudio_stream_state_t state = getState(); 60971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - wakeTime based on %s", 610c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // AAudio_convertStreamStateToText(state)); 611c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk switch (state) { 6125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_OPEN: 6135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 614204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten != 0) { 615204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Don't wait to write more data. Just prime the buffer. 616204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = currentNanoTime; 617204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 618204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 6195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur? 620204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 621204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint32_t burstSize = mFramesPerBurst; 622204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (burstSize < 32) { 623204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk burstSize = 32; // TODO review 624204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 625204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 626204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize; 627204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = mClockModel.convertPositionToTime(nextReadPosition); 628204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 629204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 630204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 631204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 632204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 633204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *wakeTimePtr = wakeTime; 634204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 635204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 63671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk// ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu", 637204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)currentNanoTime, 638204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(), 639204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter()); 640204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesWritten; 641204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 642204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 643c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 644c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t AudioStreamInternal::writeNowWithConversion(const void *buffer, 645c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t numFrames) { 646e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion(%p, %d)", 647e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // buffer, numFrames); 648c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk WrappingBuffer wrappingBuffer; 649c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk uint8_t *source = (uint8_t *) buffer; 650c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesLeft = numFrames; 651c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 652c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mAudioEndpoint.getEmptyRoomAvailable(&wrappingBuffer); 653c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 654c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Read data in one or two parts. 655c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int partIndex = 0; 656c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) { 657c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesToWrite = framesLeft; 658c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesAvailable = wrappingBuffer.numFrames[partIndex]; 659c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesAvailable > 0) { 660c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesToWrite > framesAvailable) { 661c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk framesToWrite = framesAvailable; 662c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 66371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int32_t numBytes = getBytesPerFrame() * framesToWrite; 664e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numSamples = framesToWrite * getSamplesPerFrame(); 665e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // Data conversion. 666e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float levelFrom; 667e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float levelTo; 668e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk bool ramping = mVolumeRamp.nextSegment(framesToWrite * getSamplesPerFrame(), 669e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk &levelFrom, &levelTo); 670e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // The formats are validated when the stream is opened so we do not have to 671e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // check for illegal combinations here. 672e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT) { 673e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) { 674e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudio_linearRamp( 675e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const float *) source, 676e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (float *) wrappingBuffer.data[partIndex], 677e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 678e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 679e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 680e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 681e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) { 682e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (ramping) { 683e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_floatToPcm16( 684e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const float *) source, 685e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (int16_t *) wrappingBuffer.data[partIndex], 686e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 687e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 688e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 689e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 690e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else { 691e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_floatToPcm16( 692e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const float *) source, 693e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (int16_t *) wrappingBuffer.data[partIndex], 694e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk numSamples, 695e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 696e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 697e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 698e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else if (getFormat() == AAUDIO_FORMAT_PCM_I16) { 699e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) { 700e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (ramping) { 701e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_pcm16ToFloat( 702e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const int16_t *) source, 703e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (float *) wrappingBuffer.data[partIndex], 704e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 705e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 706e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 707e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 708e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else { 709e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_pcm16ToFloat( 710e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const int16_t *) source, 711e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (float *) wrappingBuffer.data[partIndex], 712e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk numSamples, 713e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 714e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 715e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) { 716e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudio_linearRamp( 717e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const int16_t *) source, 718e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (int16_t *) wrappingBuffer.data[partIndex], 719e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 720e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 721e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 722e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 723e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 724c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 725c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk source += numBytes; 726c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk framesLeft -= framesToWrite; 72771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } else { 72871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk break; 729c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 730c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk partIndex++; 731c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 732c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesWritten = numFrames - framesLeft; 733c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mAudioEndpoint.advanceWriteIndex(framesWritten); 734c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 735c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesWritten > 0) { 736c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk incrementFramesWritten(framesWritten); 737c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 73871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion() returns %d", framesWritten); 739c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return framesWritten; 740c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 741c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 7423316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkvoid AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) { 743204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.processTimestamp( position, time); 744204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 745204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7463316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) { 7473316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t actualFrames = 0; 74871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // Round to the next highest burst size. 74971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (getFramesPerBurst() > 0) { 75071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int32_t numBursts = (requestedFrames + getFramesPerBurst() - 1) / getFramesPerBurst(); 75171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk requestedFrames = numBursts * getFramesPerBurst(); 75271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 75371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 7543316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames); 75571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::setBufferSize() %s req = %d => %d", 75671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk getLocationName(), requestedFrames, actualFrames); 7573316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk if (result < 0) { 7583316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return result; 7593316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk } else { 7603316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return (aaudio_result_t) actualFrames; 7613316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk } 762204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 763204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7643316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getBufferSize() const 765204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 766204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferSizeInFrames(); 767204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 768204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7693316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getBufferCapacity() const 770204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 771204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferCapacityInFrames(); 772204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 773204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7743316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getFramesPerBurst() const 775204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 776204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 777204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 778204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7793316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint64_t AudioStreamInternal::getFramesRead() 780204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 7813316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framesRead = 782204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) 783204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk + mFramesOffsetFromService; 784204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Prevent retrograde motion. 785204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesRead < mLastFramesRead) { 786204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesRead = mLastFramesRead; 787204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 788204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mLastFramesRead = framesRead; 789204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 79071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead); 791204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesRead; 792204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 793204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 794204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement getTimestamp 795