blob: af4b93a7e39affbc07dd248d0f916103578a6d39 [file] [log] [blame]
Phil Burk204a1632017-01-03 17:23:43 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Phil Burk5ed503c2017-02-01 09:38:15 -080017#define LOG_TAG "AAudio"
Phil Burk204a1632017-01-03 17:23:43 -080018//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
Phil Burkc0c70e32017-02-09 13:18:38 -080021#include <stdint.h>
Phil Burk204a1632017-01-03 17:23:43 -080022#include <assert.h>
23
24#include <binder/IServiceManager.h>
25
Phil Burk5ed503c2017-02-01 09:38:15 -080026#include <aaudio/AAudio.h>
Phil Burke4d7bb42017-03-28 11:32:39 -070027#include <utils/String16.h>
Phil Burk204a1632017-01-03 17:23:43 -080028
Phil Burkc0c70e32017-02-09 13:18:38 -080029#include "AudioClock.h"
30#include "AudioEndpointParcelable.h"
31#include "binding/AAudioStreamRequest.h"
32#include "binding/AAudioStreamConfiguration.h"
33#include "binding/IAAudioService.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080034#include "binding/AAudioServiceMessage.h"
Phil Burkc0c70e32017-02-09 13:18:38 -080035#include "fifo/FifoBuffer.h"
Phil Burk204a1632017-01-03 17:23:43 -080036
Phil Burk3df348f2017-02-08 11:41:55 -080037#include "core/AudioStreamBuilder.h"
Phil Burkc0c70e32017-02-09 13:18:38 -080038#include "AudioStreamInternal.h"
Phil Burk204a1632017-01-03 17:23:43 -080039
40#define LOG_TIMESTAMPS 0
41
42using android::String16;
Phil Burkdec33ab2017-01-17 14:48:16 -080043using android::Mutex;
Phil Burkc0c70e32017-02-09 13:18:38 -080044using android::WrappingBuffer;
Phil Burk204a1632017-01-03 17:23:43 -080045
Phil Burk5ed503c2017-02-01 09:38:15 -080046using namespace aaudio;
Phil Burk204a1632017-01-03 17:23:43 -080047
Phil Burke4d7bb42017-03-28 11:32:39 -070048#define MIN_TIMEOUT_NANOS (1000 * AAUDIO_NANOS_PER_MILLISECOND)
49
50// Wait at least this many times longer than the operation should take.
51#define MIN_TIMEOUT_OPERATIONS 4
52
Phil Burk71f35bb2017-04-13 16:05:07 -070053//static int64_t s_logCounter = 0;
54//#define MYLOG_CONDITION (mInService == true && s_logCounter++ < 500)
55//#define MYLOG_CONDITION (s_logCounter++ < 500000)
56#define MYLOG_CONDITION (1)
Phil Burkdec33ab2017-01-17 14:48:16 -080057
Phil Burkc0c70e32017-02-09 13:18:38 -080058AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface &serviceInterface, bool inService)
Phil Burk204a1632017-01-03 17:23:43 -080059 : AudioStream()
60 , mClockModel()
61 , mAudioEndpoint()
Phil Burk5ed503c2017-02-01 09:38:15 -080062 , mServiceStreamHandle(AAUDIO_HANDLE_INVALID)
Phil Burk204a1632017-01-03 17:23:43 -080063 , mFramesPerBurst(16)
Phil Burkc0c70e32017-02-09 13:18:38 -080064 , mServiceInterface(serviceInterface)
Phil Burk71f35bb2017-04-13 16:05:07 -070065 , mInService(inService) {
Phil Burk204a1632017-01-03 17:23:43 -080066}
67
68AudioStreamInternal::~AudioStreamInternal() {
69}
70
Phil Burk5ed503c2017-02-01 09:38:15 -080071aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
Phil Burk204a1632017-01-03 17:23:43 -080072
Phil Burk5ed503c2017-02-01 09:38:15 -080073 aaudio_result_t result = AAUDIO_OK;
74 AAudioStreamRequest request;
75 AAudioStreamConfiguration configuration;
Phil Burk204a1632017-01-03 17:23:43 -080076
77 result = AudioStream::open(builder);
78 if (result < 0) {
79 return result;
80 }
81
Phil Burkc0c70e32017-02-09 13:18:38 -080082 // We have to do volume scaling. So we prefer FLOAT format.
83 if (getFormat() == AAUDIO_UNSPECIFIED) {
84 setFormat(AAUDIO_FORMAT_PCM_FLOAT);
85 }
Phil Burk71f35bb2017-04-13 16:05:07 -070086 // Request FLOAT for the shared mixer.
87 request.getConfiguration().setAudioFormat(AAUDIO_FORMAT_PCM_FLOAT);
Phil Burkc0c70e32017-02-09 13:18:38 -080088
Phil Burkdec33ab2017-01-17 14:48:16 -080089 // Build the request to send to the server.
Phil Burk204a1632017-01-03 17:23:43 -080090 request.setUserId(getuid());
91 request.setProcessId(getpid());
Phil Burkc0c70e32017-02-09 13:18:38 -080092 request.setDirection(getDirection());
Phil Burk71f35bb2017-04-13 16:05:07 -070093 request.setSharingModeMatchRequired(isSharingModeMatchRequired());
Phil Burkc0c70e32017-02-09 13:18:38 -080094
Phil Burk204a1632017-01-03 17:23:43 -080095 request.getConfiguration().setDeviceId(getDeviceId());
96 request.getConfiguration().setSampleRate(getSampleRate());
97 request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame());
Phil Burk71f35bb2017-04-13 16:05:07 -070098 request.getConfiguration().setSharingMode(getSharingMode());
99
Phil Burk3df348f2017-02-08 11:41:55 -0800100 request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
Phil Burk204a1632017-01-03 17:23:43 -0800101
Phil Burkc0c70e32017-02-09 13:18:38 -0800102 mServiceStreamHandle = mServiceInterface.openStream(request, configuration);
Phil Burk204a1632017-01-03 17:23:43 -0800103 if (mServiceStreamHandle < 0) {
104 result = mServiceStreamHandle;
Phil Burk71f35bb2017-04-13 16:05:07 -0700105 ALOGE("AudioStreamInternal.open(): %s openStream() returned %d", getLocationName(), result);
Phil Burk204a1632017-01-03 17:23:43 -0800106 } else {
107 result = configuration.validate();
Phil Burk5ed503c2017-02-01 09:38:15 -0800108 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800109 close();
110 return result;
111 }
112 // Save results of the open.
113 setSampleRate(configuration.getSampleRate());
114 setSamplesPerFrame(configuration.getSamplesPerFrame());
Phil Burkc0c70e32017-02-09 13:18:38 -0800115 setDeviceId(configuration.getDeviceId());
Phil Burk204a1632017-01-03 17:23:43 -0800116
Phil Burkc0c70e32017-02-09 13:18:38 -0800117 // Save device format so we can do format conversion and volume scaling together.
118 mDeviceFormat = configuration.getAudioFormat();
119
120 result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable);
Phil Burk5ed503c2017-02-01 09:38:15 -0800121 if (result != AAUDIO_OK) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700122 ALOGE("AudioStreamInternal.open(): %s getStreamDescriptor returns %d",
123 getLocationName(), result);
Phil Burkc0c70e32017-02-09 13:18:38 -0800124 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800125 return result;
126 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800127
Phil Burk204a1632017-01-03 17:23:43 -0800128 // resolve parcelable into a descriptor
Phil Burkc0c70e32017-02-09 13:18:38 -0800129 result = mEndPointParcelable.resolve(&mEndpointDescriptor);
130 if (result != AAUDIO_OK) {
131 ALOGE("AudioStreamInternal.open(): resolve() returns %d", result);
132 mServiceInterface.closeStream(mServiceStreamHandle);
133 return result;
134 }
Phil Burk204a1632017-01-03 17:23:43 -0800135
136 // Configure endpoint based on descriptor.
137 mAudioEndpoint.configure(&mEndpointDescriptor);
138
Phil Burk204a1632017-01-03 17:23:43 -0800139 mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
Phil Burk71f35bb2017-04-13 16:05:07 -0700140 int32_t capacity = mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames;
141
142 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.open() %s framesPerBurst = %d, capacity = %d",
143 getLocationName(), mFramesPerBurst, capacity);
144 // Validate result from server.
145 if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) {
146 ALOGE("AudioStream::open(): framesPerBurst out of range = %d", mFramesPerBurst);
147 return AAUDIO_ERROR_OUT_OF_RANGE;
148 }
149 if (capacity < mFramesPerBurst || capacity > 32 * 1024) {
150 ALOGE("AudioStream::open(): bufferCapacity out of range = %d", capacity);
151 return AAUDIO_ERROR_OUT_OF_RANGE;
152 }
Phil Burk204a1632017-01-03 17:23:43 -0800153
154 mClockModel.setSampleRate(getSampleRate());
155 mClockModel.setFramesPerBurst(mFramesPerBurst);
156
Phil Burke4d7bb42017-03-28 11:32:39 -0700157 if (getDataCallbackProc()) {
158 mCallbackFrames = builder.getFramesPerDataCallback();
159 if (mCallbackFrames > getBufferCapacity() / 2) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700160 ALOGE("AudioStreamInternal.open(): framesPerCallback too large = %d, capacity = %d",
161 mCallbackFrames, getBufferCapacity());
Phil Burkc0c70e32017-02-09 13:18:38 -0800162 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700163 return AAUDIO_ERROR_OUT_OF_RANGE;
164
165 } else if (mCallbackFrames < 0) {
166 ALOGE("AudioStreamInternal.open(): framesPerCallback negative");
Phil Burkc0c70e32017-02-09 13:18:38 -0800167 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700168 return AAUDIO_ERROR_OUT_OF_RANGE;
169
170 }
171 if (mCallbackFrames == AAUDIO_UNSPECIFIED) {
172 mCallbackFrames = mFramesPerBurst;
173 }
174
175 int32_t bytesPerFrame = getSamplesPerFrame()
176 * AAudioConvert_formatToSizeInBytes(getFormat());
177 int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame;
178 mCallbackBuffer = new uint8_t[callbackBufferSize];
179 }
180
Phil Burk5ed503c2017-02-01 09:38:15 -0800181 setState(AAUDIO_STREAM_STATE_OPEN);
Phil Burk204a1632017-01-03 17:23:43 -0800182 }
183 return result;
184}
185
Phil Burk5ed503c2017-02-01 09:38:15 -0800186aaudio_result_t AudioStreamInternal::close() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700187 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X",
188 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800189 if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
190 aaudio_handle_t serviceStreamHandle = mServiceStreamHandle;
191 mServiceStreamHandle = AAUDIO_HANDLE_INVALID;
Phil Burkc0c70e32017-02-09 13:18:38 -0800192
193 mServiceInterface.closeStream(serviceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700194 delete[] mCallbackBuffer;
Phil Burkc0c70e32017-02-09 13:18:38 -0800195 return mEndPointParcelable.close();
Phil Burk204a1632017-01-03 17:23:43 -0800196 } else {
Phil Burk5ed503c2017-02-01 09:38:15 -0800197 return AAUDIO_ERROR_INVALID_HANDLE;
Phil Burk204a1632017-01-03 17:23:43 -0800198 }
199}
200
Phil Burkc0c70e32017-02-09 13:18:38 -0800201
Phil Burke4d7bb42017-03-28 11:32:39 -0700202// Render audio in the application callback and then write the data to the stream.
203void *AudioStreamInternal::callbackLoop() {
204 aaudio_result_t result = AAUDIO_OK;
205 aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE;
Phil Burke4d7bb42017-03-28 11:32:39 -0700206 AAudioStream_dataCallback appCallback = getDataCallbackProc();
207 if (appCallback == nullptr) return NULL;
208
Phil Burk677d7912017-04-07 12:17:12 -0700209 // result might be a frame count
210 while (mCallbackEnabled.load() && isPlaying() && (result >= 0)) {
Phil Burke4d7bb42017-03-28 11:32:39 -0700211 // Call application using the AAudio callback interface.
212 callbackResult = (*appCallback)(
213 (AAudioStream *) this,
214 getDataCallbackUserData(),
215 mCallbackBuffer,
216 mCallbackFrames);
217
218 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
Phil Burk677d7912017-04-07 12:17:12 -0700219 // Write audio data to stream.
Phil Burke4d7bb42017-03-28 11:32:39 -0700220 int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames);
Phil Burk677d7912017-04-07 12:17:12 -0700221
222 // This is a BLOCKING WRITE!
Phil Burke4d7bb42017-03-28 11:32:39 -0700223 result = write(mCallbackBuffer, mCallbackFrames, timeoutNanos);
Phil Burk677d7912017-04-07 12:17:12 -0700224 if ((result != mCallbackFrames)) {
225 ALOGE("AudioStreamInternal(): callbackLoop: write() returned %d", result);
226 if (result >= 0) {
227 // Only wrote some of the frames requested. Must have timed out.
228 result = AAUDIO_ERROR_TIMEOUT;
229 }
Phil Burke4d7bb42017-03-28 11:32:39 -0700230 if (getErrorCallbackProc() != nullptr) {
Phil Burke4d7bb42017-03-28 11:32:39 -0700231 (*getErrorCallbackProc())(
232 (AAudioStream *) this,
233 getErrorCallbackUserData(),
Phil Burk677d7912017-04-07 12:17:12 -0700234 result);
Phil Burke4d7bb42017-03-28 11:32:39 -0700235 }
236 break;
Phil Burke4d7bb42017-03-28 11:32:39 -0700237 }
238 } else if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
Phil Burk677d7912017-04-07 12:17:12 -0700239 ALOGD("AudioStreamInternal(): callback returned AAUDIO_CALLBACK_RESULT_STOP");
Phil Burke4d7bb42017-03-28 11:32:39 -0700240 break;
241 }
242 }
243
Phil Burk677d7912017-04-07 12:17:12 -0700244 ALOGD("AudioStreamInternal(): callbackLoop() exiting, result = %d, isPlaying() = %d",
Phil Burke4d7bb42017-03-28 11:32:39 -0700245 result, (int) isPlaying());
246 return NULL; // TODO review
247}
248
249static void *aaudio_callback_thread_proc(void *context)
250{
251 AudioStreamInternal *stream = (AudioStreamInternal *)context;
Phil Burk677d7912017-04-07 12:17:12 -0700252 //LOGD("AudioStreamInternal(): oboe_callback_thread, stream = %p", stream);
Phil Burke4d7bb42017-03-28 11:32:39 -0700253 if (stream != NULL) {
254 return stream->callbackLoop();
255 } else {
256 return NULL;
257 }
258}
259
Phil Burk5ed503c2017-02-01 09:38:15 -0800260aaudio_result_t AudioStreamInternal::requestStart()
Phil Burk204a1632017-01-03 17:23:43 -0800261{
Phil Burk3316d5e2017-02-15 11:23:01 -0800262 int64_t startTime;
Phil Burk71f35bb2017-04-13 16:05:07 -0700263 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): start()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800264 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
265 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800266 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800267
Phil Burk3316d5e2017-02-15 11:23:01 -0800268 startTime = AudioClock::getNanoseconds();
Phil Burk204a1632017-01-03 17:23:43 -0800269 mClockModel.start(startTime);
270 processTimestamp(0, startTime);
Phil Burk5ed503c2017-02-01 09:38:15 -0800271 setState(AAUDIO_STREAM_STATE_STARTING);
Phil Burkc0c70e32017-02-09 13:18:38 -0800272 aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);;
Phil Burke4d7bb42017-03-28 11:32:39 -0700273
274 if (result == AAUDIO_OK && getDataCallbackProc() != nullptr) {
275 // Launch the callback loop thread.
276 int64_t periodNanos = mCallbackFrames
277 * AAUDIO_NANOS_PER_SECOND
278 / getSampleRate();
279 mCallbackEnabled.store(true);
280 result = createThread(periodNanos, aaudio_callback_thread_proc, this);
281 }
282 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800283}
284
Phil Burke4d7bb42017-03-28 11:32:39 -0700285int64_t AudioStreamInternal::calculateReasonableTimeout(int32_t framesPerOperation) {
286
287 // Wait for at least a second or some number of callbacks to join the thread.
Phil Burk71f35bb2017-04-13 16:05:07 -0700288 int64_t timeoutNanoseconds = (MIN_TIMEOUT_OPERATIONS
289 * framesPerOperation
290 * AAUDIO_NANOS_PER_SECOND)
291 / getSampleRate();
Phil Burke4d7bb42017-03-28 11:32:39 -0700292 if (timeoutNanoseconds < MIN_TIMEOUT_NANOS) { // arbitrary number of seconds
293 timeoutNanoseconds = MIN_TIMEOUT_NANOS;
294 }
295 return timeoutNanoseconds;
296}
297
298aaudio_result_t AudioStreamInternal::stopCallback()
299{
300 if (isDataCallbackActive()) {
301 mCallbackEnabled.store(false);
302 return joinThread(NULL, calculateReasonableTimeout(mCallbackFrames));
303 } else {
304 return AAUDIO_OK;
305 }
306}
307
308aaudio_result_t AudioStreamInternal::requestPauseInternal()
Phil Burk204a1632017-01-03 17:23:43 -0800309{
Phil Burk5ed503c2017-02-01 09:38:15 -0800310 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700311 ALOGE("AudioStreamInternal(): requestPauseInternal() mServiceStreamHandle invalid = 0x%08X",
312 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800313 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800314 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800315
Phil Burk3316d5e2017-02-15 11:23:01 -0800316 mClockModel.stop(AudioClock::getNanoseconds());
Phil Burk5ed503c2017-02-01 09:38:15 -0800317 setState(AAUDIO_STREAM_STATE_PAUSING);
Phil Burk71f35bb2017-04-13 16:05:07 -0700318 return mServiceInterface.pauseStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800319}
320
Phil Burke4d7bb42017-03-28 11:32:39 -0700321aaudio_result_t AudioStreamInternal::requestPause()
322{
Phil Burk71f35bb2017-04-13 16:05:07 -0700323 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestPause()", getLocationName());
Phil Burke4d7bb42017-03-28 11:32:39 -0700324 aaudio_result_t result = stopCallback();
325 if (result != AAUDIO_OK) {
326 return result;
327 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700328 result = requestPauseInternal();
329 ALOGD("AudioStreamInternal(): requestPause() returns %d", result);
330 return result;
Phil Burke4d7bb42017-03-28 11:32:39 -0700331}
332
Phil Burk5ed503c2017-02-01 09:38:15 -0800333aaudio_result_t AudioStreamInternal::requestFlush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700334 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): requestFlush()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800335 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700336 ALOGE("AudioStreamInternal(): requestFlush() mServiceStreamHandle invalid = 0x%08X",
337 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800338 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800339 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800340
Phil Burke4d7bb42017-03-28 11:32:39 -0700341 setState(AAUDIO_STREAM_STATE_FLUSHING);
Phil Burkc0c70e32017-02-09 13:18:38 -0800342 return mServiceInterface.flushStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800343}
344
345void AudioStreamInternal::onFlushFromServer() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700346 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): onFlushFromServer()");
Phil Burk3316d5e2017-02-15 11:23:01 -0800347 int64_t readCounter = mAudioEndpoint.getDownDataReadCounter();
348 int64_t writeCounter = mAudioEndpoint.getDownDataWriteCounter();
Phil Burk71f35bb2017-04-13 16:05:07 -0700349
Phil Burk204a1632017-01-03 17:23:43 -0800350 // Bump offset so caller does not see the retrograde motion in getFramesRead().
Phil Burk3316d5e2017-02-15 11:23:01 -0800351 int64_t framesFlushed = writeCounter - readCounter;
Phil Burk204a1632017-01-03 17:23:43 -0800352 mFramesOffsetFromService += framesFlushed;
Phil Burk71f35bb2017-04-13 16:05:07 -0700353
Phil Burk204a1632017-01-03 17:23:43 -0800354 // Flush written frames by forcing writeCounter to readCounter.
355 // This is because we cannot move the read counter in the hardware.
356 mAudioEndpoint.setDownDataWriteCounter(readCounter);
357}
358
Phil Burk71f35bb2017-04-13 16:05:07 -0700359aaudio_result_t AudioStreamInternal::requestStopInternal()
360{
361 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
362 ALOGE("AudioStreamInternal(): requestStopInternal() mServiceStreamHandle invalid = 0x%08X",
363 mServiceStreamHandle);
364 return AAUDIO_ERROR_INVALID_STATE;
365 }
366
367 mClockModel.stop(AudioClock::getNanoseconds());
368 setState(AAUDIO_STREAM_STATE_STOPPING);
369 return mServiceInterface.stopStream(mServiceStreamHandle);
370}
371
Phil Burk5ed503c2017-02-01 09:38:15 -0800372aaudio_result_t AudioStreamInternal::requestStop()
Phil Burk204a1632017-01-03 17:23:43 -0800373{
Phil Burk71f35bb2017-04-13 16:05:07 -0700374 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestStop()", getLocationName());
375 aaudio_result_t result = stopCallback();
376 if (result != AAUDIO_OK) {
377 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800378 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700379 result = requestStopInternal();
380 ALOGD("AudioStreamInternal(): requestStop() returns %d", result);
Phil Burk204a1632017-01-03 17:23:43 -0800381 return result;
382}
383
Phil Burk5ed503c2017-02-01 09:38:15 -0800384aaudio_result_t AudioStreamInternal::registerThread() {
Phil Burk5ed503c2017-02-01 09:38:15 -0800385 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
386 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800387 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800388 return mServiceInterface.registerAudioThread(mServiceStreamHandle,
389 getpid(),
390 gettid(),
391 getPeriodNanoseconds());
Phil Burk204a1632017-01-03 17:23:43 -0800392}
393
Phil Burk5ed503c2017-02-01 09:38:15 -0800394aaudio_result_t AudioStreamInternal::unregisterThread() {
Phil Burk5ed503c2017-02-01 09:38:15 -0800395 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
396 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800397 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800398 return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, getpid(), gettid());
Phil Burk204a1632017-01-03 17:23:43 -0800399}
400
Phil Burk5ed503c2017-02-01 09:38:15 -0800401aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
Phil Burk3316d5e2017-02-15 11:23:01 -0800402 int64_t *framePosition,
403 int64_t *timeNanoseconds) {
Phil Burke4d7bb42017-03-28 11:32:39 -0700404 // TODO implement using real HAL
Phil Burk3316d5e2017-02-15 11:23:01 -0800405 int64_t time = AudioClock::getNanoseconds();
Phil Burk204a1632017-01-03 17:23:43 -0800406 *framePosition = mClockModel.convertTimeToPosition(time);
Phil Burk5ed503c2017-02-01 09:38:15 -0800407 *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay
408 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800409}
410
Phil Burke4d7bb42017-03-28 11:32:39 -0700411aaudio_result_t AudioStreamInternal::updateStateWhileWaiting() {
412 if (isDataCallbackActive()) {
413 return AAUDIO_OK; // state is getting updated by the callback thread read/write call
414 }
Phil Burk204a1632017-01-03 17:23:43 -0800415 return processCommands();
416}
417
418#if LOG_TIMESTAMPS
Phil Burk5ed503c2017-02-01 09:38:15 -0800419static void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) {
Phil Burk204a1632017-01-03 17:23:43 -0800420 static int64_t oldPosition = 0;
Phil Burk3316d5e2017-02-15 11:23:01 -0800421 static int64_t oldTime = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800422 int64_t framePosition = command.timestamp.position;
Phil Burk3316d5e2017-02-15 11:23:01 -0800423 int64_t nanoTime = command.timestamp.timestamp;
Phil Burk71f35bb2017-04-13 16:05:07 -0700424 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu",
Phil Burk204a1632017-01-03 17:23:43 -0800425 (long long) framePosition,
426 (long long) nanoTime);
427 int64_t nanosDelta = nanoTime - oldTime;
428 if (nanosDelta > 0 && oldTime > 0) {
429 int64_t framesDelta = framePosition - oldPosition;
Phil Burk5ed503c2017-02-01 09:38:15 -0800430 int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta;
Phil Burk71f35bb2017-04-13 16:05:07 -0700431 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta);
432 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta);
433 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate);
Phil Burk204a1632017-01-03 17:23:43 -0800434 }
435 oldPosition = framePosition;
436 oldTime = nanoTime;
437}
438#endif
439
Phil Burk5ed503c2017-02-01 09:38:15 -0800440aaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) {
Phil Burk3316d5e2017-02-15 11:23:01 -0800441 int64_t framePosition = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800442#if LOG_TIMESTAMPS
443 AudioStreamInternal_LogTimestamp(command);
444#endif
445 framePosition = message->timestamp.position;
446 processTimestamp(framePosition, message->timestamp.timestamp);
Phil Burk5ed503c2017-02-01 09:38:15 -0800447 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800448}
449
Phil Burk5ed503c2017-02-01 09:38:15 -0800450aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) {
451 aaudio_result_t result = AAUDIO_OK;
Phil Burk71f35bb2017-04-13 16:05:07 -0700452 ALOGD_IF(MYLOG_CONDITION, "processCommands() got event %d", message->event.event);
Phil Burk204a1632017-01-03 17:23:43 -0800453 switch (message->event.event) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800454 case AAUDIO_SERVICE_EVENT_STARTED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700455 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STARTED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800456 setState(AAUDIO_STREAM_STATE_STARTED);
Phil Burk204a1632017-01-03 17:23:43 -0800457 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800458 case AAUDIO_SERVICE_EVENT_PAUSED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700459 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_PAUSED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800460 setState(AAUDIO_STREAM_STATE_PAUSED);
Phil Burk204a1632017-01-03 17:23:43 -0800461 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700462 case AAUDIO_SERVICE_EVENT_STOPPED:
463 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STOPPED");
464 setState(AAUDIO_STREAM_STATE_STOPPED);
465 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800466 case AAUDIO_SERVICE_EVENT_FLUSHED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700467 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800468 setState(AAUDIO_STREAM_STATE_FLUSHED);
Phil Burk204a1632017-01-03 17:23:43 -0800469 onFlushFromServer();
470 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800471 case AAUDIO_SERVICE_EVENT_CLOSED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700472 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_CLOSED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800473 setState(AAUDIO_STREAM_STATE_CLOSED);
Phil Burk204a1632017-01-03 17:23:43 -0800474 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800475 case AAUDIO_SERVICE_EVENT_DISCONNECTED:
476 result = AAUDIO_ERROR_DISCONNECTED;
Phil Burkc0c70e32017-02-09 13:18:38 -0800477 setState(AAUDIO_STREAM_STATE_DISCONNECTED);
Phil Burk5ed503c2017-02-01 09:38:15 -0800478 ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED");
Phil Burk204a1632017-01-03 17:23:43 -0800479 break;
Phil Burkc0c70e32017-02-09 13:18:38 -0800480 case AAUDIO_SERVICE_EVENT_VOLUME:
481 mVolume = message->event.dataDouble;
Phil Burk71f35bb2017-04-13 16:05:07 -0700482 ALOGD_IF(MYLOG_CONDITION, "processCommands() AAUDIO_SERVICE_EVENT_VOLUME %f", mVolume);
Phil Burkc0c70e32017-02-09 13:18:38 -0800483 break;
Phil Burk204a1632017-01-03 17:23:43 -0800484 default:
485 ALOGW("WARNING - processCommands() Unrecognized event = %d",
486 (int) message->event.event);
487 break;
488 }
489 return result;
490}
491
492// Process all the commands coming from the server.
Phil Burk5ed503c2017-02-01 09:38:15 -0800493aaudio_result_t AudioStreamInternal::processCommands() {
494 aaudio_result_t result = AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800495
Phil Burk5ed503c2017-02-01 09:38:15 -0800496 while (result == AAUDIO_OK) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700497 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::processCommands() - looping, %d", result);
Phil Burk5ed503c2017-02-01 09:38:15 -0800498 AAudioServiceMessage message;
Phil Burk204a1632017-01-03 17:23:43 -0800499 if (mAudioEndpoint.readUpCommand(&message) != 1) {
500 break; // no command this time, no problem
501 }
502 switch (message.what) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800503 case AAudioServiceMessage::code::TIMESTAMP:
Phil Burk204a1632017-01-03 17:23:43 -0800504 result = onTimestampFromServer(&message);
505 break;
506
Phil Burk5ed503c2017-02-01 09:38:15 -0800507 case AAudioServiceMessage::code::EVENT:
Phil Burk204a1632017-01-03 17:23:43 -0800508 result = onEventFromServer(&message);
509 break;
510
511 default:
Phil Burk71f35bb2017-04-13 16:05:07 -0700512 ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d",
Phil Burk204a1632017-01-03 17:23:43 -0800513 (int) message.what);
Phil Burk5ed503c2017-02-01 09:38:15 -0800514 result = AAUDIO_ERROR_UNEXPECTED_VALUE;
Phil Burk204a1632017-01-03 17:23:43 -0800515 break;
516 }
517 }
518 return result;
519}
520
521// Write the data, block if needed and timeoutMillis > 0
Phil Burk5ed503c2017-02-01 09:38:15 -0800522aaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames,
Phil Burk3316d5e2017-02-15 11:23:01 -0800523 int64_t timeoutNanoseconds)
Phil Burk204a1632017-01-03 17:23:43 -0800524{
Phil Burk5ed503c2017-02-01 09:38:15 -0800525 aaudio_result_t result = AAUDIO_OK;
Phil Burkc0c70e32017-02-09 13:18:38 -0800526 int32_t loopCount = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800527 uint8_t* source = (uint8_t*)buffer;
Phil Burk3316d5e2017-02-15 11:23:01 -0800528 int64_t currentTimeNanos = AudioClock::getNanoseconds();
529 int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds;
Phil Burk204a1632017-01-03 17:23:43 -0800530 int32_t framesLeft = numFrames;
Phil Burk204a1632017-01-03 17:23:43 -0800531
532 // Write until all the data has been written or until a timeout occurs.
533 while (framesLeft > 0) {
534 // The call to writeNow() will not block. It will just write as much as it can.
Phil Burk3316d5e2017-02-15 11:23:01 -0800535 int64_t wakeTimeNanos = 0;
Phil Burk5ed503c2017-02-01 09:38:15 -0800536 aaudio_result_t framesWritten = writeNow(source, framesLeft,
Phil Burk204a1632017-01-03 17:23:43 -0800537 currentTimeNanos, &wakeTimeNanos);
Phil Burk204a1632017-01-03 17:23:43 -0800538 if (framesWritten < 0) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800539 ALOGE("AudioStreamInternal::write() loop: writeNow returned %d", framesWritten);
Phil Burk204a1632017-01-03 17:23:43 -0800540 result = framesWritten;
541 break;
542 }
543 framesLeft -= (int32_t) framesWritten;
544 source += framesWritten * getBytesPerFrame();
545
546 // Should we block?
547 if (timeoutNanoseconds == 0) {
548 break; // don't block
549 } else if (framesLeft > 0) {
Phil Burk204a1632017-01-03 17:23:43 -0800550 // clip the wake time to something reasonable
551 if (wakeTimeNanos < currentTimeNanos) {
552 wakeTimeNanos = currentTimeNanos;
553 }
554 if (wakeTimeNanos > deadlineNanos) {
555 // If we time out, just return the framesWritten so far.
Phil Burkc0c70e32017-02-09 13:18:38 -0800556 ALOGE("AudioStreamInternal::write(): timed out after %lld nanos",
557 (long long) timeoutNanoseconds);
Phil Burk204a1632017-01-03 17:23:43 -0800558 break;
559 }
560
Phil Burk71f35bb2017-04-13 16:05:07 -0700561 int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos;
562 AudioClock::sleepForNanos(sleepForNanos);
Phil Burk204a1632017-01-03 17:23:43 -0800563 currentTimeNanos = AudioClock::getNanoseconds();
564 }
565 }
566
567 // return error or framesWritten
Phil Burkc0c70e32017-02-09 13:18:38 -0800568 (void) loopCount;
Phil Burk204a1632017-01-03 17:23:43 -0800569 return (result < 0) ? result : numFrames - framesLeft;
570}
571
572// Write as much data as we can without blocking.
Phil Burk5ed503c2017-02-01 09:38:15 -0800573aaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames,
Phil Burk3316d5e2017-02-15 11:23:01 -0800574 int64_t currentNanoTime, int64_t *wakeTimePtr) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800575
Phil Burk204a1632017-01-03 17:23:43 -0800576 {
Phil Burk5ed503c2017-02-01 09:38:15 -0800577 aaudio_result_t result = processCommands();
578 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800579 return result;
580 }
581 }
582
583 if (mAudioEndpoint.isOutputFreeRunning()) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700584 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - update read counter");
Phil Burk204a1632017-01-03 17:23:43 -0800585 // Update data queue based on the timing model.
586 int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime);
587 mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter);
Phil Burk204a1632017-01-03 17:23:43 -0800588 }
589 // TODO else query from endpoint cuz set by actual reader, maybe
590
Phil Burkc0c70e32017-02-09 13:18:38 -0800591 // If the read index passed the write index then consider it an underrun.
592 if (mAudioEndpoint.getFullFramesAvailable() < 0) {
593 mXRunCount++;
Phil Burk204a1632017-01-03 17:23:43 -0800594 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800595
596 // Write some data to the buffer.
Phil Burk71f35bb2017-04-13 16:05:07 -0700597 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - writeNowWithConversion(%d)", numFrames);
Phil Burkc0c70e32017-02-09 13:18:38 -0800598 int32_t framesWritten = writeNowWithConversion(buffer, numFrames);
Phil Burk71f35bb2017-04-13 16:05:07 -0700599 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d",
Phil Burk204a1632017-01-03 17:23:43 -0800600 // numFrames, framesWritten);
601
602 // Calculate an ideal time to wake up.
603 if (wakeTimePtr != nullptr && framesWritten >= 0) {
604 // By default wake up a few milliseconds from now. // TODO review
Phil Burkc0c70e32017-02-09 13:18:38 -0800605 int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND);
606 aaudio_stream_state_t state = getState();
Phil Burk71f35bb2017-04-13 16:05:07 -0700607 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - wakeTime based on %s",
Phil Burkc0c70e32017-02-09 13:18:38 -0800608 // AAudio_convertStreamStateToText(state));
609 switch (state) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800610 case AAUDIO_STREAM_STATE_OPEN:
611 case AAUDIO_STREAM_STATE_STARTING:
Phil Burk204a1632017-01-03 17:23:43 -0800612 if (framesWritten != 0) {
613 // Don't wait to write more data. Just prime the buffer.
614 wakeTime = currentNanoTime;
615 }
616 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800617 case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur?
Phil Burk204a1632017-01-03 17:23:43 -0800618 {
619 uint32_t burstSize = mFramesPerBurst;
620 if (burstSize < 32) {
621 burstSize = 32; // TODO review
622 }
623
624 uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize;
625 wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
626 }
627 break;
628 default:
629 break;
630 }
631 *wakeTimePtr = wakeTime;
632
633 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700634// ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu",
Phil Burk204a1632017-01-03 17:23:43 -0800635// (unsigned long long)currentNanoTime,
636// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(),
637// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter());
638 return framesWritten;
639}
640
Phil Burkc0c70e32017-02-09 13:18:38 -0800641
642// TODO this function needs a major cleanup.
643aaudio_result_t AudioStreamInternal::writeNowWithConversion(const void *buffer,
644 int32_t numFrames) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700645 // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion(%p, %d)", buffer, numFrames);
Phil Burkc0c70e32017-02-09 13:18:38 -0800646 WrappingBuffer wrappingBuffer;
Phil Burkc0c70e32017-02-09 13:18:38 -0800647 uint8_t *source = (uint8_t *) buffer;
648 int32_t framesLeft = numFrames;
649
650 mAudioEndpoint.getEmptyRoomAvailable(&wrappingBuffer);
651
652 // Read data in one or two parts.
653 int partIndex = 0;
654 while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) {
655 int32_t framesToWrite = framesLeft;
656 int32_t framesAvailable = wrappingBuffer.numFrames[partIndex];
657 if (framesAvailable > 0) {
658 if (framesToWrite > framesAvailable) {
659 framesToWrite = framesAvailable;
660 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700661 int32_t numBytes = getBytesPerFrame() * framesToWrite;
Phil Burkc0c70e32017-02-09 13:18:38 -0800662 // TODO handle volume scaling
663 if (getFormat() == mDeviceFormat) {
664 // Copy straight through.
665 memcpy(wrappingBuffer.data[partIndex], source, numBytes);
666 } else if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT
Phil Burk71f35bb2017-04-13 16:05:07 -0700667 && mDeviceFormat == AAUDIO_FORMAT_PCM_I16) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800668 // Data conversion.
669 AAudioConvert_floatToPcm16(
670 (const float *) source,
671 framesToWrite * getSamplesPerFrame(),
672 (int16_t *) wrappingBuffer.data[partIndex]);
Phil Burk71f35bb2017-04-13 16:05:07 -0700673 } else if (getFormat() == AAUDIO_FORMAT_PCM_I16
674 && mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) {
675 // Data conversion.
676 AAudioConvert_pcm16ToFloat(
677 (const int16_t *) source,
678 framesToWrite * getSamplesPerFrame(),
679 (float *) wrappingBuffer.data[partIndex]);
Phil Burkc0c70e32017-02-09 13:18:38 -0800680 } else {
681 // TODO handle more conversions
682 ALOGE("AudioStreamInternal::writeNowWithConversion() unsupported formats: %d, %d",
683 getFormat(), mDeviceFormat);
684 return AAUDIO_ERROR_UNEXPECTED_VALUE;
685 }
686
687 source += numBytes;
688 framesLeft -= framesToWrite;
Phil Burk71f35bb2017-04-13 16:05:07 -0700689 } else {
690 break;
Phil Burkc0c70e32017-02-09 13:18:38 -0800691 }
692 partIndex++;
693 }
694 int32_t framesWritten = numFrames - framesLeft;
695 mAudioEndpoint.advanceWriteIndex(framesWritten);
696
697 if (framesWritten > 0) {
698 incrementFramesWritten(framesWritten);
699 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700700 // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion() returns %d", framesWritten);
Phil Burkc0c70e32017-02-09 13:18:38 -0800701 return framesWritten;
702}
703
Phil Burk3316d5e2017-02-15 11:23:01 -0800704void AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) {
Phil Burk204a1632017-01-03 17:23:43 -0800705 mClockModel.processTimestamp( position, time);
706}
707
Phil Burk3316d5e2017-02-15 11:23:01 -0800708aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) {
709 int32_t actualFrames = 0;
Phil Burk71f35bb2017-04-13 16:05:07 -0700710 // Round to the next highest burst size.
711 if (getFramesPerBurst() > 0) {
712 int32_t numBursts = (requestedFrames + getFramesPerBurst() - 1) / getFramesPerBurst();
713 requestedFrames = numBursts * getFramesPerBurst();
714 }
715
Phil Burk3316d5e2017-02-15 11:23:01 -0800716 aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames);
Phil Burk71f35bb2017-04-13 16:05:07 -0700717 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::setBufferSize() %s req = %d => %d",
718 getLocationName(), requestedFrames, actualFrames);
Phil Burk3316d5e2017-02-15 11:23:01 -0800719 if (result < 0) {
720 return result;
721 } else {
722 return (aaudio_result_t) actualFrames;
723 }
Phil Burk204a1632017-01-03 17:23:43 -0800724}
725
Phil Burk3316d5e2017-02-15 11:23:01 -0800726int32_t AudioStreamInternal::getBufferSize() const
Phil Burk204a1632017-01-03 17:23:43 -0800727{
728 return mAudioEndpoint.getBufferSizeInFrames();
729}
730
Phil Burk3316d5e2017-02-15 11:23:01 -0800731int32_t AudioStreamInternal::getBufferCapacity() const
Phil Burk204a1632017-01-03 17:23:43 -0800732{
733 return mAudioEndpoint.getBufferCapacityInFrames();
734}
735
Phil Burk3316d5e2017-02-15 11:23:01 -0800736int32_t AudioStreamInternal::getFramesPerBurst() const
Phil Burk204a1632017-01-03 17:23:43 -0800737{
738 return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
739}
740
Phil Burk3316d5e2017-02-15 11:23:01 -0800741int64_t AudioStreamInternal::getFramesRead()
Phil Burk204a1632017-01-03 17:23:43 -0800742{
Phil Burk3316d5e2017-02-15 11:23:01 -0800743 int64_t framesRead =
Phil Burk204a1632017-01-03 17:23:43 -0800744 mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
745 + mFramesOffsetFromService;
746 // Prevent retrograde motion.
747 if (framesRead < mLastFramesRead) {
748 framesRead = mLastFramesRead;
749 } else {
750 mLastFramesRead = framesRead;
751 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700752 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead);
Phil Burk204a1632017-01-03 17:23:43 -0800753 return framesRead;
754}
755
756// TODO implement getTimestamp