AudioStreamInternal.cpp revision 204a163c86f357a878873fe7d4c4164f3d55c9b6
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> 25204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 26204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include <oboe/OboeAudio.h> 27204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 28204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioClock.h" 29204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioEndpointParcelable.h" 30204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/OboeStreamRequest.h" 31204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/OboeStreamConfiguration.h" 32204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/IOboeAudioService.h" 33204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "binding/OboeServiceMessage.h" 34204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 35204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#include "AudioStreamInternal.h" 36204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 37204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#define LOG_TIMESTAMPS 0 38204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 39204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::String16; 40204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::IServiceManager; 41204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::defaultServiceManager; 42204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing android::interface_cast; 43204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 44204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkusing namespace oboe; 45204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 46204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Helper function to get access to the "OboeAudioService" service. 47204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatic sp<IOboeAudioService> getOboeAudioService() { 48204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk sp<IServiceManager> sm = defaultServiceManager(); 49204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk sp<IBinder> binder = sm->getService(String16("OboeAudioService")); 50204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO: If the "OboeHack" service is not running, getService times out and binder == 0. 51204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk sp<IOboeAudioService> service = interface_cast<IOboeAudioService>(binder); 52204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return service; 53204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 54204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 55204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::AudioStreamInternal() 56204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk : AudioStream() 57204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mClockModel() 58204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mAudioEndpoint() 59204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mServiceStreamHandle(OBOE_HANDLE_INVALID) 60204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk , mFramesPerBurst(16) 61204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 62204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO protect against mService being NULL; 63204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO Model access to the service on frameworks/av/media/libaudioclient/AudioSystem.cpp 64204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mService = getOboeAudioService(); 65204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 66204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 67204a163c86f357a878873fe7d4c4164f3d55c9b6Phil BurkAudioStreamInternal::~AudioStreamInternal() { 68204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 69204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 70204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { 71204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 72204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 73204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk OboeStreamRequest request; 74204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk OboeStreamConfiguration configuration; 75204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 76204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = AudioStream::open(builder); 77204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result < 0) { 78204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 79204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 80204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 81204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Build the request. 82204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setUserId(getuid()); 83204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.setProcessId(getpid()); 84204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setDeviceId(getDeviceId()); 85204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSampleRate(getSampleRate()); 86204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame()); 87204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.getConfiguration().setAudioFormat(getFormat()); 88204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk request.dump(); 89204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 90204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mServiceStreamHandle = mService->openStream(request, configuration); 91204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal.open(): openStream returned mServiceStreamHandle = 0x%08X", 92204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (unsigned int)mServiceStreamHandle); 93204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle < 0) { 94204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = mServiceStreamHandle; 95204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal.open(): acquireRealtimeStream oboe_result_t = 0x%08X", result); 96204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 97204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = configuration.validate(); 98204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_OK) { 99204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk close(); 100204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 101204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 102204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Save results of the open. 103204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSampleRate(configuration.getSampleRate()); 104204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setSamplesPerFrame(configuration.getSamplesPerFrame()); 105204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setFormat(configuration.getAudioFormat()); 106204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 107204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe::AudioEndpointParcelable parcelable; 108204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = mService->getStreamDescription(mServiceStreamHandle, parcelable); 109204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_OK) { 110204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal.open(): getStreamDescriptor returns %d", result); 111204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mService->closeStream(mServiceStreamHandle); 112204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 113204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 114204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // resolve parcelable into a descriptor 115204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk parcelable.resolve(&mEndpointDescriptor); 116204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 117204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Configure endpoint based on descriptor. 118204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.configure(&mEndpointDescriptor); 119204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 120204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 121204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 122204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk assert(mFramesPerBurst >= 16); 123204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk assert(mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames < 10 * 1024); 124204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 125204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setSampleRate(getSampleRate()); 126204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.setFramesPerBurst(mFramesPerBurst); 127204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 128204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_OPEN); 129204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 130204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 131204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 132204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 133204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::close() { 134204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", mServiceStreamHandle); 135204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle != OBOE_HANDLE_INVALID) { 136204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mService->closeStream(mServiceStreamHandle); 137204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mServiceStreamHandle = OBOE_HANDLE_INVALID; 138204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_OK; 139204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 140204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 141204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 142204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 143204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 144204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestStart() 145204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 146204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t startTime; 147204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): start()"); 148204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 149204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 150204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 151204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk startTime = Oboe_getNanoseconds(OBOE_CLOCK_MONOTONIC); 152204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.start(startTime); 153204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(0, startTime); 154204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_STARTING); 155204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mService->startStream(mServiceStreamHandle); 156204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 157204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 158204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestPause() 159204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 160204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): pause()"); 161204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 162204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 163204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 164204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.stop(Oboe_getNanoseconds(OBOE_CLOCK_MONOTONIC)); 165204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_PAUSING); 166204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mService->pauseStream(mServiceStreamHandle); 167204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 168204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 169204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestFlush() { 170204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): flush()"); 171204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 172204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 173204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 174204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_FLUSHING); 175204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mService->flushStream(mServiceStreamHandle); 176204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 177204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 178204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::onFlushFromServer() { 179204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): onFlushFromServer()"); 180204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t readCounter = mAudioEndpoint.getDownDataReadCounter(); 181204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t writeCounter = mAudioEndpoint.getDownDataWriteCounter(); 182204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Bump offset so caller does not see the retrograde motion in getFramesRead(). 183204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t framesFlushed = writeCounter - readCounter; 184204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mFramesOffsetFromService += framesFlushed; 185204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Flush written frames by forcing writeCounter to readCounter. 186204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // This is because we cannot move the read counter in the hardware. 187204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataWriteCounter(readCounter); 188204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 189204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 190204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::requestStop() 191204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 192204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO better implementation of requestStop() 193204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = requestPause(); 194204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result == OBOE_OK) { 195204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_stream_state_t state; 196204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = waitForStateChange(OBOE_STREAM_STATE_PAUSING, 197204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk &state, 198204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 500 * OBOE_NANOS_PER_MILLISECOND);// TODO temporary code 199204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result == OBOE_OK) { 200204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = requestFlush(); 201204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 202204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 203204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 204204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 205204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 206204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::registerThread() { 207204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): registerThread()"); 208204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 209204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 210204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 211204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mService->registerAudioThread(mServiceStreamHandle, 212204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk gettid(), 213204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk getPeriodNanoseconds()); 214204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 215204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 216204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::unregisterThread() { 217204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal(): unregisterThread()"); 218204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mServiceStreamHandle == OBOE_HANDLE_INVALID) { 219204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_ERROR_INVALID_STATE; 220204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 221204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mService->unregisterAudioThread(mServiceStreamHandle, gettid()); 222204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 223204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 224204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO use oboe_clockid_t all the way down to AudioClock 225204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::getTimestamp(clockid_t clockId, 226204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t *framePosition, 227204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t *timeNanoseconds) { 228204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement using real HAL 229204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t time = AudioClock::getNanoseconds(); 230204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *framePosition = mClockModel.convertTimeToPosition(time); 231204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *timeNanoseconds = time + (10 * OBOE_NANOS_PER_MILLISECOND); // Fake hardware delay 232204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_OK; 233204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 234204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 235204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::updateState() { 236204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return processCommands(); 237204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 238204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 239204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 240204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkstatic void AudioStreamInternal_LogTimestamp(OboeServiceMessage &command) { 241204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static int64_t oldPosition = 0; 242204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk static oboe_nanoseconds_t oldTime = 0; 243204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framePosition = command.timestamp.position; 244204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t nanoTime = command.timestamp.timestamp; 245204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu", 246204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) framePosition, 247204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (long long) nanoTime); 248204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t nanosDelta = nanoTime - oldTime; 249204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nanosDelta > 0 && oldTime > 0) { 250204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t framesDelta = framePosition - oldPosition; 251204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t rate = (framesDelta * OBOE_NANOS_PER_SECOND) / nanosDelta; 252204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta); 253204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta); 254204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate); 255204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 256204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldPosition = framePosition; 257204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oldTime = nanoTime; 258204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 259204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 260204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 261204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::onTimestampFromServer(OboeServiceMessage *message) { 262204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t framePosition = 0; 263204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#if LOG_TIMESTAMPS 264204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioStreamInternal_LogTimestamp(command); 265204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk#endif 266204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framePosition = message->timestamp.position; 267204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk processTimestamp(framePosition, message->timestamp.timestamp); 268204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return OBOE_OK; 269204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 270204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 271204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::onEventFromServer(OboeServiceMessage *message) { 272204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 273204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got event %d", message->event.event); 274204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message->event.event) { 275204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_STARTED: 276204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_STARTED"); 277204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_STARTED); 278204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 279204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_PAUSED: 280204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_PAUSED"); 281204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_PAUSED); 282204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 283204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_FLUSHED: 284204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_FLUSHED"); 285204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_FLUSHED); 286204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk onFlushFromServer(); 287204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 288204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_CLOSED: 289204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("processCommands() got OBOE_SERVICE_EVENT_CLOSED"); 290204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk setState(OBOE_STREAM_STATE_CLOSED); 291204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 292204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_SERVICE_EVENT_DISCONNECTED: 293204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = OBOE_ERROR_DISCONNECTED; 294204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - processCommands() OBOE_SERVICE_EVENT_DISCONNECTED"); 295204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 296204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 297204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - processCommands() Unrecognized event = %d", 298204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message->event.event); 299204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 300204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 301204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 302204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 303204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 304204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Process all the commands coming from the server. 305204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::processCommands() { 306204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 307204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 308204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Let the service run in case it is a fake service simulator. 309204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mService->tickle(); // TODO use real service thread 310204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 311204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (result == OBOE_OK) { 312204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk OboeServiceMessage message; 313204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.readUpCommand(&message) != 1) { 314204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // no command this time, no problem 315204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 316204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (message.what) { 317204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OboeServiceMessage::code::TIMESTAMP: 318204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onTimestampFromServer(&message); 319204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 320204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 321204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OboeServiceMessage::code::EVENT: 322204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = onEventFromServer(&message); 323204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 324204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 325204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 326204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGW("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d", 327204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk (int) message.what); 328204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = OBOE_ERROR_UNEXPECTED_VALUE; 329204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 330204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 331204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 332204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 333204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 334204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 335204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write the data, block if needed and timeoutMillis > 0 336204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames, 337204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t timeoutNanoseconds) 338204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 339204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = OBOE_OK; 340204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint8_t* source = (uint8_t*)buffer; 341204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t currentTimeNanos = AudioClock::getNanoseconds(); 342204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t deadlineNanos = currentTimeNanos + timeoutNanoseconds; 343204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesLeft = numFrames; 344204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::write(%p, %d) at time %08llu , mState = %d ------------------", 345204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// buffer, numFrames, (unsigned long long) currentTimeNanos, mState); 346204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 347204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write until all the data has been written or until a timeout occurs. 348204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (framesLeft > 0) { 349204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // The call to writeNow() will not block. It will just write as much as it can. 350204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t wakeTimeNanos = 0; 351204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t framesWritten = writeNow(source, framesLeft, 352204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos, &wakeTimeNanos); 353204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::write() writeNow() framesLeft = %d --> framesWritten = %d", framesLeft, framesWritten); 354204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten < 0) { 355204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = framesWritten; 356204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 357204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 358204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesLeft -= (int32_t) framesWritten; 359204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk source += framesWritten * getBytesPerFrame(); 360204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 361204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Should we block? 362204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (timeoutNanoseconds == 0) { 363204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; // don't block 364204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else if (framesLeft > 0) { 365204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal:: original wakeTimeNanos %lld", (long long) wakeTimeNanos); 366204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // clip the wake time to something reasonable 367204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos < currentTimeNanos) { 368204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTimeNanos = currentTimeNanos; 369204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 370204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimeNanos > deadlineNanos) { 371204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If we time out, just return the framesWritten so far. 372204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGE("AudioStreamInternal::write(): timed out after %lld nanos", (long long) timeoutNanoseconds); 373204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 374204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 375204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 376204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal:: sleep until %lld, dur = %lld", (long long) wakeTimeNanos, 377204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // (long long) (wakeTimeNanos - currentTimeNanos)); 378204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioClock::sleepForNanos(wakeTimeNanos - currentTimeNanos); 379204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk currentTimeNanos = AudioClock::getNanoseconds(); 380204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 381204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 382204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 383204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // return error or framesWritten 384204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return (result < 0) ? result : numFrames - framesLeft; 385204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 386204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 387204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// Write as much data as we can without blocking. 388204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames, 389204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t currentNanoTime, oboe_nanoseconds_t *wakeTimePtr) { 390204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 391204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = processCommands(); 392204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_OK) { 393204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 394204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 395204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 396204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 397204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.isOutputFreeRunning()) { 398204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Update data queue based on the timing model. 399204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime); 400204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter); 401204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // If the read index passed the write index then consider it an underrun. 402204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (mAudioEndpoint.getFullFramesAvailable() < 0) { 403204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mXRunCount++; 404204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 405204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 406204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO else query from endpoint cuz set by actual reader, maybe 407204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 408204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Write some data to the buffer. 409204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t framesWritten = mAudioEndpoint.writeDataNow(buffer, numFrames); 410204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten > 0) { 411204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk incrementFramesWritten(framesWritten); 412204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 413204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk //ALOGD("AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d", 414204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // numFrames, framesWritten); 415204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 416204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Calculate an ideal time to wake up. 417204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (wakeTimePtr != nullptr && framesWritten >= 0) { 418204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // By default wake up a few milliseconds from now. // TODO review 419204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t wakeTime = currentNanoTime + (2 * OBOE_NANOS_PER_MILLISECOND); 420204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk switch (getState()) { 421204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_STREAM_STATE_OPEN: 422204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_STREAM_STATE_STARTING: 423204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesWritten != 0) { 424204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Don't wait to write more data. Just prime the buffer. 425204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = currentNanoTime; 426204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 427204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 428204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk case OBOE_STREAM_STATE_STARTED: // When do we expect the next read burst to occur? 429204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk { 430204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint32_t burstSize = mFramesPerBurst; 431204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (burstSize < 32) { 432204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk burstSize = 32; // TODO review 433204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 434204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 435204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize; 436204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk wakeTime = mClockModel.convertPositionToTime(nextReadPosition); 437204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 438204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 439204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk default: 440204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk break; 441204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 442204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *wakeTimePtr = wakeTime; 443204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 444204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 445204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu", 446204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)currentNanoTime, 447204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(), 448204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter()); 449204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesWritten; 450204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 451204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 452204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::waitForStateChange(oboe_stream_state_t currentState, 453204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_stream_state_t *nextState, 454204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_nanoseconds_t timeoutNanoseconds) 455204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 456204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 457204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_result_t result = processCommands(); 458204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - processCommands() returned %d", result); 459204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_OK) { 460204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 461204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 462204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO replace this polling with a timed sleep on a futex on the message queue 463204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk int32_t durationNanos = 5 * OBOE_NANOS_PER_MILLISECOND; 464204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_stream_state_t state = getState(); 465204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state); 466204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk while (state == currentState && timeoutNanoseconds > 0) { 467204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // TODO use futex from service message queue 468204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (durationNanos > timeoutNanoseconds) { 469204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk durationNanos = timeoutNanoseconds; 470204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 471204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk AudioClock::sleepForNanos(durationNanos); 472204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk timeoutNanoseconds -= durationNanos; 473204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 474204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk result = processCommands(); 475204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (result != OBOE_OK) { 476204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return result; 477204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 478204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 479204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk state = getState(); 480204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state); 481204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 482204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (nextState != nullptr) { 483204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk *nextState = state; 484204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 485204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return (state == currentState) ? OBOE_ERROR_TIMEOUT : OBOE_OK; 486204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 487204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 488204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 489204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkvoid AudioStreamInternal::processTimestamp(uint64_t position, oboe_nanoseconds_t time) { 490204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.processTimestamp( position, time); 491204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 492204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 493204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_result_t AudioStreamInternal::setBufferSize(oboe_size_frames_t requestedFrames, 494204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_size_frames_t *actualFrames) { 495204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.setBufferSizeInFrames(requestedFrames, actualFrames); 496204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 497204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 498204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_size_frames_t AudioStreamInternal::getBufferSize() const 499204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 500204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferSizeInFrames(); 501204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 502204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 503204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_size_frames_t AudioStreamInternal::getBufferCapacity() const 504204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 505204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mAudioEndpoint.getBufferCapacityInFrames(); 506204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 507204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 508204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_size_frames_t AudioStreamInternal::getFramesPerBurst() const 509204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 510204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst; 511204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 512204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 513204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burkoboe_position_frames_t AudioStreamInternal::getFramesRead() 514204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk{ 515204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk oboe_position_frames_t framesRead = 516204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) 517204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk + mFramesOffsetFromService; 518204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk // Prevent retrograde motion. 519204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk if (framesRead < mLastFramesRead) { 520204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk framesRead = mLastFramesRead; 521204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } else { 522204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk mLastFramesRead = framesRead; 523204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk } 524204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk ALOGD("AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead); 525204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk return framesRead; 526204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk} 527204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk 528204a163c86f357a878873fe7d4c4164f3d55c9b6Phil Burk// TODO implement getTimestamp 529