blob: 701f6985464b32258ee8ed0af8072ee3c5d1a546 [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 Burk4485d412017-05-09 15:55:02 -070021#define ATRACE_TAG ATRACE_TAG_AUDIO
22
Phil Burkc0c70e32017-02-09 13:18:38 -080023#include <stdint.h>
Phil Burk204a1632017-01-03 17:23:43 -080024#include <assert.h>
25
26#include <binder/IServiceManager.h>
27
Phil Burk5ed503c2017-02-01 09:38:15 -080028#include <aaudio/AAudio.h>
Phil Burke4d7bb42017-03-28 11:32:39 -070029#include <utils/String16.h>
Phil Burk4485d412017-05-09 15:55:02 -070030#include <utils/Trace.h>
Phil Burk204a1632017-01-03 17:23:43 -080031
Phil Burkc0c70e32017-02-09 13:18:38 -080032#include "AudioClock.h"
33#include "AudioEndpointParcelable.h"
34#include "binding/AAudioStreamRequest.h"
35#include "binding/AAudioStreamConfiguration.h"
36#include "binding/IAAudioService.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080037#include "binding/AAudioServiceMessage.h"
Phil Burk3df348f2017-02-08 11:41:55 -080038#include "core/AudioStreamBuilder.h"
Phil Burke572f462017-04-20 13:03:19 -070039#include "fifo/FifoBuffer.h"
40#include "utility/LinearRamp.h"
41
Phil Burkc0c70e32017-02-09 13:18:38 -080042#include "AudioStreamInternal.h"
Phil Burk204a1632017-01-03 17:23:43 -080043
Phil Burk204a1632017-01-03 17:23:43 -080044using android::String16;
Phil Burkdec33ab2017-01-17 14:48:16 -080045using android::Mutex;
Phil Burkc0c70e32017-02-09 13:18:38 -080046using android::WrappingBuffer;
Phil Burk204a1632017-01-03 17:23:43 -080047
Phil Burk5ed503c2017-02-01 09:38:15 -080048using namespace aaudio;
Phil Burk204a1632017-01-03 17:23:43 -080049
Phil Burke4d7bb42017-03-28 11:32:39 -070050#define MIN_TIMEOUT_NANOS (1000 * AAUDIO_NANOS_PER_MILLISECOND)
51
52// Wait at least this many times longer than the operation should take.
53#define MIN_TIMEOUT_OPERATIONS 4
54
Phil Burk71f35bb2017-04-13 16:05:07 -070055//static int64_t s_logCounter = 0;
56//#define MYLOG_CONDITION (mInService == true && s_logCounter++ < 500)
57//#define MYLOG_CONDITION (s_logCounter++ < 500000)
58#define MYLOG_CONDITION (1)
Phil Burkdec33ab2017-01-17 14:48:16 -080059
Phil Burk87c9f642017-05-17 07:22:39 -070060#define LOG_TIMESTAMPS 0
61
Phil Burkc0c70e32017-02-09 13:18:38 -080062AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface &serviceInterface, bool inService)
Phil Burk204a1632017-01-03 17:23:43 -080063 : AudioStream()
64 , mClockModel()
65 , mAudioEndpoint()
Phil Burk5ed503c2017-02-01 09:38:15 -080066 , mServiceStreamHandle(AAUDIO_HANDLE_INVALID)
Phil Burk204a1632017-01-03 17:23:43 -080067 , mFramesPerBurst(16)
Phil Burkc0c70e32017-02-09 13:18:38 -080068 , mServiceInterface(serviceInterface)
Phil Burk71f35bb2017-04-13 16:05:07 -070069 , mInService(inService) {
Phil Burk204a1632017-01-03 17:23:43 -080070}
71
72AudioStreamInternal::~AudioStreamInternal() {
73}
74
Phil Burk5ed503c2017-02-01 09:38:15 -080075aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
Phil Burk204a1632017-01-03 17:23:43 -080076
Phil Burk5ed503c2017-02-01 09:38:15 -080077 aaudio_result_t result = AAUDIO_OK;
78 AAudioStreamRequest request;
79 AAudioStreamConfiguration configuration;
Phil Burk204a1632017-01-03 17:23:43 -080080
81 result = AudioStream::open(builder);
82 if (result < 0) {
83 return result;
84 }
85
Phil Burkc0c70e32017-02-09 13:18:38 -080086 // We have to do volume scaling. So we prefer FLOAT format.
87 if (getFormat() == AAUDIO_UNSPECIFIED) {
88 setFormat(AAUDIO_FORMAT_PCM_FLOAT);
89 }
Phil Burk71f35bb2017-04-13 16:05:07 -070090 // Request FLOAT for the shared mixer.
91 request.getConfiguration().setAudioFormat(AAUDIO_FORMAT_PCM_FLOAT);
Phil Burkc0c70e32017-02-09 13:18:38 -080092
Phil Burkdec33ab2017-01-17 14:48:16 -080093 // Build the request to send to the server.
Phil Burk204a1632017-01-03 17:23:43 -080094 request.setUserId(getuid());
95 request.setProcessId(getpid());
Phil Burkc0c70e32017-02-09 13:18:38 -080096 request.setDirection(getDirection());
Phil Burk71f35bb2017-04-13 16:05:07 -070097 request.setSharingModeMatchRequired(isSharingModeMatchRequired());
Phil Burkc0c70e32017-02-09 13:18:38 -080098
Phil Burk204a1632017-01-03 17:23:43 -080099 request.getConfiguration().setDeviceId(getDeviceId());
100 request.getConfiguration().setSampleRate(getSampleRate());
101 request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame());
Phil Burk71f35bb2017-04-13 16:05:07 -0700102 request.getConfiguration().setSharingMode(getSharingMode());
103
Phil Burk3df348f2017-02-08 11:41:55 -0800104 request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
Phil Burk204a1632017-01-03 17:23:43 -0800105
Phil Burkc0c70e32017-02-09 13:18:38 -0800106 mServiceStreamHandle = mServiceInterface.openStream(request, configuration);
Phil Burk204a1632017-01-03 17:23:43 -0800107 if (mServiceStreamHandle < 0) {
108 result = mServiceStreamHandle;
Phil Burk71f35bb2017-04-13 16:05:07 -0700109 ALOGE("AudioStreamInternal.open(): %s openStream() returned %d", getLocationName(), result);
Phil Burk204a1632017-01-03 17:23:43 -0800110 } else {
111 result = configuration.validate();
Phil Burk5ed503c2017-02-01 09:38:15 -0800112 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800113 close();
114 return result;
115 }
116 // Save results of the open.
117 setSampleRate(configuration.getSampleRate());
118 setSamplesPerFrame(configuration.getSamplesPerFrame());
Phil Burkc0c70e32017-02-09 13:18:38 -0800119 setDeviceId(configuration.getDeviceId());
Phil Burk204a1632017-01-03 17:23:43 -0800120
Phil Burkc0c70e32017-02-09 13:18:38 -0800121 // Save device format so we can do format conversion and volume scaling together.
122 mDeviceFormat = configuration.getAudioFormat();
123
124 result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable);
Phil Burk5ed503c2017-02-01 09:38:15 -0800125 if (result != AAUDIO_OK) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700126 ALOGE("AudioStreamInternal.open(): %s getStreamDescriptor returns %d",
127 getLocationName(), result);
Phil Burkc0c70e32017-02-09 13:18:38 -0800128 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800129 return result;
130 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800131
Phil Burk204a1632017-01-03 17:23:43 -0800132 // resolve parcelable into a descriptor
Phil Burkc0c70e32017-02-09 13:18:38 -0800133 result = mEndPointParcelable.resolve(&mEndpointDescriptor);
134 if (result != AAUDIO_OK) {
135 ALOGE("AudioStreamInternal.open(): resolve() returns %d", result);
136 mServiceInterface.closeStream(mServiceStreamHandle);
137 return result;
138 }
Phil Burk204a1632017-01-03 17:23:43 -0800139
140 // Configure endpoint based on descriptor.
141 mAudioEndpoint.configure(&mEndpointDescriptor);
142
Phil Burk87c9f642017-05-17 07:22:39 -0700143 mFramesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
144 int32_t capacity = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames;
Phil Burk71f35bb2017-04-13 16:05:07 -0700145
146 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.open() %s framesPerBurst = %d, capacity = %d",
147 getLocationName(), mFramesPerBurst, capacity);
148 // Validate result from server.
149 if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) {
150 ALOGE("AudioStream::open(): framesPerBurst out of range = %d", mFramesPerBurst);
151 return AAUDIO_ERROR_OUT_OF_RANGE;
152 }
153 if (capacity < mFramesPerBurst || capacity > 32 * 1024) {
154 ALOGE("AudioStream::open(): bufferCapacity out of range = %d", capacity);
155 return AAUDIO_ERROR_OUT_OF_RANGE;
156 }
Phil Burk204a1632017-01-03 17:23:43 -0800157
158 mClockModel.setSampleRate(getSampleRate());
159 mClockModel.setFramesPerBurst(mFramesPerBurst);
160
Phil Burke4d7bb42017-03-28 11:32:39 -0700161 if (getDataCallbackProc()) {
162 mCallbackFrames = builder.getFramesPerDataCallback();
163 if (mCallbackFrames > getBufferCapacity() / 2) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700164 ALOGE("AudioStreamInternal.open(): framesPerCallback too large = %d, capacity = %d",
165 mCallbackFrames, getBufferCapacity());
Phil Burkc0c70e32017-02-09 13:18:38 -0800166 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700167 return AAUDIO_ERROR_OUT_OF_RANGE;
168
169 } else if (mCallbackFrames < 0) {
170 ALOGE("AudioStreamInternal.open(): framesPerCallback negative");
Phil Burkc0c70e32017-02-09 13:18:38 -0800171 mServiceInterface.closeStream(mServiceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700172 return AAUDIO_ERROR_OUT_OF_RANGE;
173
174 }
175 if (mCallbackFrames == AAUDIO_UNSPECIFIED) {
176 mCallbackFrames = mFramesPerBurst;
177 }
178
179 int32_t bytesPerFrame = getSamplesPerFrame()
180 * AAudioConvert_formatToSizeInBytes(getFormat());
181 int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame;
182 mCallbackBuffer = new uint8_t[callbackBufferSize];
183 }
184
Phil Burk5ed503c2017-02-01 09:38:15 -0800185 setState(AAUDIO_STREAM_STATE_OPEN);
Phil Burk204a1632017-01-03 17:23:43 -0800186 }
187 return result;
188}
189
Phil Burk5ed503c2017-02-01 09:38:15 -0800190aaudio_result_t AudioStreamInternal::close() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700191 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X",
192 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800193 if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
Phil Burk4485d412017-05-09 15:55:02 -0700194 // Don't close a stream while it is running.
195 aaudio_stream_state_t currentState = getState();
Phil Burk87c9f642017-05-17 07:22:39 -0700196 if (isActive()) {
Phil Burk4485d412017-05-09 15:55:02 -0700197 requestStop();
198 aaudio_stream_state_t nextState;
199 int64_t timeoutNanoseconds = MIN_TIMEOUT_NANOS;
200 aaudio_result_t result = waitForStateChange(currentState, &nextState,
201 timeoutNanoseconds);
202 if (result != AAUDIO_OK) {
203 ALOGE("AudioStreamInternal::close() waitForStateChange() returned %d %s",
204 result, AAudio_convertResultToText(result));
205 }
206 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800207 aaudio_handle_t serviceStreamHandle = mServiceStreamHandle;
208 mServiceStreamHandle = AAUDIO_HANDLE_INVALID;
Phil Burkc0c70e32017-02-09 13:18:38 -0800209
210 mServiceInterface.closeStream(serviceStreamHandle);
Phil Burke4d7bb42017-03-28 11:32:39 -0700211 delete[] mCallbackBuffer;
Phil Burk4485d412017-05-09 15:55:02 -0700212 mCallbackBuffer = nullptr;
Phil Burkc0c70e32017-02-09 13:18:38 -0800213 return mEndPointParcelable.close();
Phil Burk204a1632017-01-03 17:23:43 -0800214 } else {
Phil Burk5ed503c2017-02-01 09:38:15 -0800215 return AAUDIO_ERROR_INVALID_HANDLE;
Phil Burk204a1632017-01-03 17:23:43 -0800216 }
217}
218
Phil Burkc0c70e32017-02-09 13:18:38 -0800219
Phil Burke4d7bb42017-03-28 11:32:39 -0700220static void *aaudio_callback_thread_proc(void *context)
221{
222 AudioStreamInternal *stream = (AudioStreamInternal *)context;
Phil Burk677d7912017-04-07 12:17:12 -0700223 //LOGD("AudioStreamInternal(): oboe_callback_thread, stream = %p", stream);
Phil Burke4d7bb42017-03-28 11:32:39 -0700224 if (stream != NULL) {
225 return stream->callbackLoop();
226 } else {
227 return NULL;
228 }
229}
230
Phil Burk5ed503c2017-02-01 09:38:15 -0800231aaudio_result_t AudioStreamInternal::requestStart()
Phil Burk204a1632017-01-03 17:23:43 -0800232{
Phil Burk3316d5e2017-02-15 11:23:01 -0800233 int64_t startTime;
Phil Burk71f35bb2017-04-13 16:05:07 -0700234 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): start()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800235 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
236 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800237 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800238
Phil Burk3316d5e2017-02-15 11:23:01 -0800239 startTime = AudioClock::getNanoseconds();
Phil Burk204a1632017-01-03 17:23:43 -0800240 mClockModel.start(startTime);
Phil Burk5ed503c2017-02-01 09:38:15 -0800241 setState(AAUDIO_STREAM_STATE_STARTING);
Phil Burkc0c70e32017-02-09 13:18:38 -0800242 aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);;
Phil Burke4d7bb42017-03-28 11:32:39 -0700243
244 if (result == AAUDIO_OK && getDataCallbackProc() != nullptr) {
245 // Launch the callback loop thread.
246 int64_t periodNanos = mCallbackFrames
247 * AAUDIO_NANOS_PER_SECOND
248 / getSampleRate();
249 mCallbackEnabled.store(true);
250 result = createThread(periodNanos, aaudio_callback_thread_proc, this);
251 }
252 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800253}
254
Phil Burke4d7bb42017-03-28 11:32:39 -0700255int64_t AudioStreamInternal::calculateReasonableTimeout(int32_t framesPerOperation) {
256
257 // Wait for at least a second or some number of callbacks to join the thread.
Phil Burk71f35bb2017-04-13 16:05:07 -0700258 int64_t timeoutNanoseconds = (MIN_TIMEOUT_OPERATIONS
259 * framesPerOperation
260 * AAUDIO_NANOS_PER_SECOND)
261 / getSampleRate();
Phil Burke4d7bb42017-03-28 11:32:39 -0700262 if (timeoutNanoseconds < MIN_TIMEOUT_NANOS) { // arbitrary number of seconds
263 timeoutNanoseconds = MIN_TIMEOUT_NANOS;
264 }
265 return timeoutNanoseconds;
266}
267
Phil Burk87c9f642017-05-17 07:22:39 -0700268int64_t AudioStreamInternal::calculateReasonableTimeout() {
269 return calculateReasonableTimeout(getFramesPerBurst());
270}
271
Phil Burke4d7bb42017-03-28 11:32:39 -0700272aaudio_result_t AudioStreamInternal::stopCallback()
273{
274 if (isDataCallbackActive()) {
275 mCallbackEnabled.store(false);
Phil Burk87c9f642017-05-17 07:22:39 -0700276 return joinThread(NULL);
Phil Burke4d7bb42017-03-28 11:32:39 -0700277 } else {
278 return AAUDIO_OK;
279 }
280}
281
282aaudio_result_t AudioStreamInternal::requestPauseInternal()
Phil Burk204a1632017-01-03 17:23:43 -0800283{
Phil Burk5ed503c2017-02-01 09:38:15 -0800284 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700285 ALOGE("AudioStreamInternal(): requestPauseInternal() mServiceStreamHandle invalid = 0x%08X",
286 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800287 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800288 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800289
Phil Burk3316d5e2017-02-15 11:23:01 -0800290 mClockModel.stop(AudioClock::getNanoseconds());
Phil Burk5ed503c2017-02-01 09:38:15 -0800291 setState(AAUDIO_STREAM_STATE_PAUSING);
Phil Burk71f35bb2017-04-13 16:05:07 -0700292 return mServiceInterface.pauseStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800293}
294
Phil Burke4d7bb42017-03-28 11:32:39 -0700295aaudio_result_t AudioStreamInternal::requestPause()
296{
Phil Burk71f35bb2017-04-13 16:05:07 -0700297 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestPause()", getLocationName());
Phil Burke4d7bb42017-03-28 11:32:39 -0700298 aaudio_result_t result = stopCallback();
299 if (result != AAUDIO_OK) {
300 return result;
301 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700302 result = requestPauseInternal();
303 ALOGD("AudioStreamInternal(): requestPause() returns %d", result);
304 return result;
Phil Burke4d7bb42017-03-28 11:32:39 -0700305}
306
Phil Burk5ed503c2017-02-01 09:38:15 -0800307aaudio_result_t AudioStreamInternal::requestFlush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700308 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): requestFlush()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800309 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700310 ALOGE("AudioStreamInternal(): requestFlush() mServiceStreamHandle invalid = 0x%08X",
311 mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800312 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800313 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800314
Phil Burke4d7bb42017-03-28 11:32:39 -0700315 setState(AAUDIO_STREAM_STATE_FLUSHING);
Phil Burkc0c70e32017-02-09 13:18:38 -0800316 return mServiceInterface.flushStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800317}
318
Phil Burk87c9f642017-05-17 07:22:39 -0700319// TODO for Play only
Phil Burk204a1632017-01-03 17:23:43 -0800320void AudioStreamInternal::onFlushFromServer() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700321 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): onFlushFromServer()");
Phil Burk87c9f642017-05-17 07:22:39 -0700322 int64_t readCounter = mAudioEndpoint.getDataReadCounter();
323 int64_t writeCounter = mAudioEndpoint.getDataWriteCounter();
Phil Burk71f35bb2017-04-13 16:05:07 -0700324
Phil Burk204a1632017-01-03 17:23:43 -0800325 // Bump offset so caller does not see the retrograde motion in getFramesRead().
Phil Burk3316d5e2017-02-15 11:23:01 -0800326 int64_t framesFlushed = writeCounter - readCounter;
Phil Burk204a1632017-01-03 17:23:43 -0800327 mFramesOffsetFromService += framesFlushed;
Phil Burk71f35bb2017-04-13 16:05:07 -0700328
Phil Burk204a1632017-01-03 17:23:43 -0800329 // Flush written frames by forcing writeCounter to readCounter.
330 // This is because we cannot move the read counter in the hardware.
Phil Burk87c9f642017-05-17 07:22:39 -0700331 mAudioEndpoint.setDataWriteCounter(readCounter);
Phil Burk204a1632017-01-03 17:23:43 -0800332}
333
Phil Burk71f35bb2017-04-13 16:05:07 -0700334aaudio_result_t AudioStreamInternal::requestStopInternal()
335{
336 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
337 ALOGE("AudioStreamInternal(): requestStopInternal() mServiceStreamHandle invalid = 0x%08X",
338 mServiceStreamHandle);
339 return AAUDIO_ERROR_INVALID_STATE;
340 }
341
342 mClockModel.stop(AudioClock::getNanoseconds());
343 setState(AAUDIO_STREAM_STATE_STOPPING);
344 return mServiceInterface.stopStream(mServiceStreamHandle);
345}
346
Phil Burk5ed503c2017-02-01 09:38:15 -0800347aaudio_result_t AudioStreamInternal::requestStop()
Phil Burk204a1632017-01-03 17:23:43 -0800348{
Phil Burk71f35bb2017-04-13 16:05:07 -0700349 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal(): %s requestStop()", getLocationName());
350 aaudio_result_t result = stopCallback();
351 if (result != AAUDIO_OK) {
352 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800353 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700354 result = requestStopInternal();
355 ALOGD("AudioStreamInternal(): requestStop() returns %d", result);
Phil Burk204a1632017-01-03 17:23:43 -0800356 return result;
357}
358
Phil Burk5ed503c2017-02-01 09:38:15 -0800359aaudio_result_t AudioStreamInternal::registerThread() {
Phil Burk5ed503c2017-02-01 09:38:15 -0800360 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
361 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800362 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800363 return mServiceInterface.registerAudioThread(mServiceStreamHandle,
364 getpid(),
365 gettid(),
366 getPeriodNanoseconds());
Phil Burk204a1632017-01-03 17:23:43 -0800367}
368
Phil Burk5ed503c2017-02-01 09:38:15 -0800369aaudio_result_t AudioStreamInternal::unregisterThread() {
Phil Burk5ed503c2017-02-01 09:38:15 -0800370 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
371 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800372 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800373 return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, getpid(), gettid());
Phil Burk204a1632017-01-03 17:23:43 -0800374}
375
Phil Burk5ed503c2017-02-01 09:38:15 -0800376aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
Phil Burk3316d5e2017-02-15 11:23:01 -0800377 int64_t *framePosition,
378 int64_t *timeNanoseconds) {
Phil Burk5204d312017-05-04 17:16:13 -0700379 // TODO Generate in server and pass to client. Return latest.
Phil Burk3316d5e2017-02-15 11:23:01 -0800380 int64_t time = AudioClock::getNanoseconds();
Phil Burk204a1632017-01-03 17:23:43 -0800381 *framePosition = mClockModel.convertTimeToPosition(time);
Phil Burk87c9f642017-05-17 07:22:39 -0700382 // TODO Get a more accurate timestamp from the service. This code just adds a fudge factor.
383 *timeNanoseconds = time + (6 * AAUDIO_NANOS_PER_MILLISECOND);
Phil Burk5ed503c2017-02-01 09:38:15 -0800384 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800385}
386
Phil Burke4d7bb42017-03-28 11:32:39 -0700387aaudio_result_t AudioStreamInternal::updateStateWhileWaiting() {
388 if (isDataCallbackActive()) {
389 return AAUDIO_OK; // state is getting updated by the callback thread read/write call
390 }
Phil Burk204a1632017-01-03 17:23:43 -0800391 return processCommands();
392}
393
394#if LOG_TIMESTAMPS
Phil Burk87c9f642017-05-17 07:22:39 -0700395static void AudioStreamInternal_logTimestamp(AAudioServiceMessage &command) {
Phil Burk204a1632017-01-03 17:23:43 -0800396 static int64_t oldPosition = 0;
Phil Burk3316d5e2017-02-15 11:23:01 -0800397 static int64_t oldTime = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800398 int64_t framePosition = command.timestamp.position;
Phil Burk3316d5e2017-02-15 11:23:01 -0800399 int64_t nanoTime = command.timestamp.timestamp;
Phil Burk71f35bb2017-04-13 16:05:07 -0700400 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu",
Phil Burk204a1632017-01-03 17:23:43 -0800401 (long long) framePosition,
402 (long long) nanoTime);
403 int64_t nanosDelta = nanoTime - oldTime;
404 if (nanosDelta > 0 && oldTime > 0) {
405 int64_t framesDelta = framePosition - oldPosition;
Phil Burk5ed503c2017-02-01 09:38:15 -0800406 int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta;
Phil Burk71f35bb2017-04-13 16:05:07 -0700407 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta);
408 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta);
409 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate);
Phil Burk204a1632017-01-03 17:23:43 -0800410 }
411 oldPosition = framePosition;
412 oldTime = nanoTime;
413}
414#endif
415
Phil Burk5ed503c2017-02-01 09:38:15 -0800416aaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) {
Phil Burk204a1632017-01-03 17:23:43 -0800417#if LOG_TIMESTAMPS
Phil Burk87c9f642017-05-17 07:22:39 -0700418 AudioStreamInternal_logTimestamp(*message);
Phil Burk204a1632017-01-03 17:23:43 -0800419#endif
Phil Burk87c9f642017-05-17 07:22:39 -0700420 processTimestamp(message->timestamp.position, message->timestamp.timestamp);
Phil Burk5ed503c2017-02-01 09:38:15 -0800421 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800422}
423
Phil Burk5ed503c2017-02-01 09:38:15 -0800424aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) {
425 aaudio_result_t result = AAUDIO_OK;
Phil Burk71f35bb2017-04-13 16:05:07 -0700426 ALOGD_IF(MYLOG_CONDITION, "processCommands() got event %d", message->event.event);
Phil Burk204a1632017-01-03 17:23:43 -0800427 switch (message->event.event) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800428 case AAUDIO_SERVICE_EVENT_STARTED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700429 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STARTED");
Phil Burk87c9f642017-05-17 07:22:39 -0700430 if (getState() == AAUDIO_STREAM_STATE_STARTING) {
431 setState(AAUDIO_STREAM_STATE_STARTED);
432 }
Phil Burk204a1632017-01-03 17:23:43 -0800433 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800434 case AAUDIO_SERVICE_EVENT_PAUSED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700435 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_PAUSED");
Phil Burk87c9f642017-05-17 07:22:39 -0700436 if (getState() == AAUDIO_STREAM_STATE_PAUSING) {
437 setState(AAUDIO_STREAM_STATE_PAUSED);
438 }
Phil Burk204a1632017-01-03 17:23:43 -0800439 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700440 case AAUDIO_SERVICE_EVENT_STOPPED:
441 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_STOPPED");
Phil Burk87c9f642017-05-17 07:22:39 -0700442 if (getState() == AAUDIO_STREAM_STATE_STOPPING) {
443 setState(AAUDIO_STREAM_STATE_STOPPED);
444 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700445 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800446 case AAUDIO_SERVICE_EVENT_FLUSHED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700447 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED");
Phil Burk87c9f642017-05-17 07:22:39 -0700448 if (getState() == AAUDIO_STREAM_STATE_FLUSHING) {
449 setState(AAUDIO_STREAM_STATE_FLUSHED);
450 onFlushFromServer();
451 }
Phil Burk204a1632017-01-03 17:23:43 -0800452 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800453 case AAUDIO_SERVICE_EVENT_CLOSED:
Phil Burk71f35bb2017-04-13 16:05:07 -0700454 ALOGD_IF(MYLOG_CONDITION, "processCommands() got AAUDIO_SERVICE_EVENT_CLOSED");
Phil Burk5ed503c2017-02-01 09:38:15 -0800455 setState(AAUDIO_STREAM_STATE_CLOSED);
Phil Burk204a1632017-01-03 17:23:43 -0800456 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800457 case AAUDIO_SERVICE_EVENT_DISCONNECTED:
458 result = AAUDIO_ERROR_DISCONNECTED;
Phil Burkc0c70e32017-02-09 13:18:38 -0800459 setState(AAUDIO_STREAM_STATE_DISCONNECTED);
Phil Burk5ed503c2017-02-01 09:38:15 -0800460 ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED");
Phil Burk204a1632017-01-03 17:23:43 -0800461 break;
Phil Burkc0c70e32017-02-09 13:18:38 -0800462 case AAUDIO_SERVICE_EVENT_VOLUME:
Phil Burke572f462017-04-20 13:03:19 -0700463 mVolumeRamp.setTarget((float) message->event.dataDouble);
464 ALOGD_IF(MYLOG_CONDITION, "processCommands() AAUDIO_SERVICE_EVENT_VOLUME %f",
465 message->event.dataDouble);
Phil Burkc0c70e32017-02-09 13:18:38 -0800466 break;
Phil Burk204a1632017-01-03 17:23:43 -0800467 default:
468 ALOGW("WARNING - processCommands() Unrecognized event = %d",
469 (int) message->event.event);
470 break;
471 }
472 return result;
473}
474
475// Process all the commands coming from the server.
Phil Burk5ed503c2017-02-01 09:38:15 -0800476aaudio_result_t AudioStreamInternal::processCommands() {
477 aaudio_result_t result = AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800478
Phil Burk5ed503c2017-02-01 09:38:15 -0800479 while (result == AAUDIO_OK) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700480 //ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::processCommands() - looping, %d", result);
Phil Burk5ed503c2017-02-01 09:38:15 -0800481 AAudioServiceMessage message;
Phil Burk204a1632017-01-03 17:23:43 -0800482 if (mAudioEndpoint.readUpCommand(&message) != 1) {
483 break; // no command this time, no problem
484 }
485 switch (message.what) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800486 case AAudioServiceMessage::code::TIMESTAMP:
Phil Burk204a1632017-01-03 17:23:43 -0800487 result = onTimestampFromServer(&message);
488 break;
489
Phil Burk5ed503c2017-02-01 09:38:15 -0800490 case AAudioServiceMessage::code::EVENT:
Phil Burk204a1632017-01-03 17:23:43 -0800491 result = onEventFromServer(&message);
492 break;
493
494 default:
Phil Burk71f35bb2017-04-13 16:05:07 -0700495 ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d",
Phil Burk204a1632017-01-03 17:23:43 -0800496 (int) message.what);
Phil Burk5ed503c2017-02-01 09:38:15 -0800497 result = AAUDIO_ERROR_UNEXPECTED_VALUE;
Phil Burk204a1632017-01-03 17:23:43 -0800498 break;
499 }
500 }
501 return result;
502}
503
Phil Burk87c9f642017-05-17 07:22:39 -0700504// Read or write the data, block if needed and timeoutMillis > 0
505aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames,
506 int64_t timeoutNanoseconds)
Phil Burk204a1632017-01-03 17:23:43 -0800507{
Phil Burk4485d412017-05-09 15:55:02 -0700508 const char * traceName = (mInService) ? "aaWrtS" : "aaWrtC";
509 ATRACE_BEGIN(traceName);
Phil Burk5ed503c2017-02-01 09:38:15 -0800510 aaudio_result_t result = AAUDIO_OK;
Phil Burkc0c70e32017-02-09 13:18:38 -0800511 int32_t loopCount = 0;
Phil Burk87c9f642017-05-17 07:22:39 -0700512 uint8_t* audioData = (uint8_t*)buffer;
Phil Burk3316d5e2017-02-15 11:23:01 -0800513 int64_t currentTimeNanos = AudioClock::getNanoseconds();
514 int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds;
Phil Burk204a1632017-01-03 17:23:43 -0800515 int32_t framesLeft = numFrames;
Phil Burk204a1632017-01-03 17:23:43 -0800516
Phil Burk4485d412017-05-09 15:55:02 -0700517 int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable();
518 if (ATRACE_ENABLED()) {
519 const char * traceName = (mInService) ? "aaFullS" : "aaFullC";
520 ATRACE_INT(traceName, fullFrames);
521 }
522
Phil Burk87c9f642017-05-17 07:22:39 -0700523 // Loop until all the data has been processed or until a timeout occurs.
Phil Burk204a1632017-01-03 17:23:43 -0800524 while (framesLeft > 0) {
Phil Burk87c9f642017-05-17 07:22:39 -0700525 // The call to processDataNow() will not block. It will just read as much as it can.
Phil Burk3316d5e2017-02-15 11:23:01 -0800526 int64_t wakeTimeNanos = 0;
Phil Burk87c9f642017-05-17 07:22:39 -0700527 aaudio_result_t framesProcessed = processDataNow(audioData, framesLeft,
528 currentTimeNanos, &wakeTimeNanos);
529 if (framesProcessed < 0) {
530 ALOGE("AudioStreamInternal::processData() loop: framesProcessed = %d", framesProcessed);
531 result = framesProcessed;
Phil Burk204a1632017-01-03 17:23:43 -0800532 break;
533 }
Phil Burk87c9f642017-05-17 07:22:39 -0700534 framesLeft -= (int32_t) framesProcessed;
535 audioData += framesProcessed * getBytesPerFrame();
Phil Burk204a1632017-01-03 17:23:43 -0800536
537 // Should we block?
538 if (timeoutNanoseconds == 0) {
539 break; // don't block
540 } else if (framesLeft > 0) {
Phil Burk204a1632017-01-03 17:23:43 -0800541 // clip the wake time to something reasonable
542 if (wakeTimeNanos < currentTimeNanos) {
543 wakeTimeNanos = currentTimeNanos;
544 }
545 if (wakeTimeNanos > deadlineNanos) {
546 // If we time out, just return the framesWritten so far.
Phil Burk87c9f642017-05-17 07:22:39 -0700547 ALOGE("AudioStreamInternal::processData(): timed out after %lld nanos",
Phil Burkc0c70e32017-02-09 13:18:38 -0800548 (long long) timeoutNanoseconds);
Phil Burk87c9f642017-05-17 07:22:39 -0700549 ALOGE("AudioStreamInternal::processData(): wakeTime = %lld, deadline = %lld nanos",
550 (long long) wakeTimeNanos, (long long) deadlineNanos);
551 ALOGE("AudioStreamInternal::processData(): past deadline by %d micros",
552 (int)((wakeTimeNanos - deadlineNanos) / AAUDIO_NANOS_PER_MICROSECOND));
553
Phil Burk204a1632017-01-03 17:23:43 -0800554 break;
555 }
556
Phil Burk71f35bb2017-04-13 16:05:07 -0700557 int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos;
Phil Burk87c9f642017-05-17 07:22:39 -0700558 //ALOGE("AudioStreamInternal::processData(): sleep for %d micros",
559 // (int)(sleepForNanos / AAUDIO_NANOS_PER_MICROSECOND));
Phil Burk71f35bb2017-04-13 16:05:07 -0700560 AudioClock::sleepForNanos(sleepForNanos);
Phil Burk204a1632017-01-03 17:23:43 -0800561 currentTimeNanos = AudioClock::getNanoseconds();
562 }
563 }
564
Phil Burk87c9f642017-05-17 07:22:39 -0700565 // return error or framesProcessed
Phil Burkc0c70e32017-02-09 13:18:38 -0800566 (void) loopCount;
Phil Burk4485d412017-05-09 15:55:02 -0700567 ATRACE_END();
Phil Burk204a1632017-01-03 17:23:43 -0800568 return (result < 0) ? result : numFrames - framesLeft;
569}
570
Phil Burk3316d5e2017-02-15 11:23:01 -0800571void AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) {
Phil Burk87c9f642017-05-17 07:22:39 -0700572 mClockModel.processTimestamp(position, time);
Phil Burk204a1632017-01-03 17:23:43 -0800573}
574
Phil Burk3316d5e2017-02-15 11:23:01 -0800575aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) {
576 int32_t actualFrames = 0;
Phil Burk71f35bb2017-04-13 16:05:07 -0700577 // Round to the next highest burst size.
578 if (getFramesPerBurst() > 0) {
579 int32_t numBursts = (requestedFrames + getFramesPerBurst() - 1) / getFramesPerBurst();
580 requestedFrames = numBursts * getFramesPerBurst();
581 }
582
Phil Burk3316d5e2017-02-15 11:23:01 -0800583 aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames);
Phil Burk71f35bb2017-04-13 16:05:07 -0700584 ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::setBufferSize() %s req = %d => %d",
585 getLocationName(), requestedFrames, actualFrames);
Phil Burk3316d5e2017-02-15 11:23:01 -0800586 if (result < 0) {
587 return result;
588 } else {
589 return (aaudio_result_t) actualFrames;
590 }
Phil Burk204a1632017-01-03 17:23:43 -0800591}
592
Phil Burk87c9f642017-05-17 07:22:39 -0700593int32_t AudioStreamInternal::getBufferSize() const {
Phil Burk204a1632017-01-03 17:23:43 -0800594 return mAudioEndpoint.getBufferSizeInFrames();
595}
596
Phil Burk87c9f642017-05-17 07:22:39 -0700597int32_t AudioStreamInternal::getBufferCapacity() const {
Phil Burk204a1632017-01-03 17:23:43 -0800598 return mAudioEndpoint.getBufferCapacityInFrames();
599}
600
Phil Burk87c9f642017-05-17 07:22:39 -0700601int32_t AudioStreamInternal::getFramesPerBurst() const {
602 return mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
Phil Burk204a1632017-01-03 17:23:43 -0800603}
604
Phil Burk87c9f642017-05-17 07:22:39 -0700605aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) {
606 return AudioStream::joinThread(returnArg, calculateReasonableTimeout(getFramesPerBurst()));
Phil Burk4c5129b2017-04-28 15:17:32 -0700607}