blob: 2dc62a05d209fe3ac8af3348cbc761f2ca2ab660 [file] [log] [blame]
Phil Burk2355edb2016-12-26 13:54:02 -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
Eric Laurentcb4dae22017-07-01 19:39:32 -070017#define LOG_TAG "AAudioServiceStreamBase"
Phil Burk2355edb2016-12-26 13:54:02 -080018//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
Phil Burka5222e22017-07-28 13:31:14 -070021#include <iomanip>
22#include <iostream>
Phil Burkc0c70e32017-02-09 13:18:38 -080023#include <mutex>
Phil Burk2355edb2016-12-26 13:54:02 -080024
Phil Burkc0c70e32017-02-09 13:18:38 -080025#include "binding/IAAudioService.h"
26#include "binding/AAudioServiceMessage.h"
27#include "utility/AudioClock.h"
28
Phil Burk39f02dd2017-08-04 09:13:31 -070029#include "AAudioEndpointManager.h"
30#include "AAudioService.h"
31#include "AAudioServiceEndpoint.h"
Phil Burkc0c70e32017-02-09 13:18:38 -080032#include "AAudioServiceStreamBase.h"
33#include "TimestampScheduler.h"
34
35using namespace android; // TODO just import names needed
36using namespace aaudio; // TODO just import names needed
Phil Burk2355edb2016-12-26 13:54:02 -080037
38/**
Phil Burkc0c70e32017-02-09 13:18:38 -080039 * Base class for streams in the service.
40 * @return
Phil Burk2355edb2016-12-26 13:54:02 -080041 */
42
Phil Burk39f02dd2017-08-04 09:13:31 -070043AAudioServiceStreamBase::AAudioServiceStreamBase(AAudioService &audioService)
Phil Burk2355edb2016-12-26 13:54:02 -080044 : mUpMessageQueue(nullptr)
Phil Burk97350f92017-07-21 15:59:44 -070045 , mAAudioThread()
Phil Burk39f02dd2017-08-04 09:13:31 -070046 , mAtomicTimestamp()
47 , mAudioService(audioService) {
Eric Laurentcb4dae22017-07-01 19:39:32 -070048 mMmapClient.clientUid = -1;
49 mMmapClient.clientPid = -1;
50 mMmapClient.packageName = String16("");
Phil Burk2355edb2016-12-26 13:54:02 -080051}
52
Phil Burk5ed503c2017-02-01 09:38:15 -080053AAudioServiceStreamBase::~AAudioServiceStreamBase() {
Phil Burk98d6d922017-07-06 11:52:45 -070054 ALOGD("AAudioServiceStreamBase::~AAudioServiceStreamBase() destroying %p", this);
Phil Burk5a26e662017-07-07 12:44:48 -070055 // If the stream is deleted when OPEN or in use then audio resources will leak.
56 // This would indicate an internal error. So we want to find this ASAP.
57 LOG_ALWAYS_FATAL_IF(!(mState == AAUDIO_STREAM_STATE_CLOSED
Eric Laurentcb4dae22017-07-01 19:39:32 -070058 || mState == AAUDIO_STREAM_STATE_UNINITIALIZED
59 || mState == AAUDIO_STREAM_STATE_DISCONNECTED),
Phil Burk5a26e662017-07-07 12:44:48 -070060 "service stream still open, state = %d", mState);
Phil Burk2355edb2016-12-26 13:54:02 -080061}
62
Phil Burka5222e22017-07-28 13:31:14 -070063std::string AAudioServiceStreamBase::dumpHeader() {
64 return std::string(" T Handle UId Run State Format Burst Chan Capacity");
65}
66
Phil Burk4501b352017-06-29 18:12:36 -070067std::string AAudioServiceStreamBase::dump() const {
68 std::stringstream result;
69
Phil Burka5222e22017-07-28 13:31:14 -070070 result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
71 << std::dec << std::setfill(' ') ;
72 result << std::setw(6) << mMmapClient.clientUid;
73 result << std::setw(4) << (isRunning() ? "yes" : " no");
74 result << std::setw(6) << mState;
Phil Burk39f02dd2017-08-04 09:13:31 -070075 result << std::setw(7) << getFormat();
Phil Burka5222e22017-07-28 13:31:14 -070076 result << std::setw(6) << mFramesPerBurst;
Phil Burk39f02dd2017-08-04 09:13:31 -070077 result << std::setw(5) << getSamplesPerFrame();
78 result << std::setw(9) << getBufferCapacity();
Phil Burk4501b352017-06-29 18:12:36 -070079
80 return result.str();
81}
82
Phil Burkc0c70e32017-02-09 13:18:38 -080083aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
Phil Burk39f02dd2017-08-04 09:13:31 -070084 aaudio_sharing_mode_t sharingMode) {
85 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
86 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -070087
88 mMmapClient.clientUid = request.getUserId();
89 mMmapClient.clientPid = request.getProcessId();
Phil Burk39f02dd2017-08-04 09:13:31 -070090 mMmapClient.packageName.setTo(String16("")); // TODO What should we do here?
Eric Laurentcb4dae22017-07-01 19:39:32 -070091
Phil Burk39f02dd2017-08-04 09:13:31 -070092 // Limit scope of lock to avoid recursive lock in close().
93 {
94 std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
95 if (mUpMessageQueue != nullptr) {
96 ALOGE("AAudioServiceStreamBase::open() called twice");
97 return AAUDIO_ERROR_INVALID_STATE;
98 }
99
Phil Burkc0c70e32017-02-09 13:18:38 -0800100 mUpMessageQueue = new SharedRingBuffer();
Phil Burk39f02dd2017-08-04 09:13:31 -0700101 result = mUpMessageQueue->allocate(sizeof(AAudioServiceMessage),
102 QUEUE_UP_CAPACITY_COMMANDS);
103 if (result != AAUDIO_OK) {
104 goto error;
105 }
106
107 mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService,
108 request,
109 sharingMode);
110 if (mServiceEndpoint == nullptr) {
111 ALOGE("AAudioServiceStreamBase::open() openEndpoint() failed");
112 result = AAUDIO_ERROR_UNAVAILABLE;
113 goto error;
114 }
115 mFramesPerBurst = mServiceEndpoint->getFramesPerBurst();
116 copyFrom(*mServiceEndpoint);
Phil Burkc0c70e32017-02-09 13:18:38 -0800117 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700118 return result;
119
120error:
121 close();
122 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800123}
Phil Burkdec33ab2017-01-17 14:48:16 -0800124
Phil Burkc0c70e32017-02-09 13:18:38 -0800125aaudio_result_t AAudioServiceStreamBase::close() {
Phil Burk39f02dd2017-08-04 09:13:31 -0700126 aaudio_result_t result = AAUDIO_OK;
127 if (mState == AAUDIO_STREAM_STATE_CLOSED) {
128 return AAUDIO_OK;
129 }
130
131 stop();
132
133 if (mServiceEndpoint == nullptr) {
134 result = AAUDIO_ERROR_INVALID_STATE;
135 } else {
136 mServiceEndpoint->unregisterStream(this);
137 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
138 mEndpointManager.closeEndpoint(mServiceEndpoint);
139 mServiceEndpoint.clear();
140 }
141
142 {
143 std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
Phil Burk98d6d922017-07-06 11:52:45 -0700144 stopTimestampThread();
Phil Burk98d6d922017-07-06 11:52:45 -0700145 delete mUpMessageQueue;
146 mUpMessageQueue = nullptr;
Phil Burk98d6d922017-07-06 11:52:45 -0700147 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700148
149 mState = AAUDIO_STREAM_STATE_CLOSED;
150 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800151}
152
Phil Burk39f02dd2017-08-04 09:13:31 -0700153/**
154 * Start the flow of audio data.
155 *
156 * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
157 */
Phil Burkc0c70e32017-02-09 13:18:38 -0800158aaudio_result_t AAudioServiceStreamBase::start() {
Eric Laurentcb4dae22017-07-01 19:39:32 -0700159 if (isRunning()) {
160 return AAUDIO_OK;
161 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700162
163 if (mServiceEndpoint == nullptr) {
164 ALOGE("AAudioServiceStreamBase::start() missing endpoint");
165 return AAUDIO_ERROR_INVALID_STATE;
166 }
167 mClientHandle = AUDIO_PORT_HANDLE_NONE;
168 aaudio_result_t result = mServiceEndpoint->startStream(this, &mClientHandle);
169 if (result != AAUDIO_OK) {
170 ALOGE("AAudioServiceStreamBase::start() mServiceEndpoint returned %d", result);
171 disconnect();
172 } else {
173 if (result == AAUDIO_OK) {
174 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
175 mState = AAUDIO_STREAM_STATE_STARTED;
176 mThreadEnabled.store(true);
177 result = mAAudioThread.start(this);
178 }
179 }
180 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800181}
182
183aaudio_result_t AAudioServiceStreamBase::pause() {
Phil Burk11e8d332017-05-24 09:59:02 -0700184 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700185 if (!isRunning()) {
186 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800187 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700188 if (mServiceEndpoint == nullptr) {
189 ALOGE("AAudioServiceStreamShared::pause() missing endpoint");
190 return AAUDIO_ERROR_INVALID_STATE;
191 }
192 result = mServiceEndpoint->stopStream(this, mClientHandle);
193 if (result != AAUDIO_OK) {
194 ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result);
195 disconnect(); // TODO should we return or pause Base first?
196 }
197
Eric Laurentcb4dae22017-07-01 19:39:32 -0700198 sendCurrentTimestamp();
199 mThreadEnabled.store(false);
200 result = mAAudioThread.stop();
201 if (result != AAUDIO_OK) {
202 disconnect();
203 return result;
204 }
205 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
Phil Burkc0c70e32017-02-09 13:18:38 -0800206 mState = AAUDIO_STREAM_STATE_PAUSED;
207 return result;
208}
209
Phil Burk71f35bb2017-04-13 16:05:07 -0700210aaudio_result_t AAudioServiceStreamBase::stop() {
Phil Burk11e8d332017-05-24 09:59:02 -0700211 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700212 if (!isRunning()) {
213 return result;
Phil Burk71f35bb2017-04-13 16:05:07 -0700214 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700215
216 if (mServiceEndpoint == nullptr) {
217 ALOGE("AAudioServiceStreamShared::stop() missing endpoint");
218 return AAUDIO_ERROR_INVALID_STATE;
219 }
220
Eric Laurentcb4dae22017-07-01 19:39:32 -0700221 sendCurrentTimestamp(); // warning - this calls a virtual function
222 result = stopTimestampThread();
223 if (result != AAUDIO_OK) {
224 disconnect();
225 return result;
226 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700227
228 // TODO wait for data to be played out
229 result = mServiceEndpoint->stopStream(this, mClientHandle);
230 if (result != AAUDIO_OK) {
231 ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result);
232 disconnect();
233 // TODO what to do with result here?
234 }
235
Eric Laurentcb4dae22017-07-01 19:39:32 -0700236 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
Phil Burk71f35bb2017-04-13 16:05:07 -0700237 mState = AAUDIO_STREAM_STATE_STOPPED;
238 return result;
239}
240
Phil Burk98d6d922017-07-06 11:52:45 -0700241aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() {
242 aaudio_result_t result = AAUDIO_OK;
243 // clear flag that tells thread to loop
244 if (mThreadEnabled.exchange(false)) {
245 result = mAAudioThread.stop();
246 }
247 return result;
248}
249
Phil Burk71f35bb2017-04-13 16:05:07 -0700250aaudio_result_t AAudioServiceStreamBase::flush() {
Phil Burk39f02dd2017-08-04 09:13:31 -0700251 if (mState != AAUDIO_STREAM_STATE_PAUSED) {
252 ALOGE("AAudioServiceStreamBase::flush() stream not paused, state = %s",
253 AAudio_convertStreamStateToText(mState));
254 return AAUDIO_ERROR_INVALID_STATE;
255 }
256 // Data will get flushed when the client receives the FLUSHED event.
Phil Burk71f35bb2017-04-13 16:05:07 -0700257 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
258 mState = AAUDIO_STREAM_STATE_FLUSHED;
259 return AAUDIO_OK;
260}
261
Phil Burkcf5f6d22017-05-26 12:35:07 -0700262// implement Runnable, periodically send timestamps to client
Phil Burkc0c70e32017-02-09 13:18:38 -0800263void AAudioServiceStreamBase::run() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700264 ALOGD("AAudioServiceStreamBase::run() entering ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800265 TimestampScheduler timestampScheduler;
Phil Burk39f02dd2017-08-04 09:13:31 -0700266 timestampScheduler.setBurstPeriod(mFramesPerBurst, getSampleRate());
Phil Burkc0c70e32017-02-09 13:18:38 -0800267 timestampScheduler.start(AudioClock::getNanoseconds());
268 int64_t nextTime = timestampScheduler.nextAbsoluteTime();
269 while(mThreadEnabled.load()) {
270 if (AudioClock::getNanoseconds() >= nextTime) {
271 aaudio_result_t result = sendCurrentTimestamp();
272 if (result != AAUDIO_OK) {
273 break;
274 }
275 nextTime = timestampScheduler.nextAbsoluteTime();
276 } else {
277 // Sleep until it is time to send the next timestamp.
Phil Burk98d6d922017-07-06 11:52:45 -0700278 // TODO Wait for a signal with a timeout so that we can stop more quickly.
Phil Burkc0c70e32017-02-09 13:18:38 -0800279 AudioClock::sleepUntilNanoTime(nextTime);
280 }
281 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700282 ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800283}
284
Phil Burk5ef003b2017-06-30 11:43:37 -0700285void AAudioServiceStreamBase::disconnect() {
286 if (mState != AAUDIO_STREAM_STATE_DISCONNECTED) {
287 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
288 mState = AAUDIO_STREAM_STATE_DISCONNECTED;
289 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800290}
291
292aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
293 double dataDouble,
294 int64_t dataLong) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800295 AAudioServiceMessage command;
296 command.what = AAudioServiceMessage::code::EVENT;
Phil Burk2355edb2016-12-26 13:54:02 -0800297 command.event.event = event;
Phil Burkc0c70e32017-02-09 13:18:38 -0800298 command.event.dataDouble = dataDouble;
299 command.event.dataLong = dataLong;
300 return writeUpMessageQueue(&command);
301}
302
303aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700304 std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
Phil Burk71f35bb2017-04-13 16:05:07 -0700305 if (mUpMessageQueue == nullptr) {
306 ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
307 return AAUDIO_ERROR_NULL;
308 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800309 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
310 if (count != 1) {
311 ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
312 return AAUDIO_ERROR_WOULD_BLOCK;
313 } else {
314 return AAUDIO_OK;
315 }
316}
317
318aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
319 AAudioServiceMessage command;
Phil Burk97350f92017-07-21 15:59:44 -0700320 // Send a timestamp for the clock model.
Phil Burkc0c70e32017-02-09 13:18:38 -0800321 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
322 &command.timestamp.timestamp);
323 if (result == AAUDIO_OK) {
Phil Burk97350f92017-07-21 15:59:44 -0700324 command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE;
Phil Burkc0c70e32017-02-09 13:18:38 -0800325 result = writeUpMessageQueue(&command);
Phil Burk97350f92017-07-21 15:59:44 -0700326
327 if (result == AAUDIO_OK) {
328 // Send a hardware timestamp for presentation time.
329 result = getHardwareTimestamp(&command.timestamp.position,
330 &command.timestamp.timestamp);
331 if (result == AAUDIO_OK) {
332 command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE;
333 result = writeUpMessageQueue(&command);
334 }
335 }
336 }
337
338 if (result == AAUDIO_ERROR_UNAVAILABLE) {
Phil Burk940083c2017-07-17 17:00:02 -0700339 result = AAUDIO_OK; // just not available yet, try again later
Phil Burkc0c70e32017-02-09 13:18:38 -0800340 }
341 return result;
Phil Burk2355edb2016-12-26 13:54:02 -0800342}
343
Phil Burkc0c70e32017-02-09 13:18:38 -0800344/**
345 * Get an immutable description of the in-memory queues
346 * used to communicate with the underlying HAL or Service.
347 */
348aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
349 // Gather information on the message queue.
350 mUpMessageQueue->fillParcelable(parcelable,
351 parcelable.mUpMessageQueueParcelable);
352 return getDownDataDescription(parcelable);
Phil Burk11e8d332017-05-24 09:59:02 -0700353}
Phil Burk39f02dd2017-08-04 09:13:31 -0700354
355void AAudioServiceStreamBase::onVolumeChanged(float volume) {
356 sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume);
357}