blob: c4591b016c8e6609131b8d7eaf2114b8591f7589 [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 Burkc0c70e32017-02-09 13:18:38 -080044 close();
Phil Burk11e8d332017-05-24 09:59:02 -070045 ALOGD("AAudioServiceStreamBase::~AAudioServiceStreamBase() destroyed %p", this);
Phil Burk2355edb2016-12-26 13:54:02 -080046}
47
Phil Burkc0c70e32017-02-09 13:18:38 -080048aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
49 aaudio::AAudioStreamConfiguration &configurationOutput) {
50 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
51 if (mUpMessageQueue != nullptr) {
52 return AAUDIO_ERROR_INVALID_STATE;
53 } else {
54 mUpMessageQueue = new SharedRingBuffer();
55 return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
56 }
57}
Phil Burkdec33ab2017-01-17 14:48:16 -080058
Phil Burkc0c70e32017-02-09 13:18:38 -080059aaudio_result_t AAudioServiceStreamBase::close() {
Phil Burk11e8d332017-05-24 09:59:02 -070060 stop();
Phil Burkc0c70e32017-02-09 13:18:38 -080061 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
62 delete mUpMessageQueue;
63 mUpMessageQueue = nullptr;
Phil Burk942bdc02017-05-03 11:36:50 -070064
Phil Burkc0c70e32017-02-09 13:18:38 -080065 return AAUDIO_OK;
66}
67
68aaudio_result_t AAudioServiceStreamBase::start() {
69 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
70 mState = AAUDIO_STREAM_STATE_STARTED;
71 mThreadEnabled.store(true);
72 return mAAudioThread.start(this);
73}
74
75aaudio_result_t AAudioServiceStreamBase::pause() {
Phil Burk11e8d332017-05-24 09:59:02 -070076 aaudio_result_t result = AAUDIO_OK;
77 if (isRunning()) {
78 sendCurrentTimestamp();
79 mThreadEnabled.store(false);
80 result = mAAudioThread.stop();
81 if (result != AAUDIO_OK) {
Phil Burk5ef003b2017-06-30 11:43:37 -070082 disconnect();
Phil Burk11e8d332017-05-24 09:59:02 -070083 return result;
84 }
85 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
Phil Burkc0c70e32017-02-09 13:18:38 -080086 }
Phil Burkc0c70e32017-02-09 13:18:38 -080087 mState = AAUDIO_STREAM_STATE_PAUSED;
88 return result;
89}
90
Phil Burk71f35bb2017-04-13 16:05:07 -070091aaudio_result_t AAudioServiceStreamBase::stop() {
Phil Burk11e8d332017-05-24 09:59:02 -070092 aaudio_result_t result = AAUDIO_OK;
93 if (isRunning()) {
94 // TODO wait for data to be played out
95 sendCurrentTimestamp();
96 mThreadEnabled.store(false);
97 result = mAAudioThread.stop();
98 if (result != AAUDIO_OK) {
Phil Burk5ef003b2017-06-30 11:43:37 -070099 disconnect();
Phil Burk11e8d332017-05-24 09:59:02 -0700100 return result;
101 }
102 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
Phil Burk71f35bb2017-04-13 16:05:07 -0700103 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700104 mState = AAUDIO_STREAM_STATE_STOPPED;
105 return result;
106}
107
108aaudio_result_t AAudioServiceStreamBase::flush() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700109 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
110 mState = AAUDIO_STREAM_STATE_FLUSHED;
111 return AAUDIO_OK;
112}
113
Phil Burkcf5f6d22017-05-26 12:35:07 -0700114// implement Runnable, periodically send timestamps to client
Phil Burkc0c70e32017-02-09 13:18:38 -0800115void AAudioServiceStreamBase::run() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700116 ALOGD("AAudioServiceStreamBase::run() entering ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800117 TimestampScheduler timestampScheduler;
118 timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
119 timestampScheduler.start(AudioClock::getNanoseconds());
120 int64_t nextTime = timestampScheduler.nextAbsoluteTime();
121 while(mThreadEnabled.load()) {
122 if (AudioClock::getNanoseconds() >= nextTime) {
123 aaudio_result_t result = sendCurrentTimestamp();
124 if (result != AAUDIO_OK) {
125 break;
126 }
127 nextTime = timestampScheduler.nextAbsoluteTime();
128 } else {
129 // Sleep until it is time to send the next timestamp.
130 AudioClock::sleepUntilNanoTime(nextTime);
131 }
132 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700133 ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800134}
135
Phil Burk5ef003b2017-06-30 11:43:37 -0700136void AAudioServiceStreamBase::disconnect() {
137 if (mState != AAUDIO_STREAM_STATE_DISCONNECTED) {
138 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
139 mState = AAUDIO_STREAM_STATE_DISCONNECTED;
140 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800141}
142
143aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
144 double dataDouble,
145 int64_t dataLong) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800146 AAudioServiceMessage command;
147 command.what = AAudioServiceMessage::code::EVENT;
Phil Burk2355edb2016-12-26 13:54:02 -0800148 command.event.event = event;
Phil Burkc0c70e32017-02-09 13:18:38 -0800149 command.event.dataDouble = dataDouble;
150 command.event.dataLong = dataLong;
151 return writeUpMessageQueue(&command);
152}
153
154aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
155 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
Phil Burk71f35bb2017-04-13 16:05:07 -0700156 if (mUpMessageQueue == nullptr) {
157 ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
158 return AAUDIO_ERROR_NULL;
159 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800160 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
161 if (count != 1) {
162 ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
163 return AAUDIO_ERROR_WOULD_BLOCK;
164 } else {
165 return AAUDIO_OK;
166 }
167}
168
169aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
170 AAudioServiceMessage command;
171 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
172 &command.timestamp.timestamp);
173 if (result == AAUDIO_OK) {
Phil Burk87c9f642017-05-17 07:22:39 -0700174 // ALOGD("sendCurrentTimestamp(): position = %lld, nanos = %lld",
175 // (long long) command.timestamp.position,
176 // (long long) command.timestamp.timestamp);
Phil Burkc0c70e32017-02-09 13:18:38 -0800177 command.what = AAudioServiceMessage::code::TIMESTAMP;
178 result = writeUpMessageQueue(&command);
179 }
180 return result;
Phil Burk2355edb2016-12-26 13:54:02 -0800181}
182
Phil Burkc0c70e32017-02-09 13:18:38 -0800183/**
184 * Get an immutable description of the in-memory queues
185 * used to communicate with the underlying HAL or Service.
186 */
187aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
188 // Gather information on the message queue.
189 mUpMessageQueue->fillParcelable(parcelable,
190 parcelable.mUpMessageQueueParcelable);
191 return getDownDataDescription(parcelable);
Phil Burk11e8d332017-05-24 09:59:02 -0700192}