blob: 3fc5957fe1ad80f8f1fa08c09b11d2ba9dd6ddc8 [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 Burkc0c70e32017-02-09 13:18:38 -080021#include <mutex>
Phil Burk2355edb2016-12-26 13:54:02 -080022
Phil Burkc0c70e32017-02-09 13:18:38 -080023#include "binding/IAAudioService.h"
24#include "binding/AAudioServiceMessage.h"
25#include "utility/AudioClock.h"
26
27#include "AAudioServiceStreamBase.h"
28#include "TimestampScheduler.h"
29
30using namespace android; // TODO just import names needed
31using namespace aaudio; // TODO just import names needed
Phil Burk2355edb2016-12-26 13:54:02 -080032
33/**
Phil Burkc0c70e32017-02-09 13:18:38 -080034 * Base class for streams in the service.
35 * @return
Phil Burk2355edb2016-12-26 13:54:02 -080036 */
37
Phil Burk5ed503c2017-02-01 09:38:15 -080038AAudioServiceStreamBase::AAudioServiceStreamBase()
Phil Burk2355edb2016-12-26 13:54:02 -080039 : mUpMessageQueue(nullptr)
Phil Burk97350f92017-07-21 15:59:44 -070040 , mAAudioThread()
41 , mAtomicTimestamp() {
Eric Laurentcb4dae22017-07-01 19:39:32 -070042 mMmapClient.clientUid = -1;
43 mMmapClient.clientPid = -1;
44 mMmapClient.packageName = String16("");
Phil Burk2355edb2016-12-26 13:54:02 -080045}
46
Phil Burk5ed503c2017-02-01 09:38:15 -080047AAudioServiceStreamBase::~AAudioServiceStreamBase() {
Phil Burk98d6d922017-07-06 11:52:45 -070048 ALOGD("AAudioServiceStreamBase::~AAudioServiceStreamBase() destroying %p", this);
Phil Burk5a26e662017-07-07 12:44:48 -070049 // If the stream is deleted when OPEN or in use then audio resources will leak.
50 // This would indicate an internal error. So we want to find this ASAP.
51 LOG_ALWAYS_FATAL_IF(!(mState == AAUDIO_STREAM_STATE_CLOSED
Eric Laurentcb4dae22017-07-01 19:39:32 -070052 || mState == AAUDIO_STREAM_STATE_UNINITIALIZED
53 || mState == AAUDIO_STREAM_STATE_DISCONNECTED),
Phil Burk5a26e662017-07-07 12:44:48 -070054 "service stream still open, state = %d", mState);
Phil Burk2355edb2016-12-26 13:54:02 -080055}
56
Phil Burk4501b352017-06-29 18:12:36 -070057std::string AAudioServiceStreamBase::dump() const {
58 std::stringstream result;
59
60 result << " -------- handle = 0x" << std::hex << mHandle << std::dec << "\n";
61 result << " state = " << AAudio_convertStreamStateToText(mState) << "\n";
62 result << " format = " << mAudioFormat << "\n";
63 result << " framesPerBurst = " << mFramesPerBurst << "\n";
64 result << " channelCount = " << mSamplesPerFrame << "\n";
65 result << " capacityFrames = " << mCapacityInFrames << "\n";
Eric Laurentcb4dae22017-07-01 19:39:32 -070066 result << " owner uid = " << mMmapClient.clientUid << "\n";
Phil Burk4501b352017-06-29 18:12:36 -070067
68 return result.str();
69}
70
Phil Burkc0c70e32017-02-09 13:18:38 -080071aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
72 aaudio::AAudioStreamConfiguration &configurationOutput) {
Eric Laurentcb4dae22017-07-01 19:39:32 -070073
74 mMmapClient.clientUid = request.getUserId();
75 mMmapClient.clientPid = request.getProcessId();
76 mMmapClient.packageName.setTo(String16("")); // FIXME what should we do here?
77
Phil Burkc0c70e32017-02-09 13:18:38 -080078 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
79 if (mUpMessageQueue != nullptr) {
80 return AAUDIO_ERROR_INVALID_STATE;
81 } else {
82 mUpMessageQueue = new SharedRingBuffer();
83 return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
84 }
85}
Phil Burkdec33ab2017-01-17 14:48:16 -080086
Phil Burkc0c70e32017-02-09 13:18:38 -080087aaudio_result_t AAudioServiceStreamBase::close() {
Phil Burk98d6d922017-07-06 11:52:45 -070088 if (mState != AAUDIO_STREAM_STATE_CLOSED) {
89 stopTimestampThread();
90 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
91 delete mUpMessageQueue;
92 mUpMessageQueue = nullptr;
93 mState = AAUDIO_STREAM_STATE_CLOSED;
94 }
Phil Burkc0c70e32017-02-09 13:18:38 -080095 return AAUDIO_OK;
96}
97
98aaudio_result_t AAudioServiceStreamBase::start() {
Eric Laurentcb4dae22017-07-01 19:39:32 -070099 if (isRunning()) {
100 return AAUDIO_OK;
101 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800102 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
103 mState = AAUDIO_STREAM_STATE_STARTED;
104 mThreadEnabled.store(true);
105 return mAAudioThread.start(this);
106}
107
108aaudio_result_t AAudioServiceStreamBase::pause() {
Phil Burk11e8d332017-05-24 09:59:02 -0700109 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700110 if (!isRunning()) {
111 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800112 }
Eric Laurentcb4dae22017-07-01 19:39:32 -0700113 sendCurrentTimestamp();
114 mThreadEnabled.store(false);
115 result = mAAudioThread.stop();
116 if (result != AAUDIO_OK) {
117 disconnect();
118 return result;
119 }
120 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
Phil Burkc0c70e32017-02-09 13:18:38 -0800121 mState = AAUDIO_STREAM_STATE_PAUSED;
122 return result;
123}
124
Phil Burk71f35bb2017-04-13 16:05:07 -0700125aaudio_result_t AAudioServiceStreamBase::stop() {
Phil Burk11e8d332017-05-24 09:59:02 -0700126 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700127 if (!isRunning()) {
128 return result;
Phil Burk71f35bb2017-04-13 16:05:07 -0700129 }
Eric Laurentcb4dae22017-07-01 19:39:32 -0700130 // TODO wait for data to be played out
131 sendCurrentTimestamp(); // warning - this calls a virtual function
132 result = stopTimestampThread();
133 if (result != AAUDIO_OK) {
134 disconnect();
135 return result;
136 }
137 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
Phil Burk71f35bb2017-04-13 16:05:07 -0700138 mState = AAUDIO_STREAM_STATE_STOPPED;
139 return result;
140}
141
Phil Burk98d6d922017-07-06 11:52:45 -0700142aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() {
143 aaudio_result_t result = AAUDIO_OK;
144 // clear flag that tells thread to loop
145 if (mThreadEnabled.exchange(false)) {
146 result = mAAudioThread.stop();
147 }
148 return result;
149}
150
Phil Burk71f35bb2017-04-13 16:05:07 -0700151aaudio_result_t AAudioServiceStreamBase::flush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700152 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
153 mState = AAUDIO_STREAM_STATE_FLUSHED;
154 return AAUDIO_OK;
155}
156
Phil Burkcf5f6d22017-05-26 12:35:07 -0700157// implement Runnable, periodically send timestamps to client
Phil Burkc0c70e32017-02-09 13:18:38 -0800158void AAudioServiceStreamBase::run() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700159 ALOGD("AAudioServiceStreamBase::run() entering ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800160 TimestampScheduler timestampScheduler;
161 timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
162 timestampScheduler.start(AudioClock::getNanoseconds());
163 int64_t nextTime = timestampScheduler.nextAbsoluteTime();
164 while(mThreadEnabled.load()) {
165 if (AudioClock::getNanoseconds() >= nextTime) {
166 aaudio_result_t result = sendCurrentTimestamp();
167 if (result != AAUDIO_OK) {
168 break;
169 }
170 nextTime = timestampScheduler.nextAbsoluteTime();
171 } else {
172 // Sleep until it is time to send the next timestamp.
Phil Burk98d6d922017-07-06 11:52:45 -0700173 // TODO Wait for a signal with a timeout so that we can stop more quickly.
Phil Burkc0c70e32017-02-09 13:18:38 -0800174 AudioClock::sleepUntilNanoTime(nextTime);
175 }
176 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700177 ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800178}
179
Phil Burk5ef003b2017-06-30 11:43:37 -0700180void AAudioServiceStreamBase::disconnect() {
181 if (mState != AAUDIO_STREAM_STATE_DISCONNECTED) {
182 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
183 mState = AAUDIO_STREAM_STATE_DISCONNECTED;
184 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800185}
186
187aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
188 double dataDouble,
189 int64_t dataLong) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800190 AAudioServiceMessage command;
191 command.what = AAudioServiceMessage::code::EVENT;
Phil Burk2355edb2016-12-26 13:54:02 -0800192 command.event.event = event;
Phil Burkc0c70e32017-02-09 13:18:38 -0800193 command.event.dataDouble = dataDouble;
194 command.event.dataLong = dataLong;
195 return writeUpMessageQueue(&command);
196}
197
198aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
199 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
Phil Burk71f35bb2017-04-13 16:05:07 -0700200 if (mUpMessageQueue == nullptr) {
201 ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
202 return AAUDIO_ERROR_NULL;
203 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800204 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
205 if (count != 1) {
206 ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
207 return AAUDIO_ERROR_WOULD_BLOCK;
208 } else {
209 return AAUDIO_OK;
210 }
211}
212
213aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
214 AAudioServiceMessage command;
Phil Burk97350f92017-07-21 15:59:44 -0700215 // Send a timestamp for the clock model.
Phil Burkc0c70e32017-02-09 13:18:38 -0800216 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
217 &command.timestamp.timestamp);
218 if (result == AAUDIO_OK) {
Phil Burk97350f92017-07-21 15:59:44 -0700219 command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE;
Phil Burkc0c70e32017-02-09 13:18:38 -0800220 result = writeUpMessageQueue(&command);
Phil Burk97350f92017-07-21 15:59:44 -0700221
222 if (result == AAUDIO_OK) {
223 // Send a hardware timestamp for presentation time.
224 result = getHardwareTimestamp(&command.timestamp.position,
225 &command.timestamp.timestamp);
226 if (result == AAUDIO_OK) {
227 command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE;
228 result = writeUpMessageQueue(&command);
229 }
230 }
231 }
232
233 if (result == AAUDIO_ERROR_UNAVAILABLE) {
Phil Burk940083c2017-07-17 17:00:02 -0700234 result = AAUDIO_OK; // just not available yet, try again later
Phil Burkc0c70e32017-02-09 13:18:38 -0800235 }
236 return result;
Phil Burk2355edb2016-12-26 13:54:02 -0800237}
238
Phil Burkc0c70e32017-02-09 13:18:38 -0800239/**
240 * Get an immutable description of the in-memory queues
241 * used to communicate with the underlying HAL or Service.
242 */
243aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
244 // Gather information on the message queue.
245 mUpMessageQueue->fillParcelable(parcelable,
246 parcelable.mUpMessageQueueParcelable);
247 return getDownDataDescription(parcelable);
Phil Burk11e8d332017-05-24 09:59:02 -0700248}