blob: 5f7d1792cde6e5064b9a70f6837d951a91c7e748 [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 Burkc0c70e32017-02-09 13:18:38 -080040 , mAAudioThread() {
Eric Laurentcb4dae22017-07-01 19:39:32 -070041 mMmapClient.clientUid = -1;
42 mMmapClient.clientPid = -1;
43 mMmapClient.packageName = String16("");
Phil Burk2355edb2016-12-26 13:54:02 -080044}
45
Phil Burk5ed503c2017-02-01 09:38:15 -080046AAudioServiceStreamBase::~AAudioServiceStreamBase() {
Phil Burk98d6d922017-07-06 11:52:45 -070047 ALOGD("AAudioServiceStreamBase::~AAudioServiceStreamBase() destroying %p", this);
Phil Burk5a26e662017-07-07 12:44:48 -070048 // If the stream is deleted when OPEN or in use then audio resources will leak.
49 // This would indicate an internal error. So we want to find this ASAP.
50 LOG_ALWAYS_FATAL_IF(!(mState == AAUDIO_STREAM_STATE_CLOSED
Eric Laurentcb4dae22017-07-01 19:39:32 -070051 || mState == AAUDIO_STREAM_STATE_UNINITIALIZED
52 || mState == AAUDIO_STREAM_STATE_DISCONNECTED),
Phil Burk5a26e662017-07-07 12:44:48 -070053 "service stream still open, state = %d", mState);
Phil Burk2355edb2016-12-26 13:54:02 -080054}
55
Phil Burk4501b352017-06-29 18:12:36 -070056std::string AAudioServiceStreamBase::dump() const {
57 std::stringstream result;
58
59 result << " -------- handle = 0x" << std::hex << mHandle << std::dec << "\n";
60 result << " state = " << AAudio_convertStreamStateToText(mState) << "\n";
61 result << " format = " << mAudioFormat << "\n";
62 result << " framesPerBurst = " << mFramesPerBurst << "\n";
63 result << " channelCount = " << mSamplesPerFrame << "\n";
64 result << " capacityFrames = " << mCapacityInFrames << "\n";
Eric Laurentcb4dae22017-07-01 19:39:32 -070065 result << " owner uid = " << mMmapClient.clientUid << "\n";
Phil Burk4501b352017-06-29 18:12:36 -070066
67 return result.str();
68}
69
Phil Burkc0c70e32017-02-09 13:18:38 -080070aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
71 aaudio::AAudioStreamConfiguration &configurationOutput) {
Eric Laurentcb4dae22017-07-01 19:39:32 -070072
73 mMmapClient.clientUid = request.getUserId();
74 mMmapClient.clientPid = request.getProcessId();
75 mMmapClient.packageName.setTo(String16("")); // FIXME what should we do here?
76
Phil Burkc0c70e32017-02-09 13:18:38 -080077 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
78 if (mUpMessageQueue != nullptr) {
79 return AAUDIO_ERROR_INVALID_STATE;
80 } else {
81 mUpMessageQueue = new SharedRingBuffer();
82 return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
83 }
84}
Phil Burkdec33ab2017-01-17 14:48:16 -080085
Phil Burkc0c70e32017-02-09 13:18:38 -080086aaudio_result_t AAudioServiceStreamBase::close() {
Phil Burk98d6d922017-07-06 11:52:45 -070087 if (mState != AAUDIO_STREAM_STATE_CLOSED) {
88 stopTimestampThread();
89 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
90 delete mUpMessageQueue;
91 mUpMessageQueue = nullptr;
92 mState = AAUDIO_STREAM_STATE_CLOSED;
93 }
Phil Burkc0c70e32017-02-09 13:18:38 -080094 return AAUDIO_OK;
95}
96
97aaudio_result_t AAudioServiceStreamBase::start() {
Eric Laurentcb4dae22017-07-01 19:39:32 -070098 if (isRunning()) {
99 return AAUDIO_OK;
100 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800101 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
102 mState = AAUDIO_STREAM_STATE_STARTED;
103 mThreadEnabled.store(true);
104 return mAAudioThread.start(this);
105}
106
107aaudio_result_t AAudioServiceStreamBase::pause() {
Phil Burk11e8d332017-05-24 09:59:02 -0700108 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700109 if (!isRunning()) {
110 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800111 }
Eric Laurentcb4dae22017-07-01 19:39:32 -0700112 sendCurrentTimestamp();
113 mThreadEnabled.store(false);
114 result = mAAudioThread.stop();
115 if (result != AAUDIO_OK) {
116 disconnect();
117 return result;
118 }
119 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
Phil Burkc0c70e32017-02-09 13:18:38 -0800120 mState = AAUDIO_STREAM_STATE_PAUSED;
121 return result;
122}
123
Phil Burk71f35bb2017-04-13 16:05:07 -0700124aaudio_result_t AAudioServiceStreamBase::stop() {
Phil Burk11e8d332017-05-24 09:59:02 -0700125 aaudio_result_t result = AAUDIO_OK;
Eric Laurentcb4dae22017-07-01 19:39:32 -0700126 if (!isRunning()) {
127 return result;
Phil Burk71f35bb2017-04-13 16:05:07 -0700128 }
Eric Laurentcb4dae22017-07-01 19:39:32 -0700129 // TODO wait for data to be played out
130 sendCurrentTimestamp(); // warning - this calls a virtual function
131 result = stopTimestampThread();
132 if (result != AAUDIO_OK) {
133 disconnect();
134 return result;
135 }
136 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
Phil Burk71f35bb2017-04-13 16:05:07 -0700137 mState = AAUDIO_STREAM_STATE_STOPPED;
138 return result;
139}
140
Phil Burk98d6d922017-07-06 11:52:45 -0700141aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() {
142 aaudio_result_t result = AAUDIO_OK;
143 // clear flag that tells thread to loop
144 if (mThreadEnabled.exchange(false)) {
145 result = mAAudioThread.stop();
146 }
147 return result;
148}
149
Phil Burk71f35bb2017-04-13 16:05:07 -0700150aaudio_result_t AAudioServiceStreamBase::flush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700151 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
152 mState = AAUDIO_STREAM_STATE_FLUSHED;
153 return AAUDIO_OK;
154}
155
Phil Burkcf5f6d22017-05-26 12:35:07 -0700156// implement Runnable, periodically send timestamps to client
Phil Burkc0c70e32017-02-09 13:18:38 -0800157void AAudioServiceStreamBase::run() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700158 ALOGD("AAudioServiceStreamBase::run() entering ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800159 TimestampScheduler timestampScheduler;
160 timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
161 timestampScheduler.start(AudioClock::getNanoseconds());
162 int64_t nextTime = timestampScheduler.nextAbsoluteTime();
163 while(mThreadEnabled.load()) {
164 if (AudioClock::getNanoseconds() >= nextTime) {
165 aaudio_result_t result = sendCurrentTimestamp();
166 if (result != AAUDIO_OK) {
167 break;
168 }
169 nextTime = timestampScheduler.nextAbsoluteTime();
170 } else {
171 // Sleep until it is time to send the next timestamp.
Phil Burk98d6d922017-07-06 11:52:45 -0700172 // TODO Wait for a signal with a timeout so that we can stop more quickly.
Phil Burkc0c70e32017-02-09 13:18:38 -0800173 AudioClock::sleepUntilNanoTime(nextTime);
174 }
175 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700176 ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800177}
178
Phil Burk5ef003b2017-06-30 11:43:37 -0700179void AAudioServiceStreamBase::disconnect() {
180 if (mState != AAUDIO_STREAM_STATE_DISCONNECTED) {
181 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
182 mState = AAUDIO_STREAM_STATE_DISCONNECTED;
183 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800184}
185
186aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
187 double dataDouble,
188 int64_t dataLong) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800189 AAudioServiceMessage command;
190 command.what = AAudioServiceMessage::code::EVENT;
Phil Burk2355edb2016-12-26 13:54:02 -0800191 command.event.event = event;
Phil Burkc0c70e32017-02-09 13:18:38 -0800192 command.event.dataDouble = dataDouble;
193 command.event.dataLong = dataLong;
194 return writeUpMessageQueue(&command);
195}
196
197aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
198 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
Phil Burk71f35bb2017-04-13 16:05:07 -0700199 if (mUpMessageQueue == nullptr) {
200 ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
201 return AAUDIO_ERROR_NULL;
202 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800203 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
204 if (count != 1) {
205 ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
206 return AAUDIO_ERROR_WOULD_BLOCK;
207 } else {
208 return AAUDIO_OK;
209 }
210}
211
212aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
213 AAudioServiceMessage command;
214 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
215 &command.timestamp.timestamp);
216 if (result == AAUDIO_OK) {
Phil Burk87c9f642017-05-17 07:22:39 -0700217 // ALOGD("sendCurrentTimestamp(): position = %lld, nanos = %lld",
218 // (long long) command.timestamp.position,
219 // (long long) command.timestamp.timestamp);
Phil Burkc0c70e32017-02-09 13:18:38 -0800220 command.what = AAudioServiceMessage::code::TIMESTAMP;
221 result = writeUpMessageQueue(&command);
Phil Burk940083c2017-07-17 17:00:02 -0700222 } else if (result == AAUDIO_ERROR_UNAVAILABLE) {
223 result = AAUDIO_OK; // just not available yet, try again later
Phil Burkc0c70e32017-02-09 13:18:38 -0800224 }
225 return result;
Phil Burk2355edb2016-12-26 13:54:02 -0800226}
227
Phil Burkc0c70e32017-02-09 13:18:38 -0800228/**
229 * Get an immutable description of the in-memory queues
230 * used to communicate with the underlying HAL or Service.
231 */
232aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
233 // Gather information on the message queue.
234 mUpMessageQueue->fillParcelable(parcelable,
235 parcelable.mUpMessageQueueParcelable);
236 return getDownDataDescription(parcelable);
Phil Burk11e8d332017-05-24 09:59:02 -0700237}