AudioStreamInternal.cpp revision 5ed503c7a66c90f93759c90237a9b432dbd93f9f
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 21204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <stdint.h> 22204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <assert.h> 23204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 24204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <binder/IServiceManager.h> 25dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk#include <utils/Mutex.h> 26204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h> 28204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 29204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioClock.h" 30204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioEndpointParcelable.h" 315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include "binding/AAudioStreamRequest.h" 325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include "binding/AAudioStreamConfiguration.h" 335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include "binding/IAAudioService.h" 345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include "binding/AAudioServiceMessage.h" 35204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 36204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioStreamInternal.h" 37204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 38204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#define LOG_TIMESTAMPS 0 39204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 40204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::String16; 41204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::IServiceManager; 42204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::defaultServiceManager; 43204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::interface_cast; 44dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkusing android::Mutex; 45204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 47204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 48dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkstatic android::Mutex gServiceLock; 495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic sp<IAAudioService> gAAudioService; 50dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#define AAUDIO_SERVICE_NAME "AAudioService" 52dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk// Helper function to get access to the "AAudioService" service. 54dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp 555ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic const sp<IAAudioService> getAAudioService() { 56dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk sp<IBinder> binder; 57dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk Mutex::Autolock _l(gServiceLock); 585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (gAAudioService == 0) { 59dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk sp<IServiceManager> sm = defaultServiceManager(); 60dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // Try several times to get the service. 61dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk int retries = 4; 62dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk do { 635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while. 64dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (binder != 0) { 65dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 66dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 67dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } while (retries-- > 0); 68dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 69dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (binder != 0) { 70dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // TODO Add linkToDeath() like in frameworks/av/media/libaudioclient/AudioSystem.cpp 71dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // TODO Create a DeathRecipient that disconnects all active streams. 725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk gAAudioService = interface_cast<IAAudioService>(binder); 73dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } else { 745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGE("AudioStreamInternal could not get %s", AAUDIO_SERVICE_NAME); 75dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 76dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return gAAudioService; 78204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 79204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 80204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::AudioStreamInternal() 81204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk : AudioStream() 82204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mClockModel() 83204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mAudioEndpoint() 845ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk , mServiceStreamHandle(AAUDIO_HANDLE_INVALID) 85204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mFramesPerBurst(16) 86204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 87204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 88204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 89204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::~AudioStreamInternal() { 90204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 91204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { 93204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& service = getAAudioService(); 955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 96dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamRequest request; 995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamConfiguration configuration; 100204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 101204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = AudioStream::open(builder); 102204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result < 0) { 103204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 104204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 105204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 106dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // Build the request to send to the server. 107204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setUserId(getuid()); 108204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setProcessId(getpid()); 109204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setDeviceId(getDeviceId()); 110204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSampleRate(getSampleRate()); 111204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame()); 112204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setAudioFormat(getFormat()); 113204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.dump(); 114204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 115dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk mServiceStreamHandle = service->openStream(request, configuration); 116204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal.open(): openStream returned mServiceStreamHandle = 0x%08X", 117204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (unsigned int)mServiceStreamHandle); 118204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle < 0) { 119204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = mServiceStreamHandle; 1205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGE("AudioStreamInternal.open(): acquireRealtimeStream aaudio_result_t = 0x%08X", result); 121204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 122204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = configuration.validate(); 1235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 124204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk close(); 125204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 126204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 127204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Save results of the open. 128204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSampleRate(configuration.getSampleRate()); 129204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSamplesPerFrame(configuration.getSamplesPerFrame()); 130204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setFormat(configuration.getAudioFormat()); 131204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio::AudioEndpointParcelable parcelable; 133dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk result = service->getStreamDescription(mServiceStreamHandle, parcelable); 1345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 135204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal.open(): getStreamDescriptor returns %d", result); 136dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk service->closeStream(mServiceStreamHandle); 137204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 138204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 139204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // resolve parcelable into a descriptor 140204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk parcelable.resolve(&mEndpointDescriptor); 141204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 142204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Configure endpoint based on descriptor. 143204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.configure(&mEndpointDescriptor); 144204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 145204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 146204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 147204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk assert(mFramesPerBurst >= 16); 148204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk assert(mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames < 10 * 1024); 149204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 150204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setSampleRate(getSampleRate()); 151204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setFramesPerBurst(mFramesPerBurst); 152204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 154204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 155204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 156204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 157204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::close() { 159204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", mServiceStreamHandle); 1605ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { 1615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; 1625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk mServiceStreamHandle = AAUDIO_HANDLE_INVALID; 1635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 1645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 1655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudioService->closeStream(serviceStreamHandle); 1665ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 167204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 1685ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_HANDLE; 169204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 170204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 171204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStart() 173204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 1745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t startTime; 175204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): start()"); 1765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 1775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 178204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 1795ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 1805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 1815ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk startTime = AAudio_getNanoseconds(AAUDIO_CLOCK_MONOTONIC); 182204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.start(startTime); 183204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(0, startTime); 1845ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 1855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->startStream(mServiceStreamHandle); 186204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 187204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1885ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestPause() 189204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 190204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): pause()"); 1915ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 1925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 193204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 1945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 1955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 1965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk mClockModel.stop(AAudio_getNanoseconds(AAUDIO_CLOCK_MONOTONIC)); 1975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSING); 1985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->pauseStream(mServiceStreamHandle); 199204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 200204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2015ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestFlush() { 202204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): flush()"); 2035ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 205204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 2065ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 2075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 2085ed503c7a66c90f93759c90237a9b432dbd93f9fPhil BurksetState(AAUDIO_STREAM_STATE_FLUSHING); 2095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->flushStream(mServiceStreamHandle); 210204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 211204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 212204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::onFlushFromServer() { 213204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): onFlushFromServer()"); 2145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_position_frames_t readCounter = mAudioEndpoint.getDownDataReadCounter(); 2155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_position_frames_t writeCounter = mAudioEndpoint.getDownDataWriteCounter(); 216204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Bump offset so caller does not see the retrograde motion in getFramesRead(). 2175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_position_frames_t framesFlushed = writeCounter - readCounter; 218204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesOffsetFromService += framesFlushed; 219204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Flush written frames by forcing writeCounter to readCounter. 220204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // This is because we cannot move the read counter in the hardware. 221204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataWriteCounter(readCounter); 222204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 223204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStop() 225204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 226204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO better implementation of requestStop() 2275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = requestPause(); 2285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result == AAUDIO_OK) { 2295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_stream_state_t state; 2305ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = waitForStateChange(AAUDIO_STREAM_STATE_PAUSING, 231204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk &state, 2325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk 500 * AAUDIO_NANOS_PER_MILLISECOND);// TODO temporary code 2335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result == AAUDIO_OK) { 234204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = requestFlush(); 235204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 236204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 237204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 238204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 239204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2405ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::registerThread() { 241204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): registerThread()"); 2425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 244204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 2455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 2465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 2475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->registerAudioThread(mServiceStreamHandle, 248204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk gettid(), 249204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk getPeriodNanoseconds()); 250204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 251204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::unregisterThread() { 253204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): unregisterThread()"); 2545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2555ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 256204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 2575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 2585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 2595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->unregisterAudioThread(mServiceStreamHandle, gettid()); 260204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 261204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk// TODO use aaudio_clockid_t all the way down to AudioClock 2635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId, 2645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_position_frames_t *framePosition, 2655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t *timeNanoseconds) { 266204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement using real HAL 2675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t time = AudioClock::getNanoseconds(); 268204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *framePosition = mClockModel.convertTimeToPosition(time); 2695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay 2705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 271204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 272204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2735ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::updateState() { 274204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return processCommands(); 275204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 276204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 277204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 2785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) { 279204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static int64_t oldPosition = 0; 2805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk static aaudio_nanoseconds_t oldTime = 0; 281204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framePosition = command.timestamp.position; 2825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t nanoTime = command.timestamp.timestamp; 283204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu", 284204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) framePosition, 285204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) nanoTime); 286204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t nanosDelta = nanoTime - oldTime; 287204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nanosDelta > 0 && oldTime > 0) { 288204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framesDelta = framePosition - oldPosition; 2895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta; 290204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta); 291204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta); 292204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate); 293204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 294204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldPosition = framePosition; 295204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldTime = nanoTime; 296204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 297204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 298204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) { 3005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_position_frames_t framePosition = 0; 301204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 302204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioStreamInternal_LogTimestamp(command); 303204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 304204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framePosition = message->timestamp.position; 305204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(framePosition, message->timestamp.timestamp); 3065ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 307204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 308204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) { 3105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 311204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got event %d", message->event.event); 312204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message->event.event) { 3135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_STARTED: 3145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_STARTED"); 3155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 316204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_PAUSED: 3185ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_PAUSED"); 3195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSED); 320204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_FLUSHED: 3225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED"); 3235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_FLUSHED); 324204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk onFlushFromServer(); 325204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_CLOSED: 3275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_CLOSED"); 3285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 329204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3305ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_DISCONNECTED: 3315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_DISCONNECTED; 3325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED"); 333204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 334204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 335204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - processCommands() Unrecognized event = %d", 336204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message->event.event); 337204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 338204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 339204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 340204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 341204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 342204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Process all the commands coming from the server. 3435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::processCommands() { 3445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 345204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk while (result == AAUDIO_OK) { 3475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioServiceMessage message; 348204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.readUpCommand(&message) != 1) { 349204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // no command this time, no problem 350204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 351204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message.what) { 3525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::TIMESTAMP: 353204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onTimestampFromServer(&message); 354204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 355204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3565ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::EVENT: 357204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onEventFromServer(&message); 358204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 359204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 360204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 361204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d", 362204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message.what); 3635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_UNEXPECTED_VALUE; 364204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 365204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 366204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 367204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 368204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 369204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 370204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write the data, block if needed and timeoutMillis > 0 3715ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames, 3725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t timeoutNanoseconds) 373204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 3745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 375204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint8_t* source = (uint8_t*)buffer; 3765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t currentTimeNanos = AudioClock::getNanoseconds(); 3775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t deadlineNanos = currentTimeNanos + timeoutNanoseconds; 378204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesLeft = numFrames; 379204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::write(%p, %d) at time %08llu , mState = %d ------------------", 380204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// buffer, numFrames, (unsigned long long) currentTimeNanos, mState); 381204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 382204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write until all the data has been written or until a timeout occurs. 383204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (framesLeft > 0) { 384204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // The call to writeNow() will not block. It will just write as much as it can. 3855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t wakeTimeNanos = 0; 3865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t framesWritten = writeNow(source, framesLeft, 387204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos, &wakeTimeNanos); 388204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::write() writeNow() framesLeft = %d --> framesWritten = %d", framesLeft, framesWritten); 389204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten < 0) { 390204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = framesWritten; 391204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 392204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 393204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesLeft -= (int32_t) framesWritten; 394204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk source += framesWritten * getBytesPerFrame(); 395204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 396204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Should we block? 397204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (timeoutNanoseconds == 0) { 398204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // don't block 399204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else if (framesLeft > 0) { 400204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal:: original wakeTimeNanos %lld", (long long) wakeTimeNanos); 401204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // clip the wake time to something reasonable 402204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos < currentTimeNanos) { 403204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTimeNanos = currentTimeNanos; 404204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 405204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos > deadlineNanos) { 406204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If we time out, just return the framesWritten so far. 407204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal::write(): timed out after %lld nanos", (long long) timeoutNanoseconds); 408204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 409204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 410204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 411204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal:: sleep until %lld, dur = %lld", (long long) wakeTimeNanos, 412204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // (long long) (wakeTimeNanos - currentTimeNanos)); 413204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioClock::sleepForNanos(wakeTimeNanos - currentTimeNanos); 414204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos = AudioClock::getNanoseconds(); 415204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 416204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 417204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 418204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // return error or framesWritten 419204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return (result < 0) ? result : numFrames - framesLeft; 420204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 421204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 422204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write as much data as we can without blocking. 4235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames, 4245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t currentNanoTime, aaudio_nanoseconds_t *wakeTimePtr) { 425204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 4265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = processCommands(); 4275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 428204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 429204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 430204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 431204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 432204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.isOutputFreeRunning()) { 433204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Update data queue based on the timing model. 434204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime); 435204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter); 436204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If the read index passed the write index then consider it an underrun. 437204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.getFullFramesAvailable() < 0) { 438204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mXRunCount++; 439204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 440204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 441204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO else query from endpoint cuz set by actual reader, maybe 442204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 443204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write some data to the buffer. 444204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesWritten = mAudioEndpoint.writeDataNow(buffer, numFrames); 445204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten > 0) { 446204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk incrementFramesWritten(framesWritten); 447204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 448204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d", 449204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // numFrames, framesWritten); 450204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 451204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Calculate an ideal time to wake up. 452204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimePtr != nullptr && framesWritten >= 0) { 453204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // By default wake up a few milliseconds from now. // TODO review 4545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t wakeTime = currentNanoTime + (2 * AAUDIO_NANOS_PER_MILLISECOND); 455204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (getState()) { 4565ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_OPEN: 4575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 458204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten != 0) { 459204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Don't wait to write more data. Just prime the buffer. 460204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = currentNanoTime; 461204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 462204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur? 464204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 465204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint32_t burstSize = mFramesPerBurst; 466204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (burstSize < 32) { 467204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk burstSize = 32; // TODO review 468204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 469204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 470204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize; 471204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = mClockModel.convertPositionToTime(nextReadPosition); 472204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 473204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 474204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 475204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 476204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 477204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *wakeTimePtr = wakeTime; 478204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 479204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 480204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu", 481204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)currentNanoTime, 482204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(), 483204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter()); 484204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesWritten; 485204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 486204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4875ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::waitForStateChange(aaudio_stream_state_t currentState, 4885ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_stream_state_t *nextState, 4895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_nanoseconds_t timeoutNanoseconds) 490204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 491204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 4925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = processCommands(); 493204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - processCommands() returned %d", result); 4945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 495204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 496204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 497204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO replace this polling with a timed sleep on a futex on the message queue 4985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int32_t durationNanos = 5 * AAUDIO_NANOS_PER_MILLISECOND; 4995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_stream_state_t state = getState(); 500204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state); 501204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (state == currentState && timeoutNanoseconds > 0) { 502204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO use futex from service message queue 503204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (durationNanos > timeoutNanoseconds) { 504204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk durationNanos = timeoutNanoseconds; 505204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 506204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioClock::sleepForNanos(durationNanos); 507204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk timeoutNanoseconds -= durationNanos; 508204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 509204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = processCommands(); 5105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 511204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 512204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 513204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 514204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk state = getState(); 515204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state); 516204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 517204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nextState != nullptr) { 518204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *nextState = state; 519204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 5205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK; 521204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 522204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 523204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkvoid AudioStreamInternal::processTimestamp(uint64_t position, aaudio_nanoseconds_t time) { 525204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.processTimestamp( position, time); 526204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 527204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::setBufferSize(aaudio_size_frames_t requestedFrames, 5295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_size_frames_t *actualFrames) { 530204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.setBufferSizeInFrames(requestedFrames, actualFrames); 531204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 532204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_size_frames_t AudioStreamInternal::getBufferSize() const 534204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 535204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferSizeInFrames(); 536204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 537204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_size_frames_t AudioStreamInternal::getBufferCapacity() const 539204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 540204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferCapacityInFrames(); 541204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 542204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_size_frames_t AudioStreamInternal::getFramesPerBurst() const 544204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 545204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 546204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 547204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_position_frames_t AudioStreamInternal::getFramesRead() 549204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 5505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_position_frames_t framesRead = 551204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) 552204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk + mFramesOffsetFromService; 553204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Prevent retrograde motion. 554204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesRead < mLastFramesRead) { 555204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesRead = mLastFramesRead; 556204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 557204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mLastFramesRead = framesRead; 558204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 559204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead); 560204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesRead; 561204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 562204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 563204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement getTimestamp 564