blob: 2e20287b1abc0fb3451f071a1a9d7f147521456b [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
Phil Burk5ed503c2017-02-01 09:38:15 -080017#define LOG_TAG "AAudioService"
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 Burkc0c70e32017-02-09 13:18:38 -080040 , mAAudioThread() {
Phil Burk2355edb2016-12-26 13:54:02 -080041}
42
Phil Burk5ed503c2017-02-01 09:38:15 -080043AAudioServiceStreamBase::~AAudioServiceStreamBase() {
Phil Burk98d6d922017-07-06 11:52:45 -070044 ALOGD("AAudioServiceStreamBase::~AAudioServiceStreamBase() destroying %p", this);
45 // If the stream is deleted without closing then audio resources will leak.
46 // Not being closed here would indicate an internal error. So we want to find this ASAP.
47 LOG_ALWAYS_FATAL_IF(mState != AAUDIO_STREAM_STATE_CLOSED,
48 "service stream not closed, state = %d", mState);
Phil Burk2355edb2016-12-26 13:54:02 -080049}
50
Phil Burk4501b352017-06-29 18:12:36 -070051std::string AAudioServiceStreamBase::dump() const {
52 std::stringstream result;
53
54 result << " -------- handle = 0x" << std::hex << mHandle << std::dec << "\n";
55 result << " state = " << AAudio_convertStreamStateToText(mState) << "\n";
56 result << " format = " << mAudioFormat << "\n";
57 result << " framesPerBurst = " << mFramesPerBurst << "\n";
58 result << " channelCount = " << mSamplesPerFrame << "\n";
59 result << " capacityFrames = " << mCapacityInFrames << "\n";
60 result << " owner uid = " << mOwnerUserId << "\n";
61
62 return result.str();
63}
64
Phil Burkc0c70e32017-02-09 13:18:38 -080065aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
66 aaudio::AAudioStreamConfiguration &configurationOutput) {
67 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
68 if (mUpMessageQueue != nullptr) {
69 return AAUDIO_ERROR_INVALID_STATE;
70 } else {
71 mUpMessageQueue = new SharedRingBuffer();
72 return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
73 }
74}
Phil Burkdec33ab2017-01-17 14:48:16 -080075
Phil Burkc0c70e32017-02-09 13:18:38 -080076aaudio_result_t AAudioServiceStreamBase::close() {
Phil Burk98d6d922017-07-06 11:52:45 -070077 if (mState != AAUDIO_STREAM_STATE_CLOSED) {
78 stopTimestampThread();
79 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
80 delete mUpMessageQueue;
81 mUpMessageQueue = nullptr;
82 mState = AAUDIO_STREAM_STATE_CLOSED;
83 }
Phil Burkc0c70e32017-02-09 13:18:38 -080084 return AAUDIO_OK;
85}
86
87aaudio_result_t AAudioServiceStreamBase::start() {
88 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
89 mState = AAUDIO_STREAM_STATE_STARTED;
90 mThreadEnabled.store(true);
91 return mAAudioThread.start(this);
92}
93
94aaudio_result_t AAudioServiceStreamBase::pause() {
Phil Burk11e8d332017-05-24 09:59:02 -070095 aaudio_result_t result = AAUDIO_OK;
96 if (isRunning()) {
97 sendCurrentTimestamp();
98 mThreadEnabled.store(false);
99 result = mAAudioThread.stop();
100 if (result != AAUDIO_OK) {
Phil Burk5ef003b2017-06-30 11:43:37 -0700101 disconnect();
Phil Burk11e8d332017-05-24 09:59:02 -0700102 return result;
103 }
104 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
Phil Burkc0c70e32017-02-09 13:18:38 -0800105 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800106 mState = AAUDIO_STREAM_STATE_PAUSED;
107 return result;
108}
109
Phil Burk71f35bb2017-04-13 16:05:07 -0700110aaudio_result_t AAudioServiceStreamBase::stop() {
Phil Burk11e8d332017-05-24 09:59:02 -0700111 aaudio_result_t result = AAUDIO_OK;
112 if (isRunning()) {
113 // TODO wait for data to be played out
Phil Burk98d6d922017-07-06 11:52:45 -0700114 sendCurrentTimestamp(); // warning - this calls a virtual function
115 result = stopTimestampThread();
Phil Burk11e8d332017-05-24 09:59:02 -0700116 if (result != AAUDIO_OK) {
Phil Burk5ef003b2017-06-30 11:43:37 -0700117 disconnect();
Phil Burk11e8d332017-05-24 09:59:02 -0700118 return result;
119 }
120 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
Phil Burk71f35bb2017-04-13 16:05:07 -0700121 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700122 mState = AAUDIO_STREAM_STATE_STOPPED;
123 return result;
124}
125
Phil Burk98d6d922017-07-06 11:52:45 -0700126aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() {
127 aaudio_result_t result = AAUDIO_OK;
128 // clear flag that tells thread to loop
129 if (mThreadEnabled.exchange(false)) {
130 result = mAAudioThread.stop();
131 }
132 return result;
133}
134
Phil Burk71f35bb2017-04-13 16:05:07 -0700135aaudio_result_t AAudioServiceStreamBase::flush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700136 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
137 mState = AAUDIO_STREAM_STATE_FLUSHED;
138 return AAUDIO_OK;
139}
140
Phil Burkcf5f6d22017-05-26 12:35:07 -0700141// implement Runnable, periodically send timestamps to client
Phil Burkc0c70e32017-02-09 13:18:38 -0800142void AAudioServiceStreamBase::run() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700143 ALOGD("AAudioServiceStreamBase::run() entering ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800144 TimestampScheduler timestampScheduler;
145 timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
146 timestampScheduler.start(AudioClock::getNanoseconds());
147 int64_t nextTime = timestampScheduler.nextAbsoluteTime();
148 while(mThreadEnabled.load()) {
149 if (AudioClock::getNanoseconds() >= nextTime) {
150 aaudio_result_t result = sendCurrentTimestamp();
151 if (result != AAUDIO_OK) {
152 break;
153 }
154 nextTime = timestampScheduler.nextAbsoluteTime();
155 } else {
156 // Sleep until it is time to send the next timestamp.
Phil Burk98d6d922017-07-06 11:52:45 -0700157 // TODO Wait for a signal with a timeout so that we can stop more quickly.
Phil Burkc0c70e32017-02-09 13:18:38 -0800158 AudioClock::sleepUntilNanoTime(nextTime);
159 }
160 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700161 ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800162}
163
Phil Burk5ef003b2017-06-30 11:43:37 -0700164void AAudioServiceStreamBase::disconnect() {
165 if (mState != AAUDIO_STREAM_STATE_DISCONNECTED) {
166 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
167 mState = AAUDIO_STREAM_STATE_DISCONNECTED;
168 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800169}
170
171aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
172 double dataDouble,
173 int64_t dataLong) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800174 AAudioServiceMessage command;
175 command.what = AAudioServiceMessage::code::EVENT;
Phil Burk2355edb2016-12-26 13:54:02 -0800176 command.event.event = event;
Phil Burkc0c70e32017-02-09 13:18:38 -0800177 command.event.dataDouble = dataDouble;
178 command.event.dataLong = dataLong;
179 return writeUpMessageQueue(&command);
180}
181
182aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
183 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
Phil Burk71f35bb2017-04-13 16:05:07 -0700184 if (mUpMessageQueue == nullptr) {
185 ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
186 return AAUDIO_ERROR_NULL;
187 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800188 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
189 if (count != 1) {
190 ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
191 return AAUDIO_ERROR_WOULD_BLOCK;
192 } else {
193 return AAUDIO_OK;
194 }
195}
196
197aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
198 AAudioServiceMessage command;
199 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
200 &command.timestamp.timestamp);
201 if (result == AAUDIO_OK) {
Phil Burk87c9f642017-05-17 07:22:39 -0700202 // ALOGD("sendCurrentTimestamp(): position = %lld, nanos = %lld",
203 // (long long) command.timestamp.position,
204 // (long long) command.timestamp.timestamp);
Phil Burkc0c70e32017-02-09 13:18:38 -0800205 command.what = AAudioServiceMessage::code::TIMESTAMP;
206 result = writeUpMessageQueue(&command);
207 }
208 return result;
Phil Burk2355edb2016-12-26 13:54:02 -0800209}
210
Phil Burkc0c70e32017-02-09 13:18:38 -0800211/**
212 * Get an immutable description of the in-memory queues
213 * used to communicate with the underlying HAL or Service.
214 */
215aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
216 // Gather information on the message queue.
217 mUpMessageQueue->fillParcelable(parcelable,
218 parcelable.mUpMessageQueueParcelable);
219 return getDownDataDescription(parcelable);
Phil Burk11e8d332017-05-24 09:59:02 -0700220}