blob: f04bc861f712a75da86b88a037e2324773c3d18b [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 Burk2355edb2016-12-26 13:54:02 -080045}
46
Phil Burkc0c70e32017-02-09 13:18:38 -080047aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
48 aaudio::AAudioStreamConfiguration &configurationOutput) {
49 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
50 if (mUpMessageQueue != nullptr) {
51 return AAUDIO_ERROR_INVALID_STATE;
52 } else {
53 mUpMessageQueue = new SharedRingBuffer();
54 return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
55 }
56}
Phil Burkdec33ab2017-01-17 14:48:16 -080057
Phil Burkc0c70e32017-02-09 13:18:38 -080058aaudio_result_t AAudioServiceStreamBase::close() {
59 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
60 delete mUpMessageQueue;
61 mUpMessageQueue = nullptr;
Phil Burk942bdc02017-05-03 11:36:50 -070062
Phil Burkc0c70e32017-02-09 13:18:38 -080063 return AAUDIO_OK;
64}
65
66aaudio_result_t AAudioServiceStreamBase::start() {
Phil Burk71f35bb2017-04-13 16:05:07 -070067 ALOGD("AAudioServiceStreamBase::start() send AAUDIO_SERVICE_EVENT_STARTED");
Phil Burkc0c70e32017-02-09 13:18:38 -080068 sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
69 mState = AAUDIO_STREAM_STATE_STARTED;
70 mThreadEnabled.store(true);
71 return mAAudioThread.start(this);
72}
73
74aaudio_result_t AAudioServiceStreamBase::pause() {
75
76 sendCurrentTimestamp();
77 mThreadEnabled.store(false);
78 aaudio_result_t result = mAAudioThread.stop();
79 if (result != AAUDIO_OK) {
80 processError();
81 return result;
82 }
Phil Burk71f35bb2017-04-13 16:05:07 -070083 ALOGD("AAudioServiceStreamBase::pause() send AAUDIO_SERVICE_EVENT_PAUSED");
Phil Burkc0c70e32017-02-09 13:18:38 -080084 sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
85 mState = AAUDIO_STREAM_STATE_PAUSED;
86 return result;
87}
88
Phil Burk71f35bb2017-04-13 16:05:07 -070089aaudio_result_t AAudioServiceStreamBase::stop() {
90 // TODO wait for data to be played out
91 sendCurrentTimestamp();
92 mThreadEnabled.store(false);
93 aaudio_result_t result = mAAudioThread.stop();
94 if (result != AAUDIO_OK) {
95 processError();
96 return result;
97 }
98 ALOGD("AAudioServiceStreamBase::stop() send AAUDIO_SERVICE_EVENT_STOPPED");
99 sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
100 mState = AAUDIO_STREAM_STATE_STOPPED;
101 return result;
102}
103
104aaudio_result_t AAudioServiceStreamBase::flush() {
105 ALOGD("AAudioServiceStreamBase::flush() send AAUDIO_SERVICE_EVENT_FLUSHED");
106 sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
107 mState = AAUDIO_STREAM_STATE_FLUSHED;
108 return AAUDIO_OK;
109}
110
Phil Burkc0c70e32017-02-09 13:18:38 -0800111// implement Runnable
112void AAudioServiceStreamBase::run() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700113 ALOGD("AAudioServiceStreamBase::run() entering ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800114 TimestampScheduler timestampScheduler;
115 timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
116 timestampScheduler.start(AudioClock::getNanoseconds());
117 int64_t nextTime = timestampScheduler.nextAbsoluteTime();
118 while(mThreadEnabled.load()) {
119 if (AudioClock::getNanoseconds() >= nextTime) {
120 aaudio_result_t result = sendCurrentTimestamp();
121 if (result != AAUDIO_OK) {
122 break;
123 }
124 nextTime = timestampScheduler.nextAbsoluteTime();
125 } else {
126 // Sleep until it is time to send the next timestamp.
127 AudioClock::sleepUntilNanoTime(nextTime);
128 }
129 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700130 ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
Phil Burkc0c70e32017-02-09 13:18:38 -0800131}
132
133void AAudioServiceStreamBase::processError() {
134 sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
135}
136
137aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
138 double dataDouble,
139 int64_t dataLong) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800140 AAudioServiceMessage command;
141 command.what = AAudioServiceMessage::code::EVENT;
Phil Burk2355edb2016-12-26 13:54:02 -0800142 command.event.event = event;
Phil Burkc0c70e32017-02-09 13:18:38 -0800143 command.event.dataDouble = dataDouble;
144 command.event.dataLong = dataLong;
145 return writeUpMessageQueue(&command);
146}
147
148aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
149 std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
Phil Burk71f35bb2017-04-13 16:05:07 -0700150 if (mUpMessageQueue == nullptr) {
151 ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
152 return AAUDIO_ERROR_NULL;
153 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800154 int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
155 if (count != 1) {
156 ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
157 return AAUDIO_ERROR_WOULD_BLOCK;
158 } else {
159 return AAUDIO_OK;
160 }
161}
162
163aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
164 AAudioServiceMessage command;
165 aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
166 &command.timestamp.timestamp);
167 if (result == AAUDIO_OK) {
Phil Burk87c9f642017-05-17 07:22:39 -0700168 // ALOGD("sendCurrentTimestamp(): position = %lld, nanos = %lld",
169 // (long long) command.timestamp.position,
170 // (long long) command.timestamp.timestamp);
Phil Burkc0c70e32017-02-09 13:18:38 -0800171 command.what = AAudioServiceMessage::code::TIMESTAMP;
172 result = writeUpMessageQueue(&command);
173 }
174 return result;
Phil Burk2355edb2016-12-26 13:54:02 -0800175}
176
177
Phil Burkc0c70e32017-02-09 13:18:38 -0800178/**
179 * Get an immutable description of the in-memory queues
180 * used to communicate with the underlying HAL or Service.
181 */
182aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
183 // Gather information on the message queue.
184 mUpMessageQueue->fillParcelable(parcelable,
185 parcelable.mUpMessageQueueParcelable);
186 return getDownDataDescription(parcelable);
187}