blob: eee860e2d6d0b8ed139b475c86783dee064a5a4f [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 Burk3df348f2017-02-08 11:41:55 -080035#include "core/AudioStreamBuilder.h"
Phil Burke572f462017-04-20 13:03:19 -070036#include "fifo/FifoBuffer.h"
37#include "utility/LinearRamp.h"
38
Phil Burkc0c70e32017-02-09 13:18:38 -080039#include "AudioStreamInternal.h"
Phil Burk204a1632017-01-03 17:23:43 -080040
41#define LOG_TIMESTAMPS 0
42
43using android::String16;
Phil Burkdec33ab2017-01-17 14:48:16 -080044using android::Mutex;
Phil Burkc0c70e32017-02-09 13:18:38 -080045using android::WrappingBuffer;
Phil Burk204a1632017-01-03 17:23:43 -080046
Phil Burk5ed503c2017-02-01 09:38:15 -080047using namespace aaudio;
Phil Burk204a1632017-01-03 17:23:43 -080048
Phil Burke4d7bb42017-03-28 11:32:39 -070049#define MIN_TIMEOUT_NANOS (1000 * AAUDIO_NANOS_PER_MILLISECOND)
50
51// Wait at least this many times longer than the operation should take.
52#define MIN_TIMEOUT_OPERATIONS 4
53
Phil Burk71f35bb2017-04-13 16:05:07 -070054//static int64_t s_logCounter = 0;
55//#define MYLOG_CONDITION (mInService == true && s_logCounter++ < 500)
56//#define MYLOG_CONDITION (s_logCounter++ < 500000)
57#define MYLOG_CONDITION (1)
Phil Burkdec33ab2017-01-17 14:48:16 -080058
Phil Burkc0c70e32017-02-09 13:18:38 -080059AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface &serviceInterface, bool inService)
Phil Burk204a1632017-01-03 17:23:43 -080060 : AudioStream()
61 , mClockModel()
62 , mAudioEndpoint()
Phil Burk5ed503c2017-02-01 09:38:15 -080063 , mServiceStreamHandle(AAUDIO_HANDLE_INVALID)
Phil Burk204a1632017-01-03 17:23:43 -080064 , mFramesPerBurst(16)
Phil Burkc0c70e32017-02-09 13:18:38 -080065 , mServiceInterface(serviceInterface)
Phil Burk71f35bb2017-04-13 16:05:07 -070066 , mInService(inService) {
Phil Burk204a1632017-01-03 17:23:43 -080067}
68
69AudioStreamInternal::~AudioStreamInternal() {
70}
71
Phil Burk5ed503c2017-02-01 09:38:15 -080072aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
Phil Burk204a1632017-01-03 17:23:43 -080073
Phil Burk5ed503c2017-02-01 09:38:15 -080074 aaudio_result_t result = AAUDIO_OK;
75 AAudioStreamRequest request;
76 AAudioStreamConfiguration configuration;
Phil Burk204a1632017-01-03 17:23:43 -080077
78 result = AudioStream::open(builder);
79 if (result < 0) {
80 return result;
81 }
82
Phil Burkc0c70e32017-02-09 13:18:38 -080083 // We have to do volume scaling. So we prefer FLOAT format.
84 if (getFormat() == AAUDIO_UNSPECIFIED) {
85 setFormat(AAUDIO_FORMAT_PCM_FLOAT);
86 }
Phil Burk71f35bb2017-04-13 16:05:07 -070087 // Request FLOAT for the shared mixer.
88 request.getConfiguration().setAudioFormat(AAUDIO_FORMAT_PCM_FLOAT);
Phil Burkc0c70e32017-02-09 13:18:38 -080089
Phil Burkdec33ab2017-01-17 14:48:16 -080090 // Build the request to send to the server.
Phil Burk204a1632017-01-03 17:23:43 -080091 request.setUserId(getuid());
92 request.setProcessId(getpid());
Phil Burkc0c70e32017-02-09 13:18:38 -080093 request.setDirection(getDirection());
Phil Burk71f35bb2017-04-13 16:05:07 -070094 request.setSharingModeMatchRequired(isSharingModeMatchRequired());
Phil Burkc0c70e32017-02-09 13:18:38 -080095
Phil Burk204a1632017-01-03 17:23:43 -080096 request.getConfiguration().setDeviceId(getDeviceId());
97 request.getConfiguration().setSampleRate(getSampleRate());
98 request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame());
Phil Burk71f35bb2017-04-13 16:05:07 -070099 request.getConfiguration().setSharingMode(getSharingMode());
100
Phil Burk3df348f2017-02-08 11:41:55 -0800101 request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
Phil Burk204a1632017-01-03 17:23:43 -0800102
Phil Burkc0c70e32017-02-09 13:18:38 -0800103 mServiceStreamHandle = mServiceInterface.openStream(request, configuration);
Phil Burk204a1632017-01-03 17:23:43 -0800104 if (mServiceStreamHandle < 0) {
105 result = mServiceStreamHandle;
Phil Burk71f35bb2017-04-13 16:05:07 -0700106 ALOGE("AudioStreamInternal.open(): %s openStream() returned %d", getLocationName(), result);
Phil Burk204a1632017-01-03 17:23:43 -0800107 } else {
108 result = configuration.validate();
Phil Burk5ed503c2017-02-01 09:38:15 -0800109 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800110 close();
111 return result;
112 }
113 // Save results of the open.
114 setSampleRate(configuration.getSampleRate());
115 setSamplesPerFrame(configuration.getSamplesPerFrame());
Phil Burkc0c70e32017-02-09 13:18:38 -0800116 setDeviceId(configuration.getDeviceId());
Phil Burk204a1632017-01-03 17:23:43 -0800117
Phil Burkc0c70e32017-02-09 13:18:38 -0800118 // Save device format so we can do format conversion and volume scaling together.
119 mDeviceFormat = configuration.getAudioFormat();
120
121 result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable);
Phil Burk5ed503c2017-02-01 09:38:15 -0800122 if (result != AAUDIO_OK) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700123 ALOGE("AudioStreamInternal.open(): %s getStreamDescriptor returns %d",
124 getLocationName(), result);
Phil Burkc0c70e32017-02-09 13:18:38 -0800125 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800126 return result;
127 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800128
Phil Burk204a1632017-01-03 17:23:43 -0800129 // resolve parcelable into a descriptor
Phil Burkc0c70e32017-02-09 13:18:38 -0800130 result = mEndPointParcelable.resolve(&mEndpointDescriptor);
131 if (result != AAUDIO_OK) {
132 ALOGE("AudioStreamInternal.open(): resolve() returns %d", result);
133 mServiceInterface.closeStream(mServiceStreamHandle);
134 return result;
135 }
Phil Burk204a1632017-01-03 17:23:43 -0800136
137 // Configure endpoint based on descriptor.
138 mAudioEndpoint.configure(&mEndpointDescriptor);
139
Phil Burk204a1632017-01-03 17:23:43 -0800140 mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
Phil Burk71f35bb2017-04-13 16:05:07 -0700141 int32_t capacity = mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames;
142
143 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.open() %s framesPerBurst = %d, capacity = %d",
144 getLocationName(), mFramesPerBurst, capacity);
145 // Validate result from server.
146 if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) {
147 ALOGE("AudioStream::open(): framesPerBurst out of range = %d", mFramesPerBurst);
148 return AAUDIO_ERROR_OUT_OF_RANGE;
149 }
150 if (capacity < mFramesPerBurst || capacity > 32 * 1024) {
151 ALOGE("AudioStream::open(): bufferCapacity out of range = %d", capacity);
152 return AAUDIO_ERROR_OUT_OF_RANGE;
153 }
Phil Burk204a1632017-01-03 17:23:43 -0800154
155 mClockModel.setSampleRate(getSampleRate());
156 mClockModel.setFramesPerBurst(mFramesPerBurst);
157
Phil Burke4d7bb42017-03-28 11:32:39 -0700158 if (getDataCallbackProc()) {
159 mCallbackFrames = builder.getFramesPerDataCallback();
160 if (mCallbackFrames > getBufferCapacity() / 2) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700161 ALOGE("AudioStreamInternal.open(): framesPerCallback too large = %d, capacity = %d",
162 mCallbackFrames, getBufferCapacity());
Phil Burkc0c70e32017-02-09 13:18:38 -0800163 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700164 return AAUDIO_ERROR_OUT_OF_RANGE;
165
166 } else if (mCallbackFrames < 0) {
167 ALOGE("AudioStreamInternal.open(): framesPerCallback negative");
Phil Burkc0c70e32017-02-09 13:18:38 -0800168 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700169 return AAUDIO_ERROR_OUT_OF_RANGE;
170
171 }
172 if (mCallbackFrames == AAUDIO_UNSPECIFIED) {
173 mCallbackFrames = mFramesPerBurst;
174 }
175
176 int32_t bytesPerFrame = getSamplesPerFrame()
177 * AAudioConvert_formatToSizeInBytes(getFormat());
178 int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame;
179 mCallbackBuffer = new uint8_t[callbackBufferSize];
180 }
181
Phil Burk5ed503c2017-02-01 09:38:15 -0800182 setState(AAUDIO_STREAM_STATE_OPEN);
Phil Burk204a1632017-01-03 17:23:43 -0800183 }
184 return result;
185}
186
Phil Burk5ed503c2017-02-01 09:38:15 -0800187aaudio_result_t AudioStreamInternal::close() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700188 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X",
189 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800190 if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
191 aaudio_handle_t serviceStreamHandle = mServiceStreamHandle;
192 mServiceStreamHandle = AAUDIO_HANDLE_INVALID;
Phil Burkc0c70e32017-02-09 13:18:38 -0800193
194 mServiceInterface.closeStream(serviceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700195 delete[] mCallbackBuffer;
Phil Burkc0c70e32017-02-09 13:18:38 -0800196 return mEndPointParcelable.close();
Phil Burk204a1632017-01-03 17:23:43 -0800197 } else {
Phil Burk5ed503c2017-02-01 09:38:15 -0800198 return AAUDIO_ERROR_INVALID_HANDLE;
Phil Burk204a1632017-01-03 17:23:43 -0800199 }
200}
201
Phil Burkc0c70e32017-02-09 13:18:38 -0800202
Phil Burke4d7bb42017-03-28 11:32:39 -0700203// Render audio in the application callback and then write the data to the stream.
204void *AudioStreamInternal::callbackLoop() {
205 aaudio_result_t result = AAUDIO_OK;
206 aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE;
Phil Burke4d7bb42017-03-28 11:32:39 -0700207 AAudioStream_dataCallback appCallback = getDataCallbackProc();
208 if (appCallback == nullptr) return NULL;
209
Phil Burk677d7912017-04-07 12:17:12 -0700210 // result might be a frame count
211 while (mCallbackEnabled.load() && isPlaying() && (result >= 0)) {
Phil Burke4d7bb42017-03-28 11:32:39 -0700212 // Call application using the AAudio callback interface.
213 callbackResult = (*appCallback)(
214 (AAudioStream *) this,
215 getDataCallbackUserData(),
216 mCallbackBuffer,
217 mCallbackFrames);
218
219 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
Phil Burk677d7912017-04-07 12:17:12 -0700220 // Write audio data to stream.
Phil Burke4d7bb42017-03-28 11:32:39 -0700221 int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames);
Phil Burk677d7912017-04-07 12:17:12 -0700222
223 // This is a BLOCKING WRITE!
Phil Burke4d7bb42017-03-28 11:32:39 -0700224 result = write(mCallbackBuffer, mCallbackFrames, timeoutNanos);
Phil Burk677d7912017-04-07 12:17:12 -0700225 if ((result != mCallbackFrames)) {
226 ALOGE("AudioStreamInternal(): callbackLoop: write() returned %d", result);
227 if (result >= 0) {
228 // Only wrote some of the frames requested. Must have timed out.
229 result = AAUDIO_ERROR_TIMEOUT;
230 }
Phil Burke4d7bb42017-03-28 11:32:39 -0700231 if (getErrorCallbackProc() != nullptr) {
Phil Burke4d7bb42017-03-28 11:32:39 -0700232 (*getErrorCallbackProc())(
233 (AAudioStream *) this,
234 getErrorCallbackUserData(),
Phil Burk677d7912017-04-07 12:17:12 -0700235 result);
Phil Burke4d7bb42017-03-28 11:32:39 -0700236 }
237 break;
Phil Burke4d7bb42017-03-28 11:32:39 -0700238 }
239 } else if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
Phil Burk677d7912017-04-07 12:17:12 -0700240 ALOGD("AudioStreamInternal(): callback returned AAUDIO_CALLBACK_RESULT_STOP");
Phil Burke4d7bb42017-03-28 11:32:39 -0700241 break;
242 }
243 }
244
Phil Burk677d7912017-04-07 12:17:12 -0700245 ALOGD("AudioStreamInternal(): callbackLoop() exiting, result = %d, isPlaying() = %d",
Phil Burke4d7bb42017-03-28 11:32:39 -0700246 result, (int) isPlaying());
Phil Burk5204d312017-05-04 17:16:13 -0700247 return NULL;
Phil Burke4d7bb42017-03-28 11:32:39 -0700248}
249
250static void *aaudio_callback_thread_proc(void *context)
251{
252 AudioStreamInternal *stream = (AudioStreamInternal *)context;
Phil Burk677d7912017-04-07 12:17:12 -0700253 //LOGD("AudioStreamInternal(): oboe_callback_thread, stream = %p", stream);
Phil Burke4d7bb42017-03-28 11:32:39 -0700254 if (stream != NULL) {
255 return stream->callbackLoop();
256 } else {
257 return NULL;
258 }
259}
260
Phil Burk5ed503c2017-02-01 09:38:15 -0800261aaudio_result_t AudioStreamInternal::requestStart()
Phil Burk204a1632017-01-03 17:23:43 -0800262{
Phil Burk3316d5e2017-02-15 11:23:01 -0800263 int64_t startTime;
Phil Burk71f35bb2017-04-13 16:05:07 -0700264 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): start()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800265 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
266 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800267 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800268
Phil Burk3316d5e2017-02-15 11:23:01 -0800269 startTime = AudioClock::getNanoseconds();
Phil Burk204a1632017-01-03 17:23:43 -0800270 mClockModel.start(startTime);
271 processTimestamp(0, startTime);
Phil Burk5ed503c2017-02-01 09:38:15 -0800272 setState(AAUDIO_STREAM_STATE_STARTING);
Phil Burkc0c70e32017-02-09 13:18:38 -0800273 aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);;
Phil Burke4d7bb42017-03-28 11:32:39 -0700274
275 if (result == AAUDIO_OK && getDataCallbackProc() != nullptr) {
276 // Launch the callback loop thread.
277 int64_t periodNanos = mCallbackFrames
278 * AAUDIO_NANOS_PER_SECOND
279 / getSampleRate();
280 mCallbackEnabled.store(true);
281 result = createThread(periodNanos, aaudio_callback_thread_proc, this);
282 }
283 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800284}
285
Phil Burke4d7bb42017-03-28 11:32:39 -0700286int64_t AudioStreamInternal::calculateReasonableTimeout(int32_t framesPerOperation) {
287
288 // Wait for at least a second or some number of callbacks to join the thread.
Phil Burk71f35bb2017-04-13 16:05:07 -0700289 int64_t timeoutNanoseconds = (MIN_TIMEOUT_OPERATIONS
290 * framesPerOperation
291 * AAUDIO_NANOS_PER_SECOND)
292 / getSampleRate();
Phil Burke4d7bb42017-03-28 11:32:39 -0700293 if (timeoutNanoseconds < MIN_TIMEOUT_NANOS) { // arbitrary number of seconds
294 timeoutNanoseconds = MIN_TIMEOUT_NANOS;
295 }
296 return timeoutNanoseconds;
297}
298
299aaudio_result_t AudioStreamInternal::stopCallback()
300{
301 if (isDataCallbackActive()) {
302 mCallbackEnabled.store(false);
303 return joinThread(NULL, calculateReasonableTimeout(mCallbackFrames));
304 } else {
305 return AAUDIO_OK;
306 }
307}
308
309aaudio_result_t AudioStreamInternal::requestPauseInternal()
Phil Burk204a1632017-01-03 17:23:43 -0800310{
Phil Burk5ed503c2017-02-01 09:38:15 -0800311 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700312 ALOGE("AudioStreamInternal(): requestPauseInternal() mServiceStreamHandle invalid = 0x%08X",
313 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800314 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800315 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800316
Phil Burk3316d5e2017-02-15 11:23:01 -0800317 mClockModel.stop(AudioClock::getNanoseconds());
Phil Burk5ed503c2017-02-01 09:38:15 -0800318 setState(AAUDIO_STREAM_STATE_PAUSING);
Phil Burk71f35bb2017-04-13 16:05:07 -0700319 return mServiceInterface.pauseStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800320}
321
Phil Burke4d7bb42017-03-28 11:32:39 -0700322aaudio_result_t AudioStreamInternal::requestPause()
323{
Phil Burk71f35bb2017-04-13 16:05:07 -0700324 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestPause()", getLocationName());
Phil Burke4d7bb42017-03-28 11:32:39 -0700325 aaudio_result_t result = stopCallback();
326 if (result != AAUDIO_OK) {
327 return result;
328 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700329 result = requestPauseInternal();
330 ALOGD("AudioStreamInternal(): requestPause() returns %d", result);
331 return result;
Phil Burke4d7bb42017-03-28 11:32:39 -0700332}
333
Phil Burk5ed503c2017-02-01 09:38:15 -0800334aaudio_result_t AudioStreamInternal::requestFlush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700335 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): requestFlush()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800336 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700337 ALOGE("AudioStreamInternal(): requestFlush() mServiceStreamHandle invalid = 0x%08X",
338 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800339 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800340 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800341
Phil Burke4d7bb42017-03-28 11:32:39 -0700342 setState(AAUDIO_STREAM_STATE_FLUSHING);
Phil Burkc0c70e32017-02-09 13:18:38 -0800343 return mServiceInterface.flushStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800344}
345
346void AudioStreamInternal::onFlushFromServer() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700347 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): onFlushFromServer()");
Phil Burk3316d5e2017-02-15 11:23:01 -0800348 int64_t readCounter = mAudioEndpoint.getDownDataReadCounter();
349 int64_t writeCounter = mAudioEndpoint.getDownDataWriteCounter();
Phil Burk71f35bb2017-04-13 16:05:07 -0700350
Phil Burk204a1632017-01-03 17:23:43 -0800351 // Bump offset so caller does not see the retrograde motion in getFramesRead().
Phil Burk3316d5e2017-02-15 11:23:01 -0800352 int64_t framesFlushed = writeCounter - readCounter;
Phil Burk204a1632017-01-03 17:23:43 -0800353 mFramesOffsetFromService += framesFlushed;
Phil Burk71f35bb2017-04-13 16:05:07 -0700354
Phil Burk204a1632017-01-03 17:23:43 -0800355 // Flush written frames by forcing writeCounter to readCounter.
356 // This is because we cannot move the read counter in the hardware.
357 mAudioEndpoint.setDownDataWriteCounter(readCounter);
358}
359
Phil Burk71f35bb2017-04-13 16:05:07 -0700360aaudio_result_t AudioStreamInternal::requestStopInternal()
361{
362 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
363 ALOGE("AudioStreamInternal(): requestStopInternal() mServiceStreamHandle invalid = 0x%08X",
364 mServiceStreamHandle);
365 return AAUDIO_ERROR_INVALID_STATE;
366 }
367
368 mClockModel.stop(AudioClock::getNanoseconds());
369 setState(AAUDIO_STREAM_STATE_STOPPING);
370 return mServiceInterface.stopStream(mServiceStreamHandle);
371}
372
Phil Burk5ed503c2017-02-01 09:38:15 -0800373aaudio_result_t AudioStreamInternal::requestStop()
Phil Burk204a1632017-01-03 17:23:43 -0800374{
Phil Burk71f35bb2017-04-13 16:05:07 -0700375 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestStop()", getLocationName());
376 aaudio_result_t result = stopCallback();
377 if (result != AAUDIO_OK) {
378 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800379 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700380 result = requestStopInternal();
381 ALOGD("AudioStreamInternal(): requestStop() returns %d", result);
Phil Burk204a1632017-01-03 17:23:43 -0800382 return result;
383}
384
Phil Burk5ed503c2017-02-01 09:38:15 -0800385aaudio_result_t AudioStreamInternal::registerThread() {
Phil Burk5ed503c2017-02-01 09:38:15 -0800386 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
387 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800388 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800389 return mServiceInterface.registerAudioThread(mServiceStreamHandle,
390 getpid(),
391 gettid(),
392 getPeriodNanoseconds());
Phil Burk204a1632017-01-03 17:23:43 -0800393}
394
Phil Burk5ed503c2017-02-01 09:38:15 -0800395aaudio_result_t AudioStreamInternal::unregisterThread() {
Phil Burk5ed503c2017-02-01 09:38:15 -0800396 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
397 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800398 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800399 return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, getpid(), gettid());
Phil Burk204a1632017-01-03 17:23:43 -0800400}
401
Phil Burk5ed503c2017-02-01 09:38:15 -0800402aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
Phil Burk3316d5e2017-02-15 11:23:01 -0800403 int64_t *framePosition,
404 int64_t *timeNanoseconds) {
Phil Burk5204d312017-05-04 17:16:13 -0700405 // TODO Generate in server and pass to client. Return latest.
Phil Burk3316d5e2017-02-15 11:23:01 -0800406 int64_t time = AudioClock::getNanoseconds();
Phil Burk204a1632017-01-03 17:23:43 -0800407 *framePosition = mClockModel.convertTimeToPosition(time);
Phil Burk5ed503c2017-02-01 09:38:15 -0800408 *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay
409 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800410}
411
Phil Burke4d7bb42017-03-28 11:32:39 -0700412aaudio_result_t AudioStreamInternal::updateStateWhileWaiting() {
413 if (isDataCallbackActive()) {
414 return AAUDIO_OK; // state is getting updated by the callback thread read/write call
415 }
Phil Burk204a1632017-01-03 17:23:43 -0800416 return processCommands();
417}
418
419#if LOG_TIMESTAMPS
Phil Burk5ed503c2017-02-01 09:38:15 -0800420static void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) {
Phil Burk204a1632017-01-03 17:23:43 -0800421 static int64_t oldPosition = 0;
Phil Burk3316d5e2017-02-15 11:23:01 -0800422 static int64_t oldTime = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800423 int64_t framePosition = command.timestamp.position;
Phil Burk3316d5e2017-02-15 11:23:01 -0800424 int64_t nanoTime = command.timestamp.timestamp;
Phil Burk71f35bb2017-04-13 16:05:07 -0700425 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu",
Phil Burk204a1632017-01-03 17:23:43 -0800426 (long long) framePosition,
427 (long long) nanoTime);
428 int64_t nanosDelta = nanoTime - oldTime;
429 if (nanosDelta > 0 && oldTime > 0) {
430 int64_t framesDelta = framePosition - oldPosition;
Phil Burk5ed503c2017-02-01 09:38:15 -0800431 int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta;
Phil Burk71f35bb2017-04-13 16:05:07 -0700432 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta);
433 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta);
434 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate);
Phil Burk204a1632017-01-03 17:23:43 -0800435 }
436 oldPosition = framePosition;
437 oldTime = nanoTime;
438}
439#endif
440
Phil Burk5ed503c2017-02-01 09:38:15 -0800441aaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) {
Phil Burk3316d5e2017-02-15 11:23:01 -0800442 int64_t framePosition = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800443#if LOG_TIMESTAMPS
444 AudioStreamInternal_LogTimestamp(command);
445#endif
446 framePosition = message->timestamp.position;
447 processTimestamp(framePosition, message->timestamp.timestamp);
Phil Burk5ed503c2017-02-01 09:38:15 -0800448 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800449}
450
Phil Burk5ed503c2017-02-01 09:38:15 -0800451aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) {
452 aaudio_result_t result = AAUDIO_OK;
Phil Burk71f35bb2017-04-13 16:05:07 -0700453 ALOGD_IF(MYLOG_CONDITION, "processCommands() got event %d", message->event.event);
Phil Burk204a1632017-01-03 17:23:43 -0800454 switch (message->event.event) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800455 case AAUDIO_SERVICE_EVENT_STARTED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700456 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STARTED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800457 setState(AAUDIO_STREAM_STATE_STARTED);
Phil Burk204a1632017-01-03 17:23:43 -0800458 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800459 case AAUDIO_SERVICE_EVENT_PAUSED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700460 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_PAUSED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800461 setState(AAUDIO_STREAM_STATE_PAUSED);
Phil Burk204a1632017-01-03 17:23:43 -0800462 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700463 case AAUDIO_SERVICE_EVENT_STOPPED:
464 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STOPPED");
465 setState(AAUDIO_STREAM_STATE_STOPPED);
466 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800467 case AAUDIO_SERVICE_EVENT_FLUSHED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700468 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800469 setState(AAUDIO_STREAM_STATE_FLUSHED);
Phil Burk204a1632017-01-03 17:23:43 -0800470 onFlushFromServer();
471 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800472 case AAUDIO_SERVICE_EVENT_CLOSED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700473 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_CLOSED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800474 setState(AAUDIO_STREAM_STATE_CLOSED);
Phil Burk204a1632017-01-03 17:23:43 -0800475 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800476 case AAUDIO_SERVICE_EVENT_DISCONNECTED:
477 result = AAUDIO_ERROR_DISCONNECTED;
Phil Burkc0c70e32017-02-09 13:18:38 -0800478 setState(AAUDIO_STREAM_STATE_DISCONNECTED);
Phil Burk5ed503c2017-02-01 09:38:15 -0800479 ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED");
Phil Burk204a1632017-01-03 17:23:43 -0800480 break;
Phil Burkc0c70e32017-02-09 13:18:38 -0800481 case AAUDIO_SERVICE_EVENT_VOLUME:
Phil Burke572f462017-04-20 13:03:19 -0700482 mVolumeRamp.setTarget((float) message->event.dataDouble);
483 ALOGD_IF(MYLOG_CONDITION, "processCommands() AAUDIO_SERVICE_EVENT_VOLUME %f",
484 message->event.dataDouble);
Phil Burkc0c70e32017-02-09 13:18:38 -0800485 break;
Phil Burk204a1632017-01-03 17:23:43 -0800486 default:
487 ALOGW("WARNING - processCommands() Unrecognized event = %d",
488 (int) message->event.event);
489 break;
490 }
491 return result;
492}
493
494// Process all the commands coming from the server.
Phil Burk5ed503c2017-02-01 09:38:15 -0800495aaudio_result_t AudioStreamInternal::processCommands() {
496 aaudio_result_t result = AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800497
Phil Burk5ed503c2017-02-01 09:38:15 -0800498 while (result == AAUDIO_OK) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700499 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::processCommands() - looping, %d", result);
Phil Burk5ed503c2017-02-01 09:38:15 -0800500 AAudioServiceMessage message;
Phil Burk204a1632017-01-03 17:23:43 -0800501 if (mAudioEndpoint.readUpCommand(&message) != 1) {
502 break; // no command this time, no problem
503 }
504 switch (message.what) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800505 case AAudioServiceMessage::code::TIMESTAMP:
Phil Burk204a1632017-01-03 17:23:43 -0800506 result = onTimestampFromServer(&message);
507 break;
508
Phil Burk5ed503c2017-02-01 09:38:15 -0800509 case AAudioServiceMessage::code::EVENT:
Phil Burk204a1632017-01-03 17:23:43 -0800510 result = onEventFromServer(&message);
511 break;
512
513 default:
Phil Burk71f35bb2017-04-13 16:05:07 -0700514 ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d",
Phil Burk204a1632017-01-03 17:23:43 -0800515 (int) message.what);
Phil Burk5ed503c2017-02-01 09:38:15 -0800516 result = AAUDIO_ERROR_UNEXPECTED_VALUE;
Phil Burk204a1632017-01-03 17:23:43 -0800517 break;
518 }
519 }
520 return result;
521}
522
523// Write the data, block if needed and timeoutMillis > 0
Phil Burk5ed503c2017-02-01 09:38:15 -0800524aaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames,
Phil Burk3316d5e2017-02-15 11:23:01 -0800525 int64_t timeoutNanoseconds)
Phil Burk204a1632017-01-03 17:23:43 -0800526{
Phil Burk5ed503c2017-02-01 09:38:15 -0800527 aaudio_result_t result = AAUDIO_OK;
Phil Burkc0c70e32017-02-09 13:18:38 -0800528 int32_t loopCount = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800529 uint8_t* source = (uint8_t*)buffer;
Phil Burk3316d5e2017-02-15 11:23:01 -0800530 int64_t currentTimeNanos = AudioClock::getNanoseconds();
531 int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds;
Phil Burk204a1632017-01-03 17:23:43 -0800532 int32_t framesLeft = numFrames;
Phil Burk204a1632017-01-03 17:23:43 -0800533
534 // Write until all the data has been written or until a timeout occurs.
535 while (framesLeft > 0) {
536 // The call to writeNow() will not block. It will just write as much as it can.
Phil Burk3316d5e2017-02-15 11:23:01 -0800537 int64_t wakeTimeNanos = 0;
Phil Burk5ed503c2017-02-01 09:38:15 -0800538 aaudio_result_t framesWritten = writeNow(source, framesLeft,
Phil Burk204a1632017-01-03 17:23:43 -0800539 currentTimeNanos, &wakeTimeNanos);
Phil Burk204a1632017-01-03 17:23:43 -0800540 if (framesWritten < 0) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800541 ALOGE("AudioStreamInternal::write() loop: writeNow returned %d", framesWritten);
Phil Burk204a1632017-01-03 17:23:43 -0800542 result = framesWritten;
543 break;
544 }
545 framesLeft -= (int32_t) framesWritten;
546 source += framesWritten * getBytesPerFrame();
547
548 // Should we block?
549 if (timeoutNanoseconds == 0) {
550 break; // don't block
551 } else if (framesLeft > 0) {
Phil Burk204a1632017-01-03 17:23:43 -0800552 // clip the wake time to something reasonable
553 if (wakeTimeNanos < currentTimeNanos) {
554 wakeTimeNanos = currentTimeNanos;
555 }
556 if (wakeTimeNanos > deadlineNanos) {
557 // If we time out, just return the framesWritten so far.
Phil Burkc0c70e32017-02-09 13:18:38 -0800558 ALOGE("AudioStreamInternal::write(): timed out after %lld nanos",
559 (long long) timeoutNanoseconds);
Phil Burk204a1632017-01-03 17:23:43 -0800560 break;
561 }
562
Phil Burk71f35bb2017-04-13 16:05:07 -0700563 int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos;
564 AudioClock::sleepForNanos(sleepForNanos);
Phil Burk204a1632017-01-03 17:23:43 -0800565 currentTimeNanos = AudioClock::getNanoseconds();
566 }
567 }
568
569 // return error or framesWritten
Phil Burkc0c70e32017-02-09 13:18:38 -0800570 (void) loopCount;
Phil Burk204a1632017-01-03 17:23:43 -0800571 return (result < 0) ? result : numFrames - framesLeft;
572}
573
574// Write as much data as we can without blocking.
Phil Burk5ed503c2017-02-01 09:38:15 -0800575aaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames,
Phil Burk3316d5e2017-02-15 11:23:01 -0800576 int64_t currentNanoTime, int64_t *wakeTimePtr) {
Phil Burk5204d312017-05-04 17:16:13 -0700577 aaudio_result_t result = processCommands();
578 if (result != AAUDIO_OK) {
579 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800580 }
581
582 if (mAudioEndpoint.isOutputFreeRunning()) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700583 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - update read counter");
Phil Burk204a1632017-01-03 17:23:43 -0800584 // Update data queue based on the timing model.
585 int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime);
586 mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter);
Phil Burk204a1632017-01-03 17:23:43 -0800587 }
588 // TODO else query from endpoint cuz set by actual reader, maybe
589
Phil Burkc0c70e32017-02-09 13:18:38 -0800590 // If the read index passed the write index then consider it an underrun.
591 if (mAudioEndpoint.getFullFramesAvailable() < 0) {
592 mXRunCount++;
Phil Burk204a1632017-01-03 17:23:43 -0800593 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800594
595 // Write some data to the buffer.
Phil Burk71f35bb2017-04-13 16:05:07 -0700596 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - writeNowWithConversion(%d)", numFrames);
Phil Burkc0c70e32017-02-09 13:18:38 -0800597 int32_t framesWritten = writeNowWithConversion(buffer, numFrames);
Phil Burk71f35bb2017-04-13 16:05:07 -0700598 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d",
Phil Burk204a1632017-01-03 17:23:43 -0800599 // numFrames, framesWritten);
600
601 // Calculate an ideal time to wake up.
602 if (wakeTimePtr != nullptr && framesWritten >= 0) {
603 // By default wake up a few milliseconds from now. // TODO review
Phil Burkc0c70e32017-02-09 13:18:38 -0800604 int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND);
605 aaudio_stream_state_t state = getState();
Phil Burk71f35bb2017-04-13 16:05:07 -0700606 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow() - wakeTime based on %s",
Phil Burkc0c70e32017-02-09 13:18:38 -0800607 // AAudio_convertStreamStateToText(state));
608 switch (state) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800609 case AAUDIO_STREAM_STATE_OPEN:
610 case AAUDIO_STREAM_STATE_STARTING:
Phil Burk204a1632017-01-03 17:23:43 -0800611 if (framesWritten != 0) {
612 // Don't wait to write more data. Just prime the buffer.
613 wakeTime = currentNanoTime;
614 }
615 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800616 case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur?
Phil Burk204a1632017-01-03 17:23:43 -0800617 {
618 uint32_t burstSize = mFramesPerBurst;
619 if (burstSize < 32) {
620 burstSize = 32; // TODO review
621 }
622
623 uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize;
624 wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
625 }
626 break;
627 default:
628 break;
629 }
630 *wakeTimePtr = wakeTime;
631
632 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700633// ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu",
Phil Burk204a1632017-01-03 17:23:43 -0800634// (unsigned long long)currentNanoTime,
635// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(),
636// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter());
637 return framesWritten;
638}
639
Phil Burkc0c70e32017-02-09 13:18:38 -0800640
Phil Burkc0c70e32017-02-09 13:18:38 -0800641aaudio_result_t AudioStreamInternal::writeNowWithConversion(const void *buffer,
642 int32_t numFrames) {
Phil Burke572f462017-04-20 13:03:19 -0700643 // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion(%p, %d)",
644 // buffer, numFrames);
Phil Burkc0c70e32017-02-09 13:18:38 -0800645 WrappingBuffer wrappingBuffer;
Phil Burkc0c70e32017-02-09 13:18:38 -0800646 uint8_t *source = (uint8_t *) buffer;
647 int32_t framesLeft = numFrames;
648
649 mAudioEndpoint.getEmptyRoomAvailable(&wrappingBuffer);
650
651 // Read data in one or two parts.
652 int partIndex = 0;
653 while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) {
654 int32_t framesToWrite = framesLeft;
655 int32_t framesAvailable = wrappingBuffer.numFrames[partIndex];
656 if (framesAvailable > 0) {
657 if (framesToWrite > framesAvailable) {
658 framesToWrite = framesAvailable;
659 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700660 int32_t numBytes = getBytesPerFrame() * framesToWrite;
Phil Burke572f462017-04-20 13:03:19 -0700661 int32_t numSamples = framesToWrite * getSamplesPerFrame();
662 // Data conversion.
663 float levelFrom;
664 float levelTo;
665 bool ramping = mVolumeRamp.nextSegment(framesToWrite * getSamplesPerFrame(),
666 &levelFrom, &levelTo);
667 // The formats are validated when the stream is opened so we do not have to
668 // check for illegal combinations here.
669 if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT) {
670 if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) {
671 AAudio_linearRamp(
672 (const float *) source,
673 (float *) wrappingBuffer.data[partIndex],
674 framesToWrite,
675 getSamplesPerFrame(),
676 levelFrom,
677 levelTo);
678 } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) {
679 if (ramping) {
680 AAudioConvert_floatToPcm16(
681 (const float *) source,
682 (int16_t *) wrappingBuffer.data[partIndex],
683 framesToWrite,
684 getSamplesPerFrame(),
685 levelFrom,
686 levelTo);
687 } else {
688 AAudioConvert_floatToPcm16(
689 (const float *) source,
690 (int16_t *) wrappingBuffer.data[partIndex],
691 numSamples,
692 levelTo);
693 }
694 }
695 } else if (getFormat() == AAUDIO_FORMAT_PCM_I16) {
696 if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT) {
697 if (ramping) {
698 AAudioConvert_pcm16ToFloat(
699 (const int16_t *) source,
700 (float *) wrappingBuffer.data[partIndex],
701 framesToWrite,
702 getSamplesPerFrame(),
703 levelFrom,
704 levelTo);
705 } else {
706 AAudioConvert_pcm16ToFloat(
707 (const int16_t *) source,
708 (float *) wrappingBuffer.data[partIndex],
709 numSamples,
710 levelTo);
711 }
712 } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16) {
713 AAudio_linearRamp(
714 (const int16_t *) source,
715 (int16_t *) wrappingBuffer.data[partIndex],
716 framesToWrite,
717 getSamplesPerFrame(),
718 levelFrom,
719 levelTo);
720 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800721 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800722 source += numBytes;
723 framesLeft -= framesToWrite;
Phil Burk71f35bb2017-04-13 16:05:07 -0700724 } else {
725 break;
Phil Burkc0c70e32017-02-09 13:18:38 -0800726 }
727 partIndex++;
728 }
729 int32_t framesWritten = numFrames - framesLeft;
730 mAudioEndpoint.advanceWriteIndex(framesWritten);
731
732 if (framesWritten > 0) {
733 incrementFramesWritten(framesWritten);
734 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700735 // ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::writeNowWithConversion() returns %d", framesWritten);
Phil Burkc0c70e32017-02-09 13:18:38 -0800736 return framesWritten;
737}
738
Phil Burk3316d5e2017-02-15 11:23:01 -0800739void AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) {
Phil Burk204a1632017-01-03 17:23:43 -0800740 mClockModel.processTimestamp( position, time);
741}
742
Phil Burk3316d5e2017-02-15 11:23:01 -0800743aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) {
744 int32_t actualFrames = 0;
Phil Burk71f35bb2017-04-13 16:05:07 -0700745 // Round to the next highest burst size.
746 if (getFramesPerBurst() > 0) {
747 int32_t numBursts = (requestedFrames + getFramesPerBurst() - 1) / getFramesPerBurst();
748 requestedFrames = numBursts * getFramesPerBurst();
749 }
750
Phil Burk3316d5e2017-02-15 11:23:01 -0800751 aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames);
Phil Burk71f35bb2017-04-13 16:05:07 -0700752 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::setBufferSize() %s req = %d => %d",
753 getLocationName(), requestedFrames, actualFrames);
Phil Burk3316d5e2017-02-15 11:23:01 -0800754 if (result < 0) {
755 return result;
756 } else {
757 return (aaudio_result_t) actualFrames;
758 }
Phil Burk204a1632017-01-03 17:23:43 -0800759}
760
Phil Burk3316d5e2017-02-15 11:23:01 -0800761int32_t AudioStreamInternal::getBufferSize() const
Phil Burk204a1632017-01-03 17:23:43 -0800762{
763 return mAudioEndpoint.getBufferSizeInFrames();
764}
765
Phil Burk3316d5e2017-02-15 11:23:01 -0800766int32_t AudioStreamInternal::getBufferCapacity() const
Phil Burk204a1632017-01-03 17:23:43 -0800767{
768 return mAudioEndpoint.getBufferCapacityInFrames();
769}
770
Phil Burk3316d5e2017-02-15 11:23:01 -0800771int32_t AudioStreamInternal::getFramesPerBurst() const
Phil Burk204a1632017-01-03 17:23:43 -0800772{
773 return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
774}
775
Phil Burk3316d5e2017-02-15 11:23:01 -0800776int64_t AudioStreamInternal::getFramesRead()
Phil Burk204a1632017-01-03 17:23:43 -0800777{
Phil Burk3316d5e2017-02-15 11:23:01 -0800778 int64_t framesRead =
Phil Burk204a1632017-01-03 17:23:43 -0800779 mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
780 + mFramesOffsetFromService;
781 // Prevent retrograde motion.
782 if (framesRead < mLastFramesRead) {
783 framesRead = mLastFramesRead;
784 } else {
785 mLastFramesRead = framesRead;
786 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700787 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead);
Phil Burk204a1632017-01-03 17:23:43 -0800788 return framesRead;
789}
790
Phil Burk4c5129b2017-04-28 15:17:32 -0700791int64_t AudioStreamInternal::getFramesWritten()
792{
793 int64_t getFramesWritten = mAudioEndpoint.getDownDataWriteCounter()
794 + mFramesOffsetFromService;
795 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::getFramesWritten() returns %lld", (long long)getFramesWritten);
796 return getFramesWritten;
797}