blob: 19f2300f26c4b01d98f4f4613c9f76c929859756 [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
21#include <stdint.h>
22#include <assert.h>
23
24#include <binder/IServiceManager.h>
Phil Burkdec33ab2017-01-17 14:48:16 -080025#include <utils/Mutex.h>
Phil Burk204a1632017-01-03 17:23:43 -080026
Phil Burk5ed503c2017-02-01 09:38:15 -080027#include <aaudio/AAudio.h>
Phil Burk204a1632017-01-03 17:23:43 -080028
29#include "AudioClock.h"
30#include "AudioEndpointParcelable.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080031#include "binding/AAudioStreamRequest.h"
32#include "binding/AAudioStreamConfiguration.h"
33#include "binding/IAAudioService.h"
34#include "binding/AAudioServiceMessage.h"
Phil Burk204a1632017-01-03 17:23:43 -080035
Phil Burk3df348f2017-02-08 11:41:55 -080036#include "core/AudioStreamBuilder.h"
Phil Burk204a1632017-01-03 17:23:43 -080037#include "AudioStreamInternal.h"
38
39#define LOG_TIMESTAMPS 0
40
41using android::String16;
42using android::IServiceManager;
43using android::defaultServiceManager;
44using android::interface_cast;
Phil Burkdec33ab2017-01-17 14:48:16 -080045using android::Mutex;
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 Burkdec33ab2017-01-17 14:48:16 -080049static android::Mutex gServiceLock;
Phil Burk5ed503c2017-02-01 09:38:15 -080050static sp<IAAudioService> gAAudioService;
Phil Burkdec33ab2017-01-17 14:48:16 -080051
Phil Burk5ed503c2017-02-01 09:38:15 -080052#define AAUDIO_SERVICE_NAME "AAudioService"
Phil Burkdec33ab2017-01-17 14:48:16 -080053
Phil Burk5ed503c2017-02-01 09:38:15 -080054// Helper function to get access to the "AAudioService" service.
Phil Burkdec33ab2017-01-17 14:48:16 -080055// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp
Phil Burk5ed503c2017-02-01 09:38:15 -080056static const sp<IAAudioService> getAAudioService() {
Phil Burkdec33ab2017-01-17 14:48:16 -080057 sp<IBinder> binder;
58 Mutex::Autolock _l(gServiceLock);
Phil Burk5ed503c2017-02-01 09:38:15 -080059 if (gAAudioService == 0) {
Phil Burkdec33ab2017-01-17 14:48:16 -080060 sp<IServiceManager> sm = defaultServiceManager();
61 // Try several times to get the service.
62 int retries = 4;
63 do {
Phil Burk5ed503c2017-02-01 09:38:15 -080064 binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while.
Phil Burkdec33ab2017-01-17 14:48:16 -080065 if (binder != 0) {
66 break;
67 }
68 } while (retries-- > 0);
69
70 if (binder != 0) {
71 // TODO Add linkToDeath() like in frameworks/av/media/libaudioclient/AudioSystem.cpp
72 // TODO Create a DeathRecipient that disconnects all active streams.
Phil Burk5ed503c2017-02-01 09:38:15 -080073 gAAudioService = interface_cast<IAAudioService>(binder);
Phil Burkdec33ab2017-01-17 14:48:16 -080074 } else {
Phil Burk5ed503c2017-02-01 09:38:15 -080075 ALOGE("AudioStreamInternal could not get %s", AAUDIO_SERVICE_NAME);
Phil Burkdec33ab2017-01-17 14:48:16 -080076 }
77 }
Phil Burk5ed503c2017-02-01 09:38:15 -080078 return gAAudioService;
Phil Burk204a1632017-01-03 17:23:43 -080079}
80
81AudioStreamInternal::AudioStreamInternal()
82 : AudioStream()
83 , mClockModel()
84 , mAudioEndpoint()
Phil Burk5ed503c2017-02-01 09:38:15 -080085 , mServiceStreamHandle(AAUDIO_HANDLE_INVALID)
Phil Burk204a1632017-01-03 17:23:43 -080086 , mFramesPerBurst(16)
87{
Phil Burk204a1632017-01-03 17:23:43 -080088}
89
90AudioStreamInternal::~AudioStreamInternal() {
91}
92
Phil Burk5ed503c2017-02-01 09:38:15 -080093aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
Phil Burk204a1632017-01-03 17:23:43 -080094
Phil Burk5ed503c2017-02-01 09:38:15 -080095 const sp<IAAudioService>& service = getAAudioService();
96 if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
Phil Burkdec33ab2017-01-17 14:48:16 -080097
Phil Burk5ed503c2017-02-01 09:38:15 -080098 aaudio_result_t result = AAUDIO_OK;
99 AAudioStreamRequest request;
100 AAudioStreamConfiguration configuration;
Phil Burk204a1632017-01-03 17:23:43 -0800101
102 result = AudioStream::open(builder);
103 if (result < 0) {
104 return result;
105 }
106
Phil Burkdec33ab2017-01-17 14:48:16 -0800107 // Build the request to send to the server.
Phil Burk204a1632017-01-03 17:23:43 -0800108 request.setUserId(getuid());
109 request.setProcessId(getpid());
110 request.getConfiguration().setDeviceId(getDeviceId());
111 request.getConfiguration().setSampleRate(getSampleRate());
112 request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame());
113 request.getConfiguration().setAudioFormat(getFormat());
Phil Burk3df348f2017-02-08 11:41:55 -0800114 request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
Phil Burk204a1632017-01-03 17:23:43 -0800115 request.dump();
116
Phil Burkdec33ab2017-01-17 14:48:16 -0800117 mServiceStreamHandle = service->openStream(request, configuration);
Phil Burk204a1632017-01-03 17:23:43 -0800118 ALOGD("AudioStreamInternal.open(): openStream returned mServiceStreamHandle = 0x%08X",
119 (unsigned int)mServiceStreamHandle);
120 if (mServiceStreamHandle < 0) {
121 result = mServiceStreamHandle;
Phil Burk5ed503c2017-02-01 09:38:15 -0800122 ALOGE("AudioStreamInternal.open(): acquireRealtimeStream aaudio_result_t = 0x%08X", result);
Phil Burk204a1632017-01-03 17:23:43 -0800123 } else {
124 result = configuration.validate();
Phil Burk5ed503c2017-02-01 09:38:15 -0800125 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800126 close();
127 return result;
128 }
129 // Save results of the open.
130 setSampleRate(configuration.getSampleRate());
131 setSamplesPerFrame(configuration.getSamplesPerFrame());
132 setFormat(configuration.getAudioFormat());
133
Phil Burk5ed503c2017-02-01 09:38:15 -0800134 aaudio::AudioEndpointParcelable parcelable;
Phil Burkdec33ab2017-01-17 14:48:16 -0800135 result = service->getStreamDescription(mServiceStreamHandle, parcelable);
Phil Burk5ed503c2017-02-01 09:38:15 -0800136 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800137 ALOGE("AudioStreamInternal.open(): getStreamDescriptor returns %d", result);
Phil Burkdec33ab2017-01-17 14:48:16 -0800138 service->closeStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800139 return result;
140 }
141 // resolve parcelable into a descriptor
142 parcelable.resolve(&mEndpointDescriptor);
143
144 // Configure endpoint based on descriptor.
145 mAudioEndpoint.configure(&mEndpointDescriptor);
146
Phil Burk204a1632017-01-03 17:23:43 -0800147 mFramesPerBurst = mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
148 assert(mFramesPerBurst >= 16);
149 assert(mEndpointDescriptor.downDataQueueDescriptor.capacityInFrames < 10 * 1024);
150
151 mClockModel.setSampleRate(getSampleRate());
152 mClockModel.setFramesPerBurst(mFramesPerBurst);
153
Phil Burk5ed503c2017-02-01 09:38:15 -0800154 setState(AAUDIO_STREAM_STATE_OPEN);
Phil Burk204a1632017-01-03 17:23:43 -0800155 }
156 return result;
157}
158
Phil Burk5ed503c2017-02-01 09:38:15 -0800159aaudio_result_t AudioStreamInternal::close() {
Phil Burk204a1632017-01-03 17:23:43 -0800160 ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", mServiceStreamHandle);
Phil Burk5ed503c2017-02-01 09:38:15 -0800161 if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
162 aaudio_handle_t serviceStreamHandle = mServiceStreamHandle;
163 mServiceStreamHandle = AAUDIO_HANDLE_INVALID;
164 const sp<IAAudioService>& aaudioService = getAAudioService();
165 if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
166 aaudioService->closeStream(serviceStreamHandle);
167 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800168 } else {
Phil Burk5ed503c2017-02-01 09:38:15 -0800169 return AAUDIO_ERROR_INVALID_HANDLE;
Phil Burk204a1632017-01-03 17:23:43 -0800170 }
171}
172
Phil Burk5ed503c2017-02-01 09:38:15 -0800173aaudio_result_t AudioStreamInternal::requestStart()
Phil Burk204a1632017-01-03 17:23:43 -0800174{
Phil Burk5ed503c2017-02-01 09:38:15 -0800175 aaudio_nanoseconds_t startTime;
Phil Burk204a1632017-01-03 17:23:43 -0800176 ALOGD("AudioStreamInternal(): start()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800177 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
178 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800179 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800180 const sp<IAAudioService>& aaudioService = getAAudioService();
181 if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
182 startTime = AAudio_getNanoseconds(AAUDIO_CLOCK_MONOTONIC);
Phil Burk204a1632017-01-03 17:23:43 -0800183 mClockModel.start(startTime);
184 processTimestamp(0, startTime);
Phil Burk5ed503c2017-02-01 09:38:15 -0800185 setState(AAUDIO_STREAM_STATE_STARTING);
186 return aaudioService->startStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800187}
188
Phil Burk5ed503c2017-02-01 09:38:15 -0800189aaudio_result_t AudioStreamInternal::requestPause()
Phil Burk204a1632017-01-03 17:23:43 -0800190{
191 ALOGD("AudioStreamInternal(): pause()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800192 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
193 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800194 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800195 const sp<IAAudioService>& aaudioService = getAAudioService();
196 if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
197 mClockModel.stop(AAudio_getNanoseconds(AAUDIO_CLOCK_MONOTONIC));
198 setState(AAUDIO_STREAM_STATE_PAUSING);
199 return aaudioService->pauseStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800200}
201
Phil Burk5ed503c2017-02-01 09:38:15 -0800202aaudio_result_t AudioStreamInternal::requestFlush() {
Phil Burk204a1632017-01-03 17:23:43 -0800203 ALOGD("AudioStreamInternal(): flush()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800204 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
205 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800206 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800207 const sp<IAAudioService>& aaudioService = getAAudioService();
208 if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
209setState(AAUDIO_STREAM_STATE_FLUSHING);
210 return aaudioService->flushStream(mServiceStreamHandle);
Phil Burk204a1632017-01-03 17:23:43 -0800211}
212
213void AudioStreamInternal::onFlushFromServer() {
214 ALOGD("AudioStreamInternal(): onFlushFromServer()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800215 aaudio_position_frames_t readCounter = mAudioEndpoint.getDownDataReadCounter();
216 aaudio_position_frames_t writeCounter = mAudioEndpoint.getDownDataWriteCounter();
Phil Burk204a1632017-01-03 17:23:43 -0800217 // Bump offset so caller does not see the retrograde motion in getFramesRead().
Phil Burk5ed503c2017-02-01 09:38:15 -0800218 aaudio_position_frames_t framesFlushed = writeCounter - readCounter;
Phil Burk204a1632017-01-03 17:23:43 -0800219 mFramesOffsetFromService += framesFlushed;
220 // Flush written frames by forcing writeCounter to readCounter.
221 // This is because we cannot move the read counter in the hardware.
222 mAudioEndpoint.setDownDataWriteCounter(readCounter);
223}
224
Phil Burk5ed503c2017-02-01 09:38:15 -0800225aaudio_result_t AudioStreamInternal::requestStop()
Phil Burk204a1632017-01-03 17:23:43 -0800226{
227 // TODO better implementation of requestStop()
Phil Burk5ed503c2017-02-01 09:38:15 -0800228 aaudio_result_t result = requestPause();
229 if (result == AAUDIO_OK) {
230 aaudio_stream_state_t state;
231 result = waitForStateChange(AAUDIO_STREAM_STATE_PAUSING,
Phil Burk204a1632017-01-03 17:23:43 -0800232 &state,
Phil Burk5ed503c2017-02-01 09:38:15 -0800233 500 * AAUDIO_NANOS_PER_MILLISECOND);// TODO temporary code
234 if (result == AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800235 result = requestFlush();
236 }
237 }
238 return result;
239}
240
Phil Burk5ed503c2017-02-01 09:38:15 -0800241aaudio_result_t AudioStreamInternal::registerThread() {
Phil Burk204a1632017-01-03 17:23:43 -0800242 ALOGD("AudioStreamInternal(): registerThread()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800243 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
244 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800245 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800246 const sp<IAAudioService>& aaudioService = getAAudioService();
247 if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
248 return aaudioService->registerAudioThread(mServiceStreamHandle,
Phil Burk204a1632017-01-03 17:23:43 -0800249 gettid(),
250 getPeriodNanoseconds());
251}
252
Phil Burk5ed503c2017-02-01 09:38:15 -0800253aaudio_result_t AudioStreamInternal::unregisterThread() {
Phil Burk204a1632017-01-03 17:23:43 -0800254 ALOGD("AudioStreamInternal(): unregisterThread()");
Phil Burk5ed503c2017-02-01 09:38:15 -0800255 if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
256 return AAUDIO_ERROR_INVALID_STATE;
Phil Burk204a1632017-01-03 17:23:43 -0800257 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800258 const sp<IAAudioService>& aaudioService = getAAudioService();
259 if (aaudioService == 0) return AAUDIO_ERROR_NO_SERVICE;
260 return aaudioService->unregisterAudioThread(mServiceStreamHandle, gettid());
Phil Burk204a1632017-01-03 17:23:43 -0800261}
262
Phil Burk5ed503c2017-02-01 09:38:15 -0800263// TODO use aaudio_clockid_t all the way down to AudioClock
264aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
265 aaudio_position_frames_t *framePosition,
266 aaudio_nanoseconds_t *timeNanoseconds) {
Phil Burk204a1632017-01-03 17:23:43 -0800267// TODO implement using real HAL
Phil Burk5ed503c2017-02-01 09:38:15 -0800268 aaudio_nanoseconds_t time = AudioClock::getNanoseconds();
Phil Burk204a1632017-01-03 17:23:43 -0800269 *framePosition = mClockModel.convertTimeToPosition(time);
Phil Burk5ed503c2017-02-01 09:38:15 -0800270 *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay
271 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800272}
273
Phil Burk5ed503c2017-02-01 09:38:15 -0800274aaudio_result_t AudioStreamInternal::updateState() {
Phil Burk204a1632017-01-03 17:23:43 -0800275 return processCommands();
276}
277
278#if LOG_TIMESTAMPS
Phil Burk5ed503c2017-02-01 09:38:15 -0800279static void AudioStreamInternal_LogTimestamp(AAudioServiceMessage &command) {
Phil Burk204a1632017-01-03 17:23:43 -0800280 static int64_t oldPosition = 0;
Phil Burk5ed503c2017-02-01 09:38:15 -0800281 static aaudio_nanoseconds_t oldTime = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800282 int64_t framePosition = command.timestamp.position;
Phil Burk5ed503c2017-02-01 09:38:15 -0800283 aaudio_nanoseconds_t nanoTime = command.timestamp.timestamp;
Phil Burk204a1632017-01-03 17:23:43 -0800284 ALOGD("AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %llu",
285 (long long) framePosition,
286 (long long) nanoTime);
287 int64_t nanosDelta = nanoTime - oldTime;
288 if (nanosDelta > 0 && oldTime > 0) {
289 int64_t framesDelta = framePosition - oldPosition;
Phil Burk5ed503c2017-02-01 09:38:15 -0800290 int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta;
Phil Burk204a1632017-01-03 17:23:43 -0800291 ALOGD("AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta);
292 ALOGD("AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta);
293 ALOGD("AudioStreamInternal() - measured rate = %llu", (unsigned long long) rate);
294 }
295 oldPosition = framePosition;
296 oldTime = nanoTime;
297}
298#endif
299
Phil Burk5ed503c2017-02-01 09:38:15 -0800300aaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) {
301 aaudio_position_frames_t framePosition = 0;
Phil Burk204a1632017-01-03 17:23:43 -0800302#if LOG_TIMESTAMPS
303 AudioStreamInternal_LogTimestamp(command);
304#endif
305 framePosition = message->timestamp.position;
306 processTimestamp(framePosition, message->timestamp.timestamp);
Phil Burk5ed503c2017-02-01 09:38:15 -0800307 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800308}
309
Phil Burk5ed503c2017-02-01 09:38:15 -0800310aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) {
311 aaudio_result_t result = AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800312 ALOGD("processCommands() got event %d", message->event.event);
313 switch (message->event.event) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800314 case AAUDIO_SERVICE_EVENT_STARTED:
315 ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_STARTED");
316 setState(AAUDIO_STREAM_STATE_STARTED);
Phil Burk204a1632017-01-03 17:23:43 -0800317 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800318 case AAUDIO_SERVICE_EVENT_PAUSED:
319 ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_PAUSED");
320 setState(AAUDIO_STREAM_STATE_PAUSED);
Phil Burk204a1632017-01-03 17:23:43 -0800321 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800322 case AAUDIO_SERVICE_EVENT_FLUSHED:
323 ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED");
324 setState(AAUDIO_STREAM_STATE_FLUSHED);
Phil Burk204a1632017-01-03 17:23:43 -0800325 onFlushFromServer();
326 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800327 case AAUDIO_SERVICE_EVENT_CLOSED:
328 ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_CLOSED");
329 setState(AAUDIO_STREAM_STATE_CLOSED);
Phil Burk204a1632017-01-03 17:23:43 -0800330 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800331 case AAUDIO_SERVICE_EVENT_DISCONNECTED:
332 result = AAUDIO_ERROR_DISCONNECTED;
333 ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED");
Phil Burk204a1632017-01-03 17:23:43 -0800334 break;
335 default:
336 ALOGW("WARNING - processCommands() Unrecognized event = %d",
337 (int) message->event.event);
338 break;
339 }
340 return result;
341}
342
343// Process all the commands coming from the server.
Phil Burk5ed503c2017-02-01 09:38:15 -0800344aaudio_result_t AudioStreamInternal::processCommands() {
345 aaudio_result_t result = AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800346
Phil Burk5ed503c2017-02-01 09:38:15 -0800347 while (result == AAUDIO_OK) {
348 AAudioServiceMessage message;
Phil Burk204a1632017-01-03 17:23:43 -0800349 if (mAudioEndpoint.readUpCommand(&message) != 1) {
350 break; // no command this time, no problem
351 }
352 switch (message.what) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800353 case AAudioServiceMessage::code::TIMESTAMP:
Phil Burk204a1632017-01-03 17:23:43 -0800354 result = onTimestampFromServer(&message);
355 break;
356
Phil Burk5ed503c2017-02-01 09:38:15 -0800357 case AAudioServiceMessage::code::EVENT:
Phil Burk204a1632017-01-03 17:23:43 -0800358 result = onEventFromServer(&message);
359 break;
360
361 default:
362 ALOGW("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d",
363 (int) message.what);
Phil Burk5ed503c2017-02-01 09:38:15 -0800364 result = AAUDIO_ERROR_UNEXPECTED_VALUE;
Phil Burk204a1632017-01-03 17:23:43 -0800365 break;
366 }
367 }
368 return result;
369}
370
371// Write the data, block if needed and timeoutMillis > 0
Phil Burk5ed503c2017-02-01 09:38:15 -0800372aaudio_result_t AudioStreamInternal::write(const void *buffer, int32_t numFrames,
373 aaudio_nanoseconds_t timeoutNanoseconds)
Phil Burk204a1632017-01-03 17:23:43 -0800374{
Phil Burk5ed503c2017-02-01 09:38:15 -0800375 aaudio_result_t result = AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800376 uint8_t* source = (uint8_t*)buffer;
Phil Burk5ed503c2017-02-01 09:38:15 -0800377 aaudio_nanoseconds_t currentTimeNanos = AudioClock::getNanoseconds();
378 aaudio_nanoseconds_t deadlineNanos = currentTimeNanos + timeoutNanoseconds;
Phil Burk204a1632017-01-03 17:23:43 -0800379 int32_t framesLeft = numFrames;
380// ALOGD("AudioStreamInternal::write(%p, %d) at time %08llu , mState = %d ------------------",
381// buffer, numFrames, (unsigned long long) currentTimeNanos, mState);
382
383 // Write until all the data has been written or until a timeout occurs.
384 while (framesLeft > 0) {
385 // The call to writeNow() will not block. It will just write as much as it can.
Phil Burk5ed503c2017-02-01 09:38:15 -0800386 aaudio_nanoseconds_t wakeTimeNanos = 0;
387 aaudio_result_t framesWritten = writeNow(source, framesLeft,
Phil Burk204a1632017-01-03 17:23:43 -0800388 currentTimeNanos, &wakeTimeNanos);
389// ALOGD("AudioStreamInternal::write() writeNow() framesLeft = %d --> framesWritten = %d", framesLeft, framesWritten);
390 if (framesWritten < 0) {
391 result = framesWritten;
392 break;
393 }
394 framesLeft -= (int32_t) framesWritten;
395 source += framesWritten * getBytesPerFrame();
396
397 // Should we block?
398 if (timeoutNanoseconds == 0) {
399 break; // don't block
400 } else if (framesLeft > 0) {
401 //ALOGD("AudioStreamInternal:: original wakeTimeNanos %lld", (long long) wakeTimeNanos);
402 // clip the wake time to something reasonable
403 if (wakeTimeNanos < currentTimeNanos) {
404 wakeTimeNanos = currentTimeNanos;
405 }
406 if (wakeTimeNanos > deadlineNanos) {
407 // If we time out, just return the framesWritten so far.
408 ALOGE("AudioStreamInternal::write(): timed out after %lld nanos", (long long) timeoutNanoseconds);
409 break;
410 }
411
412 //ALOGD("AudioStreamInternal:: sleep until %lld, dur = %lld", (long long) wakeTimeNanos,
413 // (long long) (wakeTimeNanos - currentTimeNanos));
414 AudioClock::sleepForNanos(wakeTimeNanos - currentTimeNanos);
415 currentTimeNanos = AudioClock::getNanoseconds();
416 }
417 }
418
419 // return error or framesWritten
420 return (result < 0) ? result : numFrames - framesLeft;
421}
422
423// Write as much data as we can without blocking.
Phil Burk5ed503c2017-02-01 09:38:15 -0800424aaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames,
425 aaudio_nanoseconds_t currentNanoTime, aaudio_nanoseconds_t *wakeTimePtr) {
Phil Burk204a1632017-01-03 17:23:43 -0800426 {
Phil Burk5ed503c2017-02-01 09:38:15 -0800427 aaudio_result_t result = processCommands();
428 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800429 return result;
430 }
431 }
432
433 if (mAudioEndpoint.isOutputFreeRunning()) {
434 // Update data queue based on the timing model.
435 int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime);
436 mAudioEndpoint.setDownDataReadCounter(estimatedReadCounter);
437 // If the read index passed the write index then consider it an underrun.
438 if (mAudioEndpoint.getFullFramesAvailable() < 0) {
439 mXRunCount++;
440 }
441 }
442 // TODO else query from endpoint cuz set by actual reader, maybe
443
444 // Write some data to the buffer.
445 int32_t framesWritten = mAudioEndpoint.writeDataNow(buffer, numFrames);
446 if (framesWritten > 0) {
447 incrementFramesWritten(framesWritten);
448 }
449 //ALOGD("AudioStreamInternal::writeNow() - tried to write %d frames, wrote %d",
450 // numFrames, framesWritten);
451
452 // Calculate an ideal time to wake up.
453 if (wakeTimePtr != nullptr && framesWritten >= 0) {
454 // By default wake up a few milliseconds from now. // TODO review
Phil Burk5ed503c2017-02-01 09:38:15 -0800455 aaudio_nanoseconds_t wakeTime = currentNanoTime + (2 * AAUDIO_NANOS_PER_MILLISECOND);
Phil Burk204a1632017-01-03 17:23:43 -0800456 switch (getState()) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800457 case AAUDIO_STREAM_STATE_OPEN:
458 case AAUDIO_STREAM_STATE_STARTING:
Phil Burk204a1632017-01-03 17:23:43 -0800459 if (framesWritten != 0) {
460 // Don't wait to write more data. Just prime the buffer.
461 wakeTime = currentNanoTime;
462 }
463 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800464 case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur?
Phil Burk204a1632017-01-03 17:23:43 -0800465 {
466 uint32_t burstSize = mFramesPerBurst;
467 if (burstSize < 32) {
468 burstSize = 32; // TODO review
469 }
470
471 uint64_t nextReadPosition = mAudioEndpoint.getDownDataReadCounter() + burstSize;
472 wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
473 }
474 break;
475 default:
476 break;
477 }
478 *wakeTimePtr = wakeTime;
479
480 }
481// ALOGD("AudioStreamInternal::writeNow finished: now = %llu, read# = %llu, wrote# = %llu",
482// (unsigned long long)currentNanoTime,
483// (unsigned long long)mAudioEndpoint.getDownDataReadCounter(),
484// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter());
485 return framesWritten;
486}
487
Phil Burk5ed503c2017-02-01 09:38:15 -0800488aaudio_result_t AudioStreamInternal::waitForStateChange(aaudio_stream_state_t currentState,
489 aaudio_stream_state_t *nextState,
490 aaudio_nanoseconds_t timeoutNanoseconds)
Phil Burk204a1632017-01-03 17:23:43 -0800491
492{
Phil Burk5ed503c2017-02-01 09:38:15 -0800493 aaudio_result_t result = processCommands();
Phil Burk204a1632017-01-03 17:23:43 -0800494// ALOGD("AudioStreamInternal::waitForStateChange() - processCommands() returned %d", result);
Phil Burk5ed503c2017-02-01 09:38:15 -0800495 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800496 return result;
497 }
498 // TODO replace this polling with a timed sleep on a futex on the message queue
Phil Burk5ed503c2017-02-01 09:38:15 -0800499 int32_t durationNanos = 5 * AAUDIO_NANOS_PER_MILLISECOND;
500 aaudio_stream_state_t state = getState();
Phil Burk204a1632017-01-03 17:23:43 -0800501// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state);
502 while (state == currentState && timeoutNanoseconds > 0) {
503 // TODO use futex from service message queue
504 if (durationNanos > timeoutNanoseconds) {
505 durationNanos = timeoutNanoseconds;
506 }
507 AudioClock::sleepForNanos(durationNanos);
508 timeoutNanoseconds -= durationNanos;
509
510 result = processCommands();
Phil Burk5ed503c2017-02-01 09:38:15 -0800511 if (result != AAUDIO_OK) {
Phil Burk204a1632017-01-03 17:23:43 -0800512 return result;
513 }
514
515 state = getState();
516// ALOGD("AudioStreamInternal::waitForStateChange() - state = %d", state);
517 }
518 if (nextState != nullptr) {
519 *nextState = state;
520 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800521 return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800522}
523
524
Phil Burk5ed503c2017-02-01 09:38:15 -0800525void AudioStreamInternal::processTimestamp(uint64_t position, aaudio_nanoseconds_t time) {
Phil Burk204a1632017-01-03 17:23:43 -0800526 mClockModel.processTimestamp( position, time);
527}
528
Phil Burk5ed503c2017-02-01 09:38:15 -0800529aaudio_result_t AudioStreamInternal::setBufferSize(aaudio_size_frames_t requestedFrames,
530 aaudio_size_frames_t *actualFrames) {
Phil Burk204a1632017-01-03 17:23:43 -0800531 return mAudioEndpoint.setBufferSizeInFrames(requestedFrames, actualFrames);
532}
533
Phil Burk5ed503c2017-02-01 09:38:15 -0800534aaudio_size_frames_t AudioStreamInternal::getBufferSize() const
Phil Burk204a1632017-01-03 17:23:43 -0800535{
536 return mAudioEndpoint.getBufferSizeInFrames();
537}
538
Phil Burk5ed503c2017-02-01 09:38:15 -0800539aaudio_size_frames_t AudioStreamInternal::getBufferCapacity() const
Phil Burk204a1632017-01-03 17:23:43 -0800540{
541 return mAudioEndpoint.getBufferCapacityInFrames();
542}
543
Phil Burk5ed503c2017-02-01 09:38:15 -0800544aaudio_size_frames_t AudioStreamInternal::getFramesPerBurst() const
Phil Burk204a1632017-01-03 17:23:43 -0800545{
546 return mEndpointDescriptor.downDataQueueDescriptor.framesPerBurst;
547}
548
Phil Burk5ed503c2017-02-01 09:38:15 -0800549aaudio_position_frames_t AudioStreamInternal::getFramesRead()
Phil Burk204a1632017-01-03 17:23:43 -0800550{
Phil Burk5ed503c2017-02-01 09:38:15 -0800551 aaudio_position_frames_t framesRead =
Phil Burk204a1632017-01-03 17:23:43 -0800552 mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
553 + mFramesOffsetFromService;
554 // Prevent retrograde motion.
555 if (framesRead < mLastFramesRead) {
556 framesRead = mLastFramesRead;
557 } else {
558 mLastFramesRead = framesRead;
559 }
560 ALOGD("AudioStreamInternal::getFramesRead() returns %lld", (long long)framesRead);
561 return framesRead;
562}
563
564// TODO implement getTimestamp