AudioStreamInternal.cpp revision dec33abe3739b2116ef6fbac36f7ca5d26f9d190
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 17204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#define LOG_TAG "OboeAudio" 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 27204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <oboe/OboeAudio.h> 28204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 29204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioClock.h" 30204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioEndpointParcelable.h" 31204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/OboeStreamRequest.h" 32204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/OboeStreamConfiguration.h" 33204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/IOboeAudioService.h" 34204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/OboeServiceMessage.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 46204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing namespace oboe; 47204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 48dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkstatic android::Mutex gServiceLock; 49dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkstatic sp<IOboeAudioService> gOboeService; 50dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 51dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk#define OBOE_SERVICE_NAME "OboeAudioService" 52dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 53204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Helper function to get access to the "OboeAudioService" service. 54dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp 55dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burkstatic const sp<IOboeAudioService> getOboeAudioService() { 56dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk sp<IBinder> binder; 57dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk Mutex::Autolock _l(gServiceLock); 58dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (gOboeService == 0) { 59dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk sp<IServiceManager> sm = defaultServiceManager(); 60dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // Try several times to get the service. 61dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk int retries = 4; 62dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk do { 63dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk binder = sm->getService(String16(OBOE_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. 72dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk gOboeService = interface_cast<IOboeAudioService>(binder); 73dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } else { 74dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk ALOGE("AudioStreamInternal could not get %s", OBOE_SERVICE_NAME); 75dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 76dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 77dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return gOboeService; 78204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 79204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 80204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::AudioStreamInternal() 81204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk : AudioStream() 82204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mClockModel() 83204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mAudioEndpoint() 84204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mServiceStreamHandle(OBOE_HANDLE_INVALID) 85204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mFramesPerBurst(16) 86204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 87204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 88204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 89204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::~AudioStreamInternal() { 90204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 91204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 92204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { 93204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 94dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk const sp<IOboeAudioService>& service = getOboeAudioService(); 95dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (service == 0) return OBOE_ERROR_NO_SERVICE; 96dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 97204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 98204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk OboeStreamRequest request; 99204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk OboeStreamConfiguration 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; 120204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal.open(): acquireRealtimeStream oboe_result_t = 0x%08X", result); 121204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 122204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = configuration.validate(); 123204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_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 132204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe::AudioEndpointParcelable parcelable; 133dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk result = service->getStreamDescription(mServiceStreamHandle, parcelable); 134204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_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 153204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_OPEN); 154204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 155204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 156204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 157204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 158204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::close() { 159204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", mServiceStreamHandle); 160204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle != OBOE_HANDLE_INVALID) { 161dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk oboe_handle_t serviceStreamHandle = mServiceStreamHandle; 162204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mServiceStreamHandle = OBOE_HANDLE_INVALID; 163dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk const sp<IOboeAudioService>& oboeService = getOboeAudioService(); 164dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (oboeService == 0) return OBOE_ERROR_NO_SERVICE; 165dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk oboeService->closeStream(serviceStreamHandle); 166204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_OK; 167204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 168dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return OBOE_ERROR_INVALID_HANDLE; 169204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 170204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 171204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 172204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestStart() 173204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 174204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t startTime; 175204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): start()"); 176204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 177204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 178204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 179dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk const sp<IOboeAudioService>& oboeService = getOboeAudioService(); 180dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (oboeService == 0) return OBOE_ERROR_NO_SERVICE; 181204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk startTime = Oboe_getNanoseconds(OBOE_CLOCK_MONOTONIC); 182204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.start(startTime); 183204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(0, startTime); 184204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_STARTING); 185dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return oboeService->startStream(mServiceStreamHandle); 186204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 187204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 188204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestPause() 189204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 190204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): pause()"); 191204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 192204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 193204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 194dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk const sp<IOboeAudioService>& oboeService = getOboeAudioService(); 195dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (oboeService == 0) return OBOE_ERROR_NO_SERVICE; 196204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.stop(Oboe_getNanoseconds(OBOE_CLOCK_MONOTONIC)); 197204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_PAUSING); 198dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return oboeService->pauseStream(mServiceStreamHandle); 199204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 200204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 201204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestFlush() { 202204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): flush()"); 203204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 204204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 205204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 206dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk const sp<IOboeAudioService>& oboeService = getOboeAudioService(); 207dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (oboeService == 0) return OBOE_ERROR_NO_SERVICE; 208dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil BurksetState(OBOE_STREAM_STATE_FLUSHING); 209dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return oboeService->flushStream(mServiceStreamHandle); 210204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 211204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 212204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::onFlushFromServer() { 213204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): onFlushFromServer()"); 214204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t readCounter = mAudioEndpoint.getDownDataReadCounter(); 215204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t writeCounter = mAudioEndpoint.getDownDataWriteCounter(); 216204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Bump offset so caller does not see the retrograde motion in getFramesRead(). 217204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_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 224204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestStop() 225204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 226204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO better implementation of requestStop() 227204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = requestPause(); 228204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result == OBOE_OK) { 229204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_stream_state_t state; 230204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = waitForStateChange(OBOE_STREAM_STATE_PAUSING, 231204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk &state, 232204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 500 * OBOE_NANOS_PER_MILLISECOND);// TODO temporary code 233204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result == OBOE_OK) { 234204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = requestFlush(); 235204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 236204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 237204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 238204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 239204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 240204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::registerThread() { 241204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): registerThread()"); 242204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 243204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 244204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 245dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk const sp<IOboeAudioService>& oboeService = getOboeAudioService(); 246dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (oboeService == 0) return OBOE_ERROR_NO_SERVICE; 247dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return oboeService->registerAudioThread(mServiceStreamHandle, 248204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk gettid(), 249204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk getPeriodNanoseconds()); 250204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 251204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 252204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::unregisterThread() { 253204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): unregisterThread()"); 254204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 255204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 256204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 257dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk const sp<IOboeAudioService>& oboeService = getOboeAudioService(); 258dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (oboeService == 0) return OBOE_ERROR_NO_SERVICE; 259dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return oboeService->unregisterAudioThread(mServiceStreamHandle, gettid()); 260204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 261204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 262204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO use oboe_clockid_t all the way down to AudioClock 263204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::getTimestamp(clockid_t clockId, 264204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t *framePosition, 265204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t *timeNanoseconds) { 266204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement using real HAL 267204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t time = AudioClock::getNanoseconds(); 268204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *framePosition = mClockModel.convertTimeToPosition(time); 269204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *timeNanoseconds = time + (10 * OBOE_NANOS_PER_MILLISECOND); // Fake hardware delay 270204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_OK; 271204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 272204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 273204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::updateState() { 274204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return processCommands(); 275204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 276204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 277204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 278204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatic void AudioStreamInternal_LogTimestamp(OboeServiceMessage &command) { 279204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static int64_t oldPosition = 0; 280204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static oboe_nanoseconds_t oldTime = 0; 281204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framePosition = command.timestamp.position; 282204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_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; 289204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t rate = (framesDelta * OBOE_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 299204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::onTimestampFromServer(OboeServiceMessage *message) { 300204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_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); 306204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_OK; 307204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 308204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 309204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::onEventFromServer(OboeServiceMessage *message) { 310204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 311204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got event %d", message->event.event); 312204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message->event.event) { 313204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_STARTED: 314204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_STARTED"); 315204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_STARTED); 316204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 317204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_PAUSED: 318204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_PAUSED"); 319204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_PAUSED); 320204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 321204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_FLUSHED: 322204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_FLUSHED"); 323204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_FLUSHED); 324204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk onFlushFromServer(); 325204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 326204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_CLOSED: 327204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_CLOSED"); 328204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_CLOSED); 329204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 330204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_DISCONNECTED: 331204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = OBOE_ERROR_DISCONNECTED; 332204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - processCommands() OBOE_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. 343204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::processCommands() { 344204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 345204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 346204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (result == OBOE_OK) { 347204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk OboeServiceMessage message; 348204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.readUpCommand(&message) != 1) { 349204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // no command this time, no problem 350204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 351204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message.what) { 352204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OboeServiceMessage::code::TIMESTAMP: 353204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onTimestampFromServer(&message); 354204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 355204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 356204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OboeServiceMessage::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); 363204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = OBOE_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 371204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames, 372204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t timeoutNanoseconds) 373204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 374204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 375204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint8_t* source = (uint8_t*)buffer; 376204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t currentTimeNanos = AudioClock::getNanoseconds(); 377204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_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. 385204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t wakeTimeNanos = 0; 386204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_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. 423204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames, 424204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t currentNanoTime, oboe_nanoseconds_t *wakeTimePtr) { 425204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 426204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = processCommands(); 427204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_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 454204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t wakeTime = currentNanoTime + (2 * OBOE_NANOS_PER_MILLISECOND); 455204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (getState()) { 456204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_STREAM_STATE_OPEN: 457204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_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; 463204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_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 487204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::waitForStateChange(oboe_stream_state_t currentState, 488204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_stream_state_t *nextState, 489204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t timeoutNanoseconds) 490204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 491204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 492204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = processCommands(); 493204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - processCommands() returned %d", result); 494204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_OK) { 495204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 496204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 497204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO replace this polling with a timed sleep on a futex on the message queue 498204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t durationNanos = 5 * OBOE_NANOS_PER_MILLISECOND; 499204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_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(); 510204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_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 } 520204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return (state == currentState) ? OBOE_ERROR_TIMEOUT : OBOE_OK; 521204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 522204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 523204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 524204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::processTimestamp(uint64_t position, oboe_nanoseconds_t time) { 525204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.processTimestamp( position, time); 526204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 527204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 528204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::setBufferSize(oboe_size_frames_t requestedFrames, 529204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_size_frames_t *actualFrames) { 530204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.setBufferSizeInFrames(requestedFrames, actualFrames); 531204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 532204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 533204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_size_frames_t AudioStreamInternal::getBufferSize() const 534204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 535204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferSizeInFrames(); 536204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 537204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 538204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_size_frames_t AudioStreamInternal::getBufferCapacity() const 539204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 540204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferCapacityInFrames(); 541204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 542204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 543204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_size_frames_t AudioStreamInternal::getFramesPerBurst() const 544204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 545204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 546204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 547204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 548204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_position_frames_t AudioStreamInternal::getFramesRead() 549204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 550204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_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