blob: e5f916c29f16f6435472b668ff710b093da9259f [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
29#include "AAudioServiceStreamBase.h"
30#include "TimestampScheduler.h"
31
32using namespace android; // TODO just import names needed
33using namespace aaudio; // TODO just import names needed
Phil Burk2355edb2016-12-26 13:54:02 -080034
35/**
Phil Burkc0c70e32017-02-09 13:18:38 -080036 * Base class for streams in the service.
37 * @return
Phil Burk2355edb2016-12-26 13:54:02 -080038 */
39
Phil Burk5ed503c2017-02-01 09:38:15 -080040AAudioServiceStreamBase::AAudioServiceStreamBase()
Phil Burk2355edb2016-12-26 13:54:02 -080041 : mUpMessageQueue(nullptr)
Phil Burk97350f92017-07-21 15:59:44 -070042 , mAAudioThread()
43 , mAtomicTimestamp() {
Eric Laurentcb4dae22017-07-01 19:39:32 -070044 mMmapClient.clientUid = -1;
45 mMmapClient.clientPid = -1;
46 mMmapClient.packageName = String16("");
Phil Burk2355edb2016-12-26 13:54:02 -080047}
48
Phil Burk5ed503c2017-02-01 09:38:15 -080049AAudioServiceStreamBase::~AAudioServiceStreamBase() {
Phil Burk98d6d922017-07-06 11:52:45 -070050 ALOGD("AAudioServiceStreamBase::~AAudioServiceStreamBase() destroying %p", this);
Phil Burk5a26e662017-07-07 12:44:48 -070051 // If the stream is deleted when OPEN or in use then audio resources will leak.
52 // This would indicate an internal error. So we want to find this ASAP.
53 LOG_ALWAYS_FATAL_IF(!(mState == AAUDIO_STREAM_STATE_CLOSED
Eric Laurentcb4dae22017-07-01 19:39:32 -070054 || mState == AAUDIO_STREAM_STATE_UNINITIALIZED
55 || mState == AAUDIO_STREAM_STATE_DISCONNECTED),
Phil Burk5a26e662017-07-07 12:44:48 -070056 "service stream still open, state = %d", mState);
Phil Burk2355edb2016-12-26 13:54:02 -080057}
58
Phil Burka5222e22017-07-28 13:31:14 -070059std::string AAudioServiceStreamBase::dumpHeader() {
60 return std::string(" T Handle UId Run State Format Burst Chan Capacity");
61}
62
Phil Burk4501b352017-06-29 18:12:36 -070063std::string AAudioServiceStreamBase::dump() const {
64 std::stringstream result;
65
Phil Burka5222e22017-07-28 13:31:14 -070066 result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
67 << std::dec << std::setfill(' ') ;
68 result << std::setw(6) << mMmapClient.clientUid;
69 result << std::setw(4) << (isRunning() ? "yes" : " no");
70 result << std::setw(6) << mState;
71 result << std::setw(7) << mAudioFormat;
72 result << std::setw(6) << mFramesPerBurst;
73 result << std::setw(5) << mSamplesPerFrame;
74 result << std::setw(9) << mCapacityInFrames;
Phil Burk4501b352017-06-29 18:12:36 -070075
76 return result.str();
77}
78
Phil Burkc0c70e32017-02-09 13:18:38 -080079aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
80 aaudio::AAudioStreamConfiguration &configurationOutput) {
Eric Laurentcb4dae22017-07-01 19:39:32 -070081
82 mMmapClient.clientUid = request.getUserId();
83 mMmapClient.clientPid = request.getProcessId();
84 mMmapClient.packageName.setTo(String16("")); // FIXME what should we do here?
85
Phil Burkc0c70e32017-02-09 13:18:38 -080086 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
87 if (mUpMessageQueue != nullptr) {
88 return AAUDIO_ERROR_INVALID_STATE;
89 } else {
90 mUpMessageQueue = new SharedRingBuffer();
91 return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
92 }
93}
Phil Burkdec33ab2017-01-17 14:48:16 -080094
Phil Burkc0c70e32017-02-09 13:18:38 -080095aaudio_result_t AAudioServiceStreamBase::close() {
Phil Burk98d6d922017-07-06 11:52:45 -070096 if (mState != AAUDIO_STREAM_STATE_CLOSED) {
97 stopTimestampThread();
98 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
99 delete mUpMessageQueue;
100 mUpMessageQueue = nullptr;
101 mState = AAUDIO_STREAM_STATE_CLOSED;
102 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800103 return AAUDIO_OK;
104}
105
106aaudio_result_t AAudioServiceStreamBase::start() {
Eric Laurentcb4dae22017-07-01 19:39:32 -0700107 if (isRunning()) {
108 return AAUDIO_OK;
109 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800110 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
111 mState = AAUDIO_STREAM_STATE_STARTED;
112 mThreadEnabled.store(true);
113 return mAAudioThread.start(this);
114}
115
116aaudio_result_t AAudioServiceStreamBase::pause() {
Phil Burk11e8d332017-05-24 09:59:02 -0700117 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700118 if (!isRunning()) {
119 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800120 }
Eric Laurentcb4dae22017-07-01 19:39:32 -0700121 sendCurrentTimestamp();
122 mThreadEnabled.store(false);
123 result = mAAudioThread.stop();
124 if (result != AAUDIO_OK) {
125 disconnect();
126 return result;
127 }
128 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
Phil Burkc0c70e32017-02-09 13:18:38 -0800129 mState = AAUDIO_STREAM_STATE_PAUSED;
130 return result;
131}
132
Phil Burk71f35bb2017-04-13 16:05:07 -0700133aaudio_result_t AAudioServiceStreamBase::stop() {
Phil Burk11e8d332017-05-24 09:59:02 -0700134 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700135 if (!isRunning()) {
136 return result;
Phil Burk71f35bb2017-04-13 16:05:07 -0700137 }
Eric Laurentcb4dae22017-07-01 19:39:32 -0700138 // TODO wait for data to be played out
139 sendCurrentTimestamp(); // warning - this calls a virtual function
140 result = stopTimestampThread();
141 if (result != AAUDIO_OK) {
142 disconnect();
143 return result;
144 }
145 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
Phil Burk71f35bb2017-04-13 16:05:07 -0700146 mState = AAUDIO_STREAM_STATE_STOPPED;
147 return result;
148}
149
Phil Burk98d6d922017-07-06 11:52:45 -0700150aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() {
151 aaudio_result_t result = AAUDIO_OK;
152 // clear flag that tells thread to loop
153 if (mThreadEnabled.exchange(false)) {
154 result = mAAudioThread.stop();
155 }
156 return result;
157}
158
Phil Burk71f35bb2017-04-13 16:05:07 -0700159aaudio_result_t AAudioServiceStreamBase::flush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700160 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
161 mState = AAUDIO_STREAM_STATE_FLUSHED;
162 return AAUDIO_OK;
163}
164
Phil Burkcf5f6d22017-05-26 12:35:07 -0700165// implement Runnable, periodically send timestamps to client
Phil Burkc0c70e32017-02-09 13:18:38 -0800166void AAudioServiceStreamBase::run() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700167 ALOGD("AAudioServiceStreamBase::run() entering ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800168 TimestampScheduler timestampScheduler;
169 timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
170 timestampScheduler.start(AudioClock::getNanoseconds());
171 int64_t nextTime = timestampScheduler.nextAbsoluteTime();
172 while(mThreadEnabled.load()) {
173 if (AudioClock::getNanoseconds() >= nextTime) {
174 aaudio_result_t result = sendCurrentTimestamp();
175 if (result != AAUDIO_OK) {
176 break;
177 }
178 nextTime = timestampScheduler.nextAbsoluteTime();
179 } else {
180 // Sleep until it is time to send the next timestamp.
Phil Burk98d6d922017-07-06 11:52:45 -0700181 // TODO Wait for a signal with a timeout so that we can stop more quickly.
Phil Burkc0c70e32017-02-09 13:18:38 -0800182 AudioClock::sleepUntilNanoTime(nextTime);
183 }
184 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700185 ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800186}
187
Phil Burk5ef003b2017-06-30 11:43:37 -0700188void AAudioServiceStreamBase::disconnect() {
189 if (mState != AAUDIO_STREAM_STATE_DISCONNECTED) {
190 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
191 mState = AAUDIO_STREAM_STATE_DISCONNECTED;
192 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800193}
194
195aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
196 double dataDouble,
197 int64_t dataLong) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800198 AAudioServiceMessage command;
199 command.what = AAudioServiceMessage::code::EVENT;
Phil Burk2355edb2016-12-26 13:54:02 -0800200 command.event.event = event;
Phil Burkc0c70e32017-02-09 13:18:38 -0800201 command.event.dataDouble = dataDouble;
202 command.event.dataLong = dataLong;
203 return writeUpMessageQueue(&command);
204}
205
206aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
207 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
Phil Burk71f35bb2017-04-13 16:05:07 -0700208 if (mUpMessageQueue == nullptr) {
209 ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
210 return AAUDIO_ERROR_NULL;
211 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800212 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
213 if (count != 1) {
214 ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
215 return AAUDIO_ERROR_WOULD_BLOCK;
216 } else {
217 return AAUDIO_OK;
218 }
219}
220
221aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
222 AAudioServiceMessage command;
Phil Burk97350f92017-07-21 15:59:44 -0700223 // Send a timestamp for the clock model.
Phil Burkc0c70e32017-02-09 13:18:38 -0800224 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
225 &command.timestamp.timestamp);
226 if (result == AAUDIO_OK) {
Phil Burk97350f92017-07-21 15:59:44 -0700227 command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE;
Phil Burkc0c70e32017-02-09 13:18:38 -0800228 result = writeUpMessageQueue(&command);
Phil Burk97350f92017-07-21 15:59:44 -0700229
230 if (result == AAUDIO_OK) {
231 // Send a hardware timestamp for presentation time.
232 result = getHardwareTimestamp(&command.timestamp.position,
233 &command.timestamp.timestamp);
234 if (result == AAUDIO_OK) {
235 command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE;
236 result = writeUpMessageQueue(&command);
237 }
238 }
239 }
240
241 if (result == AAUDIO_ERROR_UNAVAILABLE) {
Phil Burk940083c2017-07-17 17:00:02 -0700242 result = AAUDIO_OK; // just not available yet, try again later
Phil Burkc0c70e32017-02-09 13:18:38 -0800243 }
244 return result;
Phil Burk2355edb2016-12-26 13:54:02 -0800245}
246
Phil Burkc0c70e32017-02-09 13:18:38 -0800247/**
248 * Get an immutable description of the in-memory queues
249 * used to communicate with the underlying HAL or Service.
250 */
251aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
252 // Gather information on the message queue.
253 mUpMessageQueue->fillParcelable(parcelable,
254 parcelable.mUpMessageQueueParcelable);
255 return getDownDataDescription(parcelable);
Phil Burk11e8d332017-05-24 09:59:02 -0700256}