AudioStreamInternal.cpp revision 4485d41bcded0eceec7ec97d50aa2b0e702397a0
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 214485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk#define ATRACE_TAG ATRACE_TAG_AUDIO 224485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 23c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <stdint.h> 24204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <assert.h> 25204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 26204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <binder/IServiceManager.h> 27204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h> 29e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <utils/String16.h> 304485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk#include <utils/Trace.h> 31204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 32c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AudioClock.h" 33c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AudioEndpointParcelable.h" 34c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/AAudioStreamRequest.h" 35c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/AAudioStreamConfiguration.h" 36c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/IAAudioService.h" 375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include "binding/AAudioServiceMessage.h" 38e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#include "core/AudioStreamBuilder.h" 39c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "fifo/FifoBuffer.h" 40e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#include "utility/LinearRamp.h" 41204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 42c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AudioStreamInternal.h" 43204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 44204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#define LOG_TIMESTAMPS 0 45204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 46204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::String16; 47dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkusing android::Mutex; 48c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkusing android::WrappingBuffer; 49204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 51204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 52e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define MIN_TIMEOUT_NANOS (1000 * AAUDIO_NANOS_PER_MILLISECOND) 53e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 54e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Wait at least this many times longer than the operation should take. 55e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define MIN_TIMEOUT_OPERATIONS 4 56e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 5771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk//static int64_t s_logCounter = 0; 5871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk//#define MYLOG_CONDITION (mInService == true && s_logCounter++ < 500) 5971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk//#define MYLOG_CONDITION (s_logCounter++ < 500000) 6071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#define MYLOG_CONDITION (1) 61204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 62c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil BurkAudioStreamInternal::AudioStreamInternal(AAudioServiceInterface &serviceInterface, bool inService) 63204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk : AudioStream() 64204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mClockModel() 65204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mAudioEndpoint() 665ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk , mServiceStreamHandle(AAUDIO_HANDLE_INVALID) 67204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mFramesPerBurst(16) 68c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk , mServiceInterface(serviceInterface) 6971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk , mInService(inService) { 70204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 71204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 72204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::~AudioStreamInternal() { 73204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 74204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { 76204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamRequest request; 795ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamConfiguration configuration; 80204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 81204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = AudioStream::open(builder); 82204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result < 0) { 83204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 84204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 85204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 86c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // We have to do volume scaling. So we prefer FLOAT format. 87c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (getFormat() == AAUDIO_UNSPECIFIED) { 88c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk setFormat(AAUDIO_FORMAT_PCM_FLOAT); 89c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 9071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // Request FLOAT for the shared mixer. 9171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk request.getConfiguration().setAudioFormat(AAUDIO_FORMAT_PCM_FLOAT); 92c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 93dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // Build the request to send to the server. 94204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setUserId(getuid()); 95204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setProcessId(getpid()); 96c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk request.setDirection(getDirection()); 9771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk request.setSharingModeMatchRequired(isSharingModeMatchRequired()); 98c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 99204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setDeviceId(getDeviceId()); 100204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSampleRate(getSampleRate()); 101204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame()); 10271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk request.getConfiguration().setSharingMode(getSharingMode()); 10371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 1043df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk request.getConfiguration().setBufferCapacity(builder.getBufferCapacity()); 105204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 106c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceStreamHandle = mServiceInterface.openStream(request, configuration); 107204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle < 0) { 108204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = mServiceStreamHandle; 10971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal.open(): %s openStream() returned %d", getLocationName(), result); 110204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 111204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = configuration.validate(); 1125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 113204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk close(); 114204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 115204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 116204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Save results of the open. 117204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSampleRate(configuration.getSampleRate()); 118204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSamplesPerFrame(configuration.getSamplesPerFrame()); 119c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk setDeviceId(configuration.getDeviceId()); 120204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 121c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Save device format so we can do format conversion and volume scaling together. 122c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mDeviceFormat = configuration.getAudioFormat(); 123c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 124c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable); 1255ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 12671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal.open(): %s getStreamDescriptor returns %d", 12771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk getLocationName(), result); 128c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 129204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 130204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 131c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 132204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // resolve parcelable into a descriptor 133c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk result = mEndPointParcelable.resolve(&mEndpointDescriptor); 134c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (result != AAUDIO_OK) { 135c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk ALOGE("AudioStreamInternal.open(): resolve() returns %d", result); 136c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 137c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return result; 138c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 139204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 140204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Configure endpoint based on descriptor. 141204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.configure(&mEndpointDescriptor); 142204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 143204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 14471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int32_t capacity = mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames; 14571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 14671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.open() %s framesPerBurst = %d, capacity = %d", 14771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk getLocationName(), mFramesPerBurst, capacity); 14871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // Validate result from server. 14971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) { 15071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStream::open(): framesPerBurst out of range = %d", mFramesPerBurst); 15171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 15271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 15371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (capacity < mFramesPerBurst || capacity > 32 * 1024) { 15471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStream::open(): bufferCapacity out of range = %d", capacity); 15571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 15671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 157204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 158204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setSampleRate(getSampleRate()); 159204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setFramesPerBurst(mFramesPerBurst); 160204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 161e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (getDataCallbackProc()) { 162e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackFrames = builder.getFramesPerDataCallback(); 163e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackFrames > getBufferCapacity() / 2) { 16471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal.open(): framesPerCallback too large = %d, capacity = %d", 16571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mCallbackFrames, getBufferCapacity()); 166c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 167e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 168e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 169e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else if (mCallbackFrames < 0) { 170e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk ALOGE("AudioStreamInternal.open(): framesPerCallback negative"); 171c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(mServiceStreamHandle); 172e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 173e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 174e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 175e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackFrames == AAUDIO_UNSPECIFIED) { 176e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackFrames = mFramesPerBurst; 177e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 178e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 179e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int32_t bytesPerFrame = getSamplesPerFrame() 180e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * AAudioConvert_formatToSizeInBytes(getFormat()); 181e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame; 182e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBuffer = new uint8_t[callbackBufferSize]; 183e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 184e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 1855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 186204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 187204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 188204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 189204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1905ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::close() { 19171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", 19271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 1935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { 1944485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk // Don't close a stream while it is running. 1954485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk aaudio_stream_state_t currentState = getState(); 1964485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk if (isPlaying()) { 1974485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk requestStop(); 1984485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk aaudio_stream_state_t nextState; 1994485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk int64_t timeoutNanoseconds = MIN_TIMEOUT_NANOS; 2004485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk aaudio_result_t result = waitForStateChange(currentState, &nextState, 2014485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk timeoutNanoseconds); 2024485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk if (result != AAUDIO_OK) { 2034485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk ALOGE("AudioStreamInternal::close() waitForStateChange() returned %d %s", 2044485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk result, AAudio_convertResultToText(result)); 2054485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk } 2064485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk } 2075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; 2085ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk mServiceStreamHandle = AAUDIO_HANDLE_INVALID; 209c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 210c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mServiceInterface.closeStream(serviceStreamHandle); 211e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk delete[] mCallbackBuffer; 2124485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk mCallbackBuffer = nullptr; 213c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mEndPointParcelable.close(); 214204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 2155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_HANDLE; 216204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 217204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 218204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 219c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 220e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Render audio in the application callback and then write the data to the stream. 221e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid *AudioStreamInternal::callbackLoop() { 222e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk aaudio_result_t result = AAUDIO_OK; 223e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE; 224e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AAudioStream_dataCallback appCallback = getDataCallbackProc(); 225e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (appCallback == nullptr) return NULL; 226e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 227677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // result might be a frame count 228677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk while (mCallbackEnabled.load() && isPlaying() && (result >= 0)) { 229e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Call application using the AAudio callback interface. 230e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackResult = (*appCallback)( 231e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk (AAudioStream *) this, 232e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk getDataCallbackUserData(), 233e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBuffer, 234e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackFrames); 235e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 236e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) { 237677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // Write audio data to stream. 238e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames); 239677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk 240677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // This is a BLOCKING WRITE! 241e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk result = write(mCallbackBuffer, mCallbackFrames, timeoutNanos); 242677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk if ((result != mCallbackFrames)) { 243677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk ALOGE("AudioStreamInternal(): callbackLoop: write() returned %d", result); 244677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk if (result >= 0) { 245677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk // Only wrote some of the frames requested. Must have timed out. 246677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk result = AAUDIO_ERROR_TIMEOUT; 247677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk } 248e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (getErrorCallbackProc() != nullptr) { 249e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk (*getErrorCallbackProc())( 250e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk (AAudioStream *) this, 251e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk getErrorCallbackUserData(), 252677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk result); 253e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 254e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 255e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 256e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) { 257677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk ALOGD("AudioStreamInternal(): callback returned AAUDIO_CALLBACK_RESULT_STOP"); 258e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 259e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 260e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 261e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 262677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk ALOGD("AudioStreamInternal(): callbackLoop() exiting, result = %d, isPlaying() = %d", 263e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk result, (int) isPlaying()); 2645204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk return NULL; 265e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 266e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 267e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkstatic void *aaudio_callback_thread_proc(void *context) 268e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{ 269e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioStreamInternal *stream = (AudioStreamInternal *)context; 270677d7916c0fa6f0955aae8f3ef921383e285beb2Phil Burk //LOGD("AudioStreamInternal(): oboe_callback_thread, stream = %p", stream); 271e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (stream != NULL) { 272e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return stream->callbackLoop(); 273e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 274e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return NULL; 275e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 276e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 277e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 2785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStart() 279204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 2803316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t startTime; 28171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): start()"); 2825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2835ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 284204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 285c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 2863316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk startTime = AudioClock::getNanoseconds(); 287204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.start(startTime); 288204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(0, startTime); 2895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 290c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);; 291e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 292e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (result == AAUDIO_OK && getDataCallbackProc() != nullptr) { 293e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Launch the callback loop thread. 294e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int64_t periodNanos = mCallbackFrames 295e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * AAUDIO_NANOS_PER_SECOND 296e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk / getSampleRate(); 297e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackEnabled.store(true); 298e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk result = createThread(periodNanos, aaudio_callback_thread_proc, this); 299e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 300e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return result; 301204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 302204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 303e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkint64_t AudioStreamInternal::calculateReasonableTimeout(int32_t framesPerOperation) { 304e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 305e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Wait for at least a second or some number of callbacks to join the thread. 30671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int64_t timeoutNanoseconds = (MIN_TIMEOUT_OPERATIONS 30771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk * framesPerOperation 30871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk * AAUDIO_NANOS_PER_SECOND) 30971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk / getSampleRate(); 310e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (timeoutNanoseconds < MIN_TIMEOUT_NANOS) { // arbitrary number of seconds 311e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk timeoutNanoseconds = MIN_TIMEOUT_NANOS; 312e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 313e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return timeoutNanoseconds; 314e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 315e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 316e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::stopCallback() 317e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{ 318e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (isDataCallbackActive()) { 319e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackEnabled.store(false); 320e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return joinThread(NULL, calculateReasonableTimeout(mCallbackFrames)); 321e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 322e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_OK; 323e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 324e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 325e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 326e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::requestPauseInternal() 327204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 3285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 32971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal(): requestPauseInternal() mServiceStreamHandle invalid = 0x%08X", 33071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 3315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 332204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 333c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 3343316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk mClockModel.stop(AudioClock::getNanoseconds()); 3355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSING); 33671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return mServiceInterface.pauseStream(mServiceStreamHandle); 337204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 338204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 339e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::requestPause() 340e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{ 34171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestPause()", getLocationName()); 342e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk aaudio_result_t result = stopCallback(); 343e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (result != AAUDIO_OK) { 344e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return result; 345e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 34671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk result = requestPauseInternal(); 34771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD("AudioStreamInternal(): requestPause() returns %d", result); 34871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return result; 349e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 350e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 3515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestFlush() { 35271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): requestFlush()"); 3535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 35471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal(): requestFlush() mServiceStreamHandle invalid = 0x%08X", 35571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 3565ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 357204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 358c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 359e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk setState(AAUDIO_STREAM_STATE_FLUSHING); 360c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mServiceInterface.flushStream(mServiceStreamHandle); 361204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 362204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 363204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::onFlushFromServer() { 36471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): onFlushFromServer()"); 3653316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t readCounter = mAudioEndpoint.getDownDataReadCounter(); 3663316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t writeCounter = mAudioEndpoint.getDownDataWriteCounter(); 36771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 368204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Bump offset so caller does not see the retrograde motion in getFramesRead(). 3693316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framesFlushed = writeCounter - readCounter; 370204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesOffsetFromService += framesFlushed; 37171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 372204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Flush written frames by forcing writeCounter to readCounter. 373204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // This is because we cannot move the read counter in the hardware. 374204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataWriteCounter(readCounter); 375204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 376204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 37771f35bb687476694882a617ba4a810a0bb56fe23Phil Burkaaudio_result_t AudioStreamInternal::requestStopInternal() 37871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk{ 37971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 38071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("AudioStreamInternal(): requestStopInternal() mServiceStreamHandle invalid = 0x%08X", 38171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mServiceStreamHandle); 38271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return AAUDIO_ERROR_INVALID_STATE; 38371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 38471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 38571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk mClockModel.stop(AudioClock::getNanoseconds()); 38671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk setState(AAUDIO_STREAM_STATE_STOPPING); 38771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return mServiceInterface.stopStream(mServiceStreamHandle); 38871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk} 38971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 3905ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStop() 391204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 39271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestStop()", getLocationName()); 39371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk aaudio_result_t result = stopCallback(); 39471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (result != AAUDIO_OK) { 39571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return result; 396204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 39771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk result = requestStopInternal(); 39871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD("AudioStreamInternal(): requestStop() returns %d", result); 399204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 400204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 401204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::registerThread() { 4035ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 4045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 405204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 406c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mServiceInterface.registerAudioThread(mServiceStreamHandle, 407c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk getpid(), 408c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk gettid(), 409c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk getPeriodNanoseconds()); 410204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 411204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::unregisterThread() { 4135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 4145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 415204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 416c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, getpid(), gettid()); 417204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 418204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId, 4203316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t *framePosition, 4213316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t *timeNanoseconds) { 4225204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk // TODO Generate in server and pass to client. Return latest. 4233316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t time = AudioClock::getNanoseconds(); 424204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *framePosition = mClockModel.convertTimeToPosition(time); 4255ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay 4265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 427204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 428204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 429e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamInternal::updateStateWhileWaiting() { 430e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (isDataCallbackActive()) { 431e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return AAUDIO_OK; // state is getting updated by the callback thread read/write call 432e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 433204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return processCommands(); 434204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 435204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 436204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 4375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) { 438204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static int64_t oldPosition = 0; 4393316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk static int64_t oldTime = 0; 440204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framePosition = command.timestamp.position; 4413316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t nanoTime = command.timestamp.timestamp; 44271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu", 443204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) framePosition, 444204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) nanoTime); 445204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t nanosDelta = nanoTime - oldTime; 446204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nanosDelta > 0 && oldTime > 0) { 447204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framesDelta = framePosition - oldPosition; 4485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta; 44971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta); 45071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta); 45171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate); 452204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 453204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldPosition = framePosition; 454204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldTime = nanoTime; 455204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 456204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 457204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) { 4593316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framePosition = 0; 460204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 461204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioStreamInternal_LogTimestamp(command); 462204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 463204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framePosition = message->timestamp.position; 464204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(framePosition, message->timestamp.timestamp); 4655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 466204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 467204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4685ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) { 4695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 47071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got event %d", message->event.event); 471204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message->event.event) { 4725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_STARTED: 47371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STARTED"); 4745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 475204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_PAUSED: 47771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_PAUSED"); 4785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSED); 479204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 48071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk case AAUDIO_SERVICE_EVENT_STOPPED: 48171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STOPPED"); 48271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk setState(AAUDIO_STREAM_STATE_STOPPED); 48371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk break; 4845ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_FLUSHED: 48571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED"); 4865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_FLUSHED); 487204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk onFlushFromServer(); 488204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_CLOSED: 49071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_CLOSED"); 4915ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 492204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_DISCONNECTED: 4945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_DISCONNECTED; 495c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk setState(AAUDIO_STREAM_STATE_DISCONNECTED); 4965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED"); 497204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 498c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk case AAUDIO_SERVICE_EVENT_VOLUME: 499e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk mVolumeRamp.setTarget((float) message->event.dataDouble); 500e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk ALOGD_IF(MYLOG_CONDITION, "processCommands() AAUDIO_SERVICE_EVENT_VOLUME %f", 501e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk message->event.dataDouble); 502c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk break; 503204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 504204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - processCommands() Unrecognized event = %d", 505204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message->event.event); 506204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 507204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 508204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 509204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 510204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 511204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Process all the commands coming from the server. 5125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::processCommands() { 5135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 514204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk while (result == AAUDIO_OK) { 51671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::processCommands() - looping, %d", result); 5175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioServiceMessage message; 518204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.readUpCommand(&message) != 1) { 519204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // no command this time, no problem 520204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 521204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message.what) { 5225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::TIMESTAMP: 523204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onTimestampFromServer(&message); 524204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 525204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::EVENT: 527204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onEventFromServer(&message); 528204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 529204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 530204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 53171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d", 532204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message.what); 5335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_UNEXPECTED_VALUE; 534204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 535204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 536204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 537204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 538204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 539204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 540204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write the data, block if needed and timeoutMillis > 0 5415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames, 5423316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 543204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 5444485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk const char * traceName = (mInService) ? "aaWrtS" : "aaWrtC"; 5454485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk ATRACE_BEGIN(traceName); 5465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 547c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t loopCount = 0; 548204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint8_t* source = (uint8_t*)buffer; 5493316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t currentTimeNanos = AudioClock::getNanoseconds(); 5503316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds; 551204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesLeft = numFrames; 552204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5534485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); 5544485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk if (ATRACE_ENABLED()) { 5554485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk const char * traceName = (mInService) ? "aaFullS" : "aaFullC"; 5564485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk ATRACE_INT(traceName, fullFrames); 5574485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk } 5584485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 559204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write until all the data has been written or until a timeout occurs. 560204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (framesLeft > 0) { 561204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // The call to writeNow() will not block. It will just write as much as it can. 5623316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t wakeTimeNanos = 0; 5635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t framesWritten = writeNow(source, framesLeft, 564204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos, &wakeTimeNanos); 565204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten < 0) { 566c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk ALOGE("AudioStreamInternal::write() loop: writeNow returned %d", framesWritten); 567204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = framesWritten; 568204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 569204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 570204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesLeft -= (int32_t) framesWritten; 571204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk source += framesWritten * getBytesPerFrame(); 572204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 573204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Should we block? 574204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (timeoutNanoseconds == 0) { 575204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // don't block 576204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else if (framesLeft > 0) { 577204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // clip the wake time to something reasonable 578204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos < currentTimeNanos) { 579204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTimeNanos = currentTimeNanos; 580204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 581204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos > deadlineNanos) { 582204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If we time out, just return the framesWritten so far. 583c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk ALOGE("AudioStreamInternal::write(): timed out after %lld nanos", 584c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk (long long) timeoutNanoseconds); 585204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 586204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 587204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 58871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos; 58971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk AudioClock::sleepForNanos(sleepForNanos); 590204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos = AudioClock::getNanoseconds(); 591204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 592204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 593204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 594204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // return error or framesWritten 595c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk (void) loopCount; 5964485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk ATRACE_END(); 597204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return (result < 0) ? result : numFrames - framesLeft; 598204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 599204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 600204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write as much data as we can without blocking. 6015ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames, 6023316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t currentNanoTime, int64_t *wakeTimePtr) { 6035204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk aaudio_result_t result = processCommands(); 6045204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk if (result != AAUDIO_OK) { 6055204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk return result; 606204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 607204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 608204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.isOutputFreeRunning()) { 60971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - update read counter"); 610204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Update data queue based on the timing model. 611204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime); 612204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter); 613204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 614204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO else query from endpoint cuz set by actual reader, maybe 615204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 616c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // If the read index passed the write index then consider it an underrun. 617c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (mAudioEndpoint.getFullFramesAvailable() < 0) { 618c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mXRunCount++; 619204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 620c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 621c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Write some data to the buffer. 62271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - writeNowWithConversion(%d)", numFrames); 623c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesWritten = writeNowWithConversion(buffer, numFrames); 62471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d", 625204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // numFrames, framesWritten); 626204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 627204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Calculate an ideal time to wake up. 628204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimePtr != nullptr && framesWritten >= 0) { 629204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // By default wake up a few milliseconds from now. // TODO review 630c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND); 631c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk aaudio_stream_state_t state = getState(); 63271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - wakeTime based on %s", 633c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // AAudio_convertStreamStateToText(state)); 634c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk switch (state) { 6355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_OPEN: 6365ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 637204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten != 0) { 638204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Don't wait to write more data. Just prime the buffer. 639204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = currentNanoTime; 640204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 641204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 6425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur? 643204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 644204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint32_t burstSize = mFramesPerBurst; 645204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (burstSize < 32) { 646204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk burstSize = 32; // TODO review 647204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 648204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 649204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize; 650204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = mClockModel.convertPositionToTime(nextReadPosition); 651204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 652204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 653204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 654204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 655204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 656204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *wakeTimePtr = wakeTime; 657204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 658204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 65971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk// ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu", 660204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)currentNanoTime, 661204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(), 662204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter()); 663204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesWritten; 664204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 665204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 666c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 667c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t AudioStreamInternal::writeNowWithConversion(const void *buffer, 668c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t numFrames) { 669e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion(%p, %d)", 670e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // buffer, numFrames); 671c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk WrappingBuffer wrappingBuffer; 672c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk uint8_t *source = (uint8_t *) buffer; 673c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesLeft = numFrames; 674c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 675c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mAudioEndpoint.getEmptyRoomAvailable(&wrappingBuffer); 676c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 677c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Read data in one or two parts. 678c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int partIndex = 0; 679c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) { 680c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesToWrite = framesLeft; 681c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesAvailable = wrappingBuffer.numFrames[partIndex]; 682c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesAvailable > 0) { 683c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesToWrite > framesAvailable) { 684c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk framesToWrite = framesAvailable; 685c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 68671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int32_t numBytes = getBytesPerFrame() * framesToWrite; 687e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numSamples = framesToWrite * getSamplesPerFrame(); 688e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // Data conversion. 689e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float levelFrom; 690e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float levelTo; 691e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk bool ramping = mVolumeRamp.nextSegment(framesToWrite * getSamplesPerFrame(), 692e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk &levelFrom, &levelTo); 693e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // The formats are validated when the stream is opened so we do not have to 694e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // check for illegal combinations here. 695e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT) { 696e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) { 697e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudio_linearRamp( 698e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const float *) source, 699e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (float *) wrappingBuffer.data[partIndex], 700e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 701e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 702e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 703e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 704e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) { 705e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (ramping) { 706e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_floatToPcm16( 707e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const float *) source, 708e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (int16_t *) wrappingBuffer.data[partIndex], 709e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 710e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 711e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 712e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 713e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else { 714e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_floatToPcm16( 715e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const float *) source, 716e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (int16_t *) wrappingBuffer.data[partIndex], 717e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk numSamples, 718e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 719e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 720e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 721e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else if (getFormat() == AAUDIO_FORMAT_PCM_I16) { 722e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) { 723e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (ramping) { 724e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_pcm16ToFloat( 725e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const int16_t *) source, 726e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (float *) wrappingBuffer.data[partIndex], 727e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 728e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 729e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 730e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 731e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else { 732e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudioConvert_pcm16ToFloat( 733e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const int16_t *) source, 734e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (float *) wrappingBuffer.data[partIndex], 735e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk numSamples, 736e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 737e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 738e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) { 739e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk AAudio_linearRamp( 740e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (const int16_t *) source, 741e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk (int16_t *) wrappingBuffer.data[partIndex], 742e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk framesToWrite, 743e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk getSamplesPerFrame(), 744e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelFrom, 745e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk levelTo); 746e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 747c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 748c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk source += numBytes; 749c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk framesLeft -= framesToWrite; 75071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } else { 75171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk break; 752c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 753c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk partIndex++; 754c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 755c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t framesWritten = numFrames - framesLeft; 756c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mAudioEndpoint.advanceWriteIndex(framesWritten); 757c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 758c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesWritten > 0) { 759c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk incrementFramesWritten(framesWritten); 760c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 76171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion() returns %d", framesWritten); 762c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return framesWritten; 763c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 764c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 7653316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkvoid AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) { 766204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.processTimestamp( position, time); 767204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 768204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7693316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) { 7703316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t actualFrames = 0; 77171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // Round to the next highest burst size. 77271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk if (getFramesPerBurst() > 0) { 77371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk int32_t numBursts = (requestedFrames + getFramesPerBurst() - 1) / getFramesPerBurst(); 77471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk requestedFrames = numBursts * getFramesPerBurst(); 77571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk } 77671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 7773316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames); 77871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::setBufferSize() %s req = %d => %d", 77971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk getLocationName(), requestedFrames, actualFrames); 7803316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk if (result < 0) { 7813316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return result; 7823316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk } else { 7833316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return (aaudio_result_t) actualFrames; 7843316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk } 785204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 786204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7873316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getBufferSize() const 788204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 789204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferSizeInFrames(); 790204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 791204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7923316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getBufferCapacity() const 793204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 794204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferCapacityInFrames(); 795204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 796204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 7973316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getFramesPerBurst() const 798204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 799204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 800204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 801204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 8023316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint64_t AudioStreamInternal::getFramesRead() 803204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 8043316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framesRead = 805204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) 806204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk + mFramesOffsetFromService; 807204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Prevent retrograde motion. 808204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesRead < mLastFramesRead) { 809204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesRead = mLastFramesRead; 810204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 811204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mLastFramesRead = framesRead; 812204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 81371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead); 814204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesRead; 815204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 816204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 8174c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burkint64_t AudioStreamInternal::getFramesWritten() 8184c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk{ 8194c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk int64_t getFramesWritten = mAudioEndpoint.getDownDataWriteCounter() 8204c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk + mFramesOffsetFromService; 8214c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::getFramesWritten() returns %lld", (long long)getFramesWritten); 8224c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk return getFramesWritten; 8234c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk} 824