• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #define LOG_TAG "AAudioService"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <mutex>
22 
23 #include "binding/IAAudioService.h"
24 #include "binding/AAudioServiceMessage.h"
25 #include "utility/AudioClock.h"
26 
27 #include "AAudioServiceStreamBase.h"
28 #include "TimestampScheduler.h"
29 
30 using namespace android;  // TODO just import names needed
31 using namespace aaudio;   // TODO just import names needed
32 
33 /**
34  * Base class for streams in the service.
35  * @return
36  */
37 
AAudioServiceStreamBase()38 AAudioServiceStreamBase::AAudioServiceStreamBase()
39         : mUpMessageQueue(nullptr)
40         , mAAudioThread() {
41 }
42 
~AAudioServiceStreamBase()43 AAudioServiceStreamBase::~AAudioServiceStreamBase() {
44     close();
45 }
46 
open(const aaudio::AAudioStreamRequest & request,aaudio::AAudioStreamConfiguration & configurationOutput)47 aaudio_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 }
57 
close()58 aaudio_result_t AAudioServiceStreamBase::close() {
59     std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
60     delete mUpMessageQueue;
61     mUpMessageQueue = nullptr;
62 
63     return AAUDIO_OK;
64 }
65 
start()66 aaudio_result_t AAudioServiceStreamBase::start() {
67     sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
68     mState = AAUDIO_STREAM_STATE_STARTED;
69     mThreadEnabled.store(true);
70     return mAAudioThread.start(this);
71 }
72 
pause()73 aaudio_result_t AAudioServiceStreamBase::pause() {
74 
75     sendCurrentTimestamp();
76     mThreadEnabled.store(false);
77     aaudio_result_t result = mAAudioThread.stop();
78     if (result != AAUDIO_OK) {
79         processError();
80         return result;
81     }
82     sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
83     mState = AAUDIO_STREAM_STATE_PAUSED;
84     return result;
85 }
86 
stop()87 aaudio_result_t AAudioServiceStreamBase::stop() {
88     // TODO wait for data to be played out
89     sendCurrentTimestamp();
90     mThreadEnabled.store(false);
91     aaudio_result_t result = mAAudioThread.stop();
92     if (result != AAUDIO_OK) {
93         processError();
94         return result;
95     }
96     sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
97     mState = AAUDIO_STREAM_STATE_STOPPED;
98     return result;
99 }
100 
flush()101 aaudio_result_t AAudioServiceStreamBase::flush() {
102     sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
103     mState = AAUDIO_STREAM_STATE_FLUSHED;
104     return AAUDIO_OK;
105 }
106 
107 // implement Runnable, periodically send timestamps to client
run()108 void AAudioServiceStreamBase::run() {
109     ALOGD("AAudioServiceStreamBase::run() entering ----------------");
110     TimestampScheduler timestampScheduler;
111     timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
112     timestampScheduler.start(AudioClock::getNanoseconds());
113     int64_t nextTime = timestampScheduler.nextAbsoluteTime();
114     while(mThreadEnabled.load()) {
115         if (AudioClock::getNanoseconds() >= nextTime) {
116             aaudio_result_t result = sendCurrentTimestamp();
117             if (result != AAUDIO_OK) {
118                 break;
119             }
120             nextTime = timestampScheduler.nextAbsoluteTime();
121         } else  {
122             // Sleep until it is time to send the next timestamp.
123             AudioClock::sleepUntilNanoTime(nextTime);
124         }
125     }
126     ALOGD("AAudioServiceStreamBase::run() exiting ----------------");
127 }
128 
processError()129 void AAudioServiceStreamBase::processError() {
130     sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
131 }
132 
sendServiceEvent(aaudio_service_event_t event,double dataDouble,int64_t dataLong)133 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
134                                                double  dataDouble,
135                                                int64_t dataLong) {
136     AAudioServiceMessage command;
137     command.what = AAudioServiceMessage::code::EVENT;
138     command.event.event = event;
139     command.event.dataDouble = dataDouble;
140     command.event.dataLong = dataLong;
141     return writeUpMessageQueue(&command);
142 }
143 
writeUpMessageQueue(AAudioServiceMessage * command)144 aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
145     std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
146     if (mUpMessageQueue == nullptr) {
147         ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
148         return AAUDIO_ERROR_NULL;
149     }
150     int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
151     if (count != 1) {
152         ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
153         return AAUDIO_ERROR_WOULD_BLOCK;
154     } else {
155         return AAUDIO_OK;
156     }
157 }
158 
sendCurrentTimestamp()159 aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
160     AAudioServiceMessage command;
161     aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
162                                                     &command.timestamp.timestamp);
163     if (result == AAUDIO_OK) {
164     //    ALOGD("sendCurrentTimestamp(): position = %lld, nanos = %lld",
165     //          (long long) command.timestamp.position,
166     //          (long long) command.timestamp.timestamp);
167         command.what = AAudioServiceMessage::code::TIMESTAMP;
168         result = writeUpMessageQueue(&command);
169     }
170     return result;
171 }
172 
173 /**
174  * Get an immutable description of the in-memory queues
175  * used to communicate with the underlying HAL or Service.
176  */
getDescription(AudioEndpointParcelable & parcelable)177 aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
178     // Gather information on the message queue.
179     mUpMessageQueue->fillParcelable(parcelable,
180                                     parcelable.mUpMessageQueueParcelable);
181     return getDownDataDescription(parcelable);
182 }