AudioStreamInternal.cpp revision 3316d5e6d375a4f09c681205e9094d30a0bfc4a2
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 363df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk#include "core/AudioStreamBuilder.h" 37204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioStreamInternal.h" 38204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 39204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#define LOG_TIMESTAMPS 0 40204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 41204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::String16; 42204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::IServiceManager; 43204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::defaultServiceManager; 44204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::interface_cast; 45dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkusing android::Mutex; 46204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 48204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 49dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkstatic android::Mutex gServiceLock; 505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic sp<IAAudioService> gAAudioService; 51dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#define AAUDIO_SERVICE_NAME "AAudioService" 53dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk// Helper function to get access to the "AAudioService" service. 55dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp 565ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic const sp<IAAudioService> getAAudioService() { 57dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk sp<IBinder> binder; 58dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk Mutex::Autolock _l(gServiceLock); 595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (gAAudioService == 0) { 60dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk sp<IServiceManager> sm = defaultServiceManager(); 61dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // Try several times to get the service. 62dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk int retries = 4; 63dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk do { 645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while. 65dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (binder != 0) { 66dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 67dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 68dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } while (retries-- > 0); 69dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 70dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (binder != 0) { 71dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // TODO Add linkToDeath() like in frameworks/av/media/libaudioclient/AudioSystem.cpp 72dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // TODO Create a DeathRecipient that disconnects all active streams. 735ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk gAAudioService = interface_cast<IAAudioService>(binder); 74dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } else { 755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGE("AudioStreamInternal could not get %s", AAUDIO_SERVICE_NAME); 76dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 77dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return gAAudioService; 79204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 80204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 81204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::AudioStreamInternal() 82204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk : AudioStream() 83204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mClockModel() 84204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mAudioEndpoint() 855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk , mServiceStreamHandle(AAUDIO_HANDLE_INVALID) 86204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mFramesPerBurst(16) 87204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 88204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 89204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 90204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::~AudioStreamInternal() { 91204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 92204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { 94204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& service = getAAudioService(); 965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 97dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamRequest request; 1005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioStreamConfiguration configuration; 101204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 102204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = AudioStream::open(builder); 103204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result < 0) { 104204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 105204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 106204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 107dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // Build the request to send to the server. 108204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setUserId(getuid()); 109204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setProcessId(getpid()); 110204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setDeviceId(getDeviceId()); 111204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSampleRate(getSampleRate()); 112204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame()); 113204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setAudioFormat(getFormat()); 1143df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk request.getConfiguration().setBufferCapacity(builder.getBufferCapacity()); 115204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.dump(); 116204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 117dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk mServiceStreamHandle = service->openStream(request, configuration); 118204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal.open(): openStream returned mServiceStreamHandle = 0x%08X", 119204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (unsigned int)mServiceStreamHandle); 120204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle < 0) { 121204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = mServiceStreamHandle; 1225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGE("AudioStreamInternal.open(): acquireRealtimeStream aaudio_result_t = 0x%08X", result); 123204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 124204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = configuration.validate(); 1255ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 126204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk close(); 127204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 128204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 129204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Save results of the open. 130204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSampleRate(configuration.getSampleRate()); 131204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSamplesPerFrame(configuration.getSamplesPerFrame()); 132204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setFormat(configuration.getAudioFormat()); 133204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio::AudioEndpointParcelable parcelable; 135dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk result = service->getStreamDescription(mServiceStreamHandle, parcelable); 1365ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 137204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal.open(): getStreamDescriptor returns %d", result); 138dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk service->closeStream(mServiceStreamHandle); 139204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 140204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 141204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // resolve parcelable into a descriptor 142204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk parcelable.resolve(&mEndpointDescriptor); 143204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 144204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Configure endpoint based on descriptor. 145204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.configure(&mEndpointDescriptor); 146204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 147204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 148204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk assert(mFramesPerBurst >= 16); 149204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk assert(mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames < 10 * 1024); 150204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 151204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setSampleRate(getSampleRate()); 152204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setFramesPerBurst(mFramesPerBurst); 153204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 155204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 156204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 157204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 158204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::close() { 160204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", mServiceStreamHandle); 1615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { 1625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; 1635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk mServiceStreamHandle = AAUDIO_HANDLE_INVALID; 1645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 1655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 1665ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudioService->closeStream(serviceStreamHandle); 1675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 168204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 1695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_HANDLE; 170204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 171204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 172204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1735ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStart() 174204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 1753316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t startTime; 176204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): start()"); 1775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 1785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 179204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 1805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 1815ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 1823316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk startTime = AudioClock::getNanoseconds(); 183204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.start(startTime); 184204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(0, startTime); 1855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 1865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->startStream(mServiceStreamHandle); 187204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 188204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 1895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestPause() 190204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 191204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): pause()"); 1925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 1935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 194204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 1955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 1965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 1973316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk mClockModel.stop(AudioClock::getNanoseconds()); 1985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSING); 1995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->pauseStream(mServiceStreamHandle); 200204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 201204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestFlush() { 203204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): flush()"); 2045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 206204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 2075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 2085ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 2095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil BurksetState(AAUDIO_STREAM_STATE_FLUSHING); 2105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->flushStream(mServiceStreamHandle); 211204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 212204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 213204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::onFlushFromServer() { 214204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): onFlushFromServer()"); 2153316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t readCounter = mAudioEndpoint.getDownDataReadCounter(); 2163316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t writeCounter = mAudioEndpoint.getDownDataWriteCounter(); 217204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Bump offset so caller does not see the retrograde motion in getFramesRead(). 2183316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framesFlushed = writeCounter - readCounter; 219204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesOffsetFromService += framesFlushed; 220204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Flush written frames by forcing writeCounter to readCounter. 221204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // This is because we cannot move the read counter in the hardware. 222204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataWriteCounter(readCounter); 223204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 224204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2255ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::requestStop() 226204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 227204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO better implementation of requestStop() 2285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = requestPause(); 2295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result == AAUDIO_OK) { 2305ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_stream_state_t state; 2315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = waitForStateChange(AAUDIO_STREAM_STATE_PAUSING, 232204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk &state, 2335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk 500 * AAUDIO_NANOS_PER_MILLISECOND);// TODO temporary code 2345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result == AAUDIO_OK) { 235204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = requestFlush(); 236204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 237204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 238204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 239204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 240204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::registerThread() { 242204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): registerThread()"); 2435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 245204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 2465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 2475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 2485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->registerAudioThread(mServiceStreamHandle, 249204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk gettid(), 250204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk getPeriodNanoseconds()); 251204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 252204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::unregisterThread() { 254204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): unregisterThread()"); 2555ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { 2565ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 257204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 2585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const sp<IAAudioService>& aaudioService = getAAudioService(); 2595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE; 2605ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioService->unregisterAudioThread(mServiceStreamHandle, gettid()); 261204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 262204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk// TODO use aaudio_clockid_t all the way down to AudioClock 2645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId, 2653316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t *framePosition, 2663316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t *timeNanoseconds) { 267204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement using real HAL 2683316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t time = AudioClock::getNanoseconds(); 269204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *framePosition = mClockModel.convertTimeToPosition(time); 2705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay 2715ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 272204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 273204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 2745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::updateState() { 275204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return processCommands(); 276204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 277204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 278204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 2795ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatic void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) { 280204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static int64_t oldPosition = 0; 2813316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk static int64_t oldTime = 0; 282204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framePosition = command.timestamp.position; 2833316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t nanoTime = command.timestamp.timestamp; 284204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu", 285204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) framePosition, 286204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) nanoTime); 287204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t nanosDelta = nanoTime - oldTime; 288204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nanosDelta > 0 && oldTime > 0) { 289204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framesDelta = framePosition - oldPosition; 2905ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta; 291204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta); 292204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta); 293204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate); 294204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 295204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldPosition = framePosition; 296204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldTime = nanoTime; 297204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 298204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 299204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) { 3013316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framePosition = 0; 302204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 303204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioStreamInternal_LogTimestamp(command); 304204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 305204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framePosition = message->timestamp.position; 306204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(framePosition, message->timestamp.timestamp); 3075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 308204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 309204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) { 3115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 312204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got event %d", message->event.event); 313204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message->event.event) { 3145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_STARTED: 3155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_STARTED"); 3165ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 317204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3185ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_PAUSED: 3195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_PAUSED"); 3205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSED); 321204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_FLUSHED: 3235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED"); 3245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_FLUSHED); 325204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk onFlushFromServer(); 326204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_CLOSED: 3285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_CLOSED"); 3295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 330204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 3315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_SERVICE_EVENT_DISCONNECTED: 3325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_DISCONNECTED; 3335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED"); 334204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 335204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 336204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - processCommands() Unrecognized event = %d", 337204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message->event.event); 338204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 339204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 340204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 341204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 342204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 343204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Process all the commands coming from the server. 3445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::processCommands() { 3455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 346204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk while (result == AAUDIO_OK) { 3485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk AAudioServiceMessage message; 349204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.readUpCommand(&message) != 1) { 350204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // no command this time, no problem 351204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 352204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message.what) { 3535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::TIMESTAMP: 354204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onTimestampFromServer(&message); 355204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 356204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 3575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAudioServiceMessage::code::EVENT: 358204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onEventFromServer(&message); 359204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 360204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 361204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 362204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d", 363204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message.what); 3645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_UNEXPECTED_VALUE; 365204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 366204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 367204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 368204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 369204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 370204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 371204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write the data, block if needed and timeoutMillis > 0 3725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames, 3733316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 374204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 3755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 376204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint8_t* source = (uint8_t*)buffer; 3773316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t currentTimeNanos = AudioClock::getNanoseconds(); 3783316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds; 379204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesLeft = numFrames; 380204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::write(%p, %d) at time %08llu , mState = %d ------------------", 381204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// buffer, numFrames, (unsigned long long) currentTimeNanos, mState); 382204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 383204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write until all the data has been written or until a timeout occurs. 384204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (framesLeft > 0) { 385204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // The call to writeNow() will not block. It will just write as much as it can. 3863316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t wakeTimeNanos = 0; 3875ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t framesWritten = writeNow(source, framesLeft, 388204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos, &wakeTimeNanos); 389204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::write() writeNow() framesLeft = %d --> framesWritten = %d", framesLeft, framesWritten); 390204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten < 0) { 391204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = framesWritten; 392204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 393204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 394204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesLeft -= (int32_t) framesWritten; 395204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk source += framesWritten * getBytesPerFrame(); 396204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 397204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Should we block? 398204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (timeoutNanoseconds == 0) { 399204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // don't block 400204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else if (framesLeft > 0) { 401204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal:: original wakeTimeNanos %lld", (long long) wakeTimeNanos); 402204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // clip the wake time to something reasonable 403204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos < currentTimeNanos) { 404204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTimeNanos = currentTimeNanos; 405204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 406204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos > deadlineNanos) { 407204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If we time out, just return the framesWritten so far. 408204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal::write(): timed out after %lld nanos", (long long) timeoutNanoseconds); 409204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 410204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 411204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 412204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal:: sleep until %lld, dur = %lld", (long long) wakeTimeNanos, 413204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // (long long) (wakeTimeNanos - currentTimeNanos)); 414204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioClock::sleepForNanos(wakeTimeNanos - currentTimeNanos); 415204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos = AudioClock::getNanoseconds(); 416204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 417204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 418204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 419204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // return error or framesWritten 420204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return (result < 0) ? result : numFrames - framesLeft; 421204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 422204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 423204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write as much data as we can without blocking. 4245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames, 4253316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t currentNanoTime, int64_t *wakeTimePtr) { 426204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 4275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = processCommands(); 4285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 429204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 430204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 431204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 432204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 433204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.isOutputFreeRunning()) { 434204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Update data queue based on the timing model. 435204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime); 436204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter); 437204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If the read index passed the write index then consider it an underrun. 438204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.getFullFramesAvailable() < 0) { 439204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mXRunCount++; 440204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 441204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 442204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO else query from endpoint cuz set by actual reader, maybe 443204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 444204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write some data to the buffer. 445204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesWritten = mAudioEndpoint.writeDataNow(buffer, numFrames); 446204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten > 0) { 447204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk incrementFramesWritten(framesWritten); 448204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 449204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d", 450204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // numFrames, framesWritten); 451204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 452204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Calculate an ideal time to wake up. 453204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimePtr != nullptr && framesWritten >= 0) { 454204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // By default wake up a few milliseconds from now. // TODO review 4553316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t wakeTime = currentNanoTime + (2 * AAUDIO_NANOS_PER_MILLISECOND); 456204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (getState()) { 4575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_OPEN: 4585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 459204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten != 0) { 460204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Don't wait to write more data. Just prime the buffer. 461204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = currentNanoTime; 462204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 463204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 4645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur? 465204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 466204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint32_t burstSize = mFramesPerBurst; 467204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (burstSize < 32) { 468204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk burstSize = 32; // TODO review 469204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 470204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 471204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize; 472204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = mClockModel.convertPositionToTime(nextReadPosition); 473204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 474204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 475204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 476204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 477204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 478204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *wakeTimePtr = wakeTime; 479204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 480204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 481204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu", 482204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)currentNanoTime, 483204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(), 484204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter()); 485204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesWritten; 486204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 487204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 4885ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamInternal::waitForStateChange(aaudio_stream_state_t currentState, 4895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_stream_state_t *nextState, 4903316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 491204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 492204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 4935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = processCommands(); 494204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - processCommands() returned %d", result); 4955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 496204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 497204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 498204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO replace this polling with a timed sleep on a futex on the message queue 4995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int32_t durationNanos = 5 * AAUDIO_NANOS_PER_MILLISECOND; 5005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_stream_state_t state = getState(); 501204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state); 502204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (state == currentState && timeoutNanoseconds > 0) { 503204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO use futex from service message queue 504204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (durationNanos > timeoutNanoseconds) { 505204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk durationNanos = timeoutNanoseconds; 506204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 507204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioClock::sleepForNanos(durationNanos); 508204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk timeoutNanoseconds -= durationNanos; 509204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 510204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = processCommands(); 5115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 512204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 513204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 514204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 515204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk state = getState(); 516204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state); 517204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 518204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nextState != nullptr) { 519204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *nextState = state; 520204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 5215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK; 522204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 523204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 524204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5253316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkvoid AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) { 526204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.processTimestamp( position, time); 527204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 528204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5293316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) { 5303316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t actualFrames = 0; 5313316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames); 5323316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk if (result < 0) { 5333316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return result; 5343316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk } else { 5353316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return (aaudio_result_t) actualFrames; 5363316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk } 537204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 538204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5393316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getBufferSize() const 540204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 541204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferSizeInFrames(); 542204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 543204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5443316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getBufferCapacity() const 545204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 546204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferCapacityInFrames(); 547204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 548204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5493316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamInternal::getFramesPerBurst() const 550204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 551204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 552204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 553204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 5543316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint64_t AudioStreamInternal::getFramesRead() 555204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 5563316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t framesRead = 557204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) 558204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk + mFramesOffsetFromService; 559204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Prevent retrograde motion. 560204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesRead < mLastFramesRead) { 561204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesRead = mLastFramesRead; 562204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 563204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mLastFramesRead = framesRead; 564204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 565204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead); 566204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesRead; 567204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 568204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 569204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement getTimestamp 570