• 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 #ifndef AAUDIO_AAUDIO_SERVICE_STREAM_BASE_H
18 #define AAUDIO_AAUDIO_SERVICE_STREAM_BASE_H
19 
20 #include <assert.h>
21 #include <mutex>
22 
23 #include <android-base/thread_annotations.h>
24 #include <media/AidlConversion.h>
25 #include <media/AudioClient.h>
26 #include <utils/RefBase.h>
27 
28 #include "fifo/FifoBuffer.h"
29 #include "binding/AudioEndpointParcelable.h"
30 #include "binding/AAudioServiceMessage.h"
31 #include "binding/AAudioStreamRequest.h"
32 #include "core/AAudioStreamParameters.h"
33 #include "utility/AAudioUtilities.h"
34 #include "utility/AudioClock.h"
35 
36 #include "AAudioCommandQueue.h"
37 #include "AAudioThread.h"
38 #include "SharedRingBuffer.h"
39 #include "TimestampScheduler.h"
40 
41 namespace android {
42     class AAudioService;
43 }
44 
45 namespace aaudio {
46 
47 class AAudioServiceEndpoint;
48 
49 // We expect the queue to only have a few commands.
50 // This should be way more than we need.
51 #define QUEUE_UP_CAPACITY_COMMANDS (128)
52 
53 /**
54  * Each instance of AAudioServiceStreamBase corresponds to a client stream.
55  * It uses a subclass of AAudioServiceEndpoint to communicate with the underlying device or port.
56  */
57 class AAudioServiceStreamBase
58     : public virtual android::RefBase
59     , public AAudioStreamParameters
60     , public Runnable  {
61 
62 public:
63     explicit AAudioServiceStreamBase(android::AAudioService &aAudioService);
64 
65     virtual ~AAudioServiceStreamBase();
66 
67     enum {
68         ILLEGAL_THREAD_ID = 0
69     };
70 
71     static std::string dumpHeader();
72 
73     // does not include EOL
74     virtual std::string dump() const;
75 
76     /**
77      * Open the device.
78      */
79     virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request) = 0;
80 
81     // We log the CLOSE from the close() method. We needed this separate method to log the OPEN
82     // because we had to wait until we generated the handle.
83     void logOpen(aaudio_handle_t streamHandle);
84 
85     aaudio_result_t close() EXCLUDES(mLock);
86 
87     /**
88      * Start the flow of audio data.
89      *
90      * This is not guaranteed to be synchronous but it currently is.
91      * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
92      */
93     aaudio_result_t start() EXCLUDES(mLock);
94 
95     /**
96      * Stop the flow of data so that start() can resume without loss of data.
97      *
98      * This is not guaranteed to be synchronous but it currently is.
99      * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
100     */
101     aaudio_result_t pause() EXCLUDES(mLock);
102 
103     /**
104      * Stop the flow of data after the currently queued data has finished playing.
105      *
106      * This is not guaranteed to be synchronous but it currently is.
107      * An AAUDIO_SERVICE_EVENT_STOPPED will be sent to the client when complete.
108      *
109      */
110     aaudio_result_t stop() EXCLUDES(mLock);
111 
112     /**
113      * Discard any data held by the underlying HAL or Service.
114      *
115      * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
116      */
117     aaudio_result_t flush() EXCLUDES(mLock);
118 
119     /**
120      * Exit standby mode. The MMAP buffer will be reallocated.
121      */
122     aaudio_result_t exitStandby(AudioEndpointParcelable *parcelable) EXCLUDES(mLock);
123 
startClient(const android::AudioClient & client,const audio_attributes_t * attr __unused,audio_port_handle_t * clientHandle __unused)124     virtual aaudio_result_t startClient(const android::AudioClient& client,
125                                         const audio_attributes_t *attr __unused,
126                                         audio_port_handle_t *clientHandle __unused) {
127         ALOGD("AAudioServiceStreamBase::startClient(%p, ...) AAUDIO_ERROR_UNAVAILABLE", &client);
128         return AAUDIO_ERROR_UNAVAILABLE;
129     }
130 
stopClient(audio_port_handle_t clientHandle __unused)131     virtual aaudio_result_t stopClient(audio_port_handle_t clientHandle __unused) {
132         ALOGD("AAudioServiceStreamBase::stopClient(%d) AAUDIO_ERROR_UNAVAILABLE", clientHandle);
133         return AAUDIO_ERROR_UNAVAILABLE;
134     }
135 
136     aaudio_result_t registerAudioThread(pid_t clientThreadId, int priority) EXCLUDES(mLock);
137 
138     aaudio_result_t unregisterAudioThread(pid_t clientThreadId) EXCLUDES(mLock);
139 
isRunning()140     bool isRunning() const {
141         return mState == AAUDIO_STREAM_STATE_STARTED;
142     }
143 
144     /**
145      * Fill in a parcelable description of stream.
146      */
147     aaudio_result_t getDescription(AudioEndpointParcelable &parcelable) EXCLUDES(mLock);
148 
setRegisteredThread(pid_t pid)149     void setRegisteredThread(pid_t pid) {
150         mRegisteredClientThread = pid;
151     }
152 
getRegisteredThread()153     pid_t getRegisteredThread() const {
154         return mRegisteredClientThread;
155     }
156 
getFramesPerBurst()157     int32_t getFramesPerBurst() const {
158         return mFramesPerBurst;
159     }
160 
161     void run() override; // to implement Runnable
162 
163     void disconnect() EXCLUDES(mLock);
164 
getAudioClient()165     const android::AudioClient &getAudioClient() {
166         return mMmapClient;
167     }
168 
getOwnerUserId()169     uid_t getOwnerUserId() const {
170         return VALUE_OR_FATAL(android::aidl2legacy_int32_t_uid_t(
171                 mMmapClient.attributionSource.uid));
172     }
173 
getOwnerProcessId()174     pid_t getOwnerProcessId() const {
175         return VALUE_OR_FATAL(android::aidl2legacy_int32_t_pid_t(
176                 mMmapClient.attributionSource.pid));
177     }
178 
getHandle()179     aaudio_handle_t getHandle() const {
180         return mHandle;
181     }
setHandle(aaudio_handle_t handle)182     void setHandle(aaudio_handle_t handle) {
183         mHandle = handle;
184     }
185 
getPortHandle()186     audio_port_handle_t getPortHandle() const {
187         return mClientHandle;
188     }
189 
getState()190     aaudio_stream_state_t getState() const {
191         return mState;
192     }
193 
194     void onVolumeChanged(float volume);
195 
196     /**
197      * Set false when the stream is started.
198      * Set true when data is first read from the stream.
199      * @param b
200      */
setFlowing(bool b)201     void setFlowing(bool b) {
202         mFlowing = b;
203     }
204 
isFlowing()205     bool isFlowing() const {
206         return mFlowing;
207     }
208 
209     /**
210      * Set false when the stream should not longer be processed.
211      * This may be caused by a message queue overflow.
212      * Set true when stream is started.
213      * @param suspended
214      */
setSuspended(bool suspended)215     void setSuspended(bool suspended) {
216         mSuspended = suspended;
217     }
218 
isSuspended()219     bool isSuspended() const {
220         return mSuspended;
221     }
222 
isCloseNeeded()223     bool isCloseNeeded() const {
224         return mCloseNeeded.load();
225     }
226 
227     /**
228      * Mark this stream as needing to be closed.
229      * Once marked for closing, it cannot be unmarked.
230      */
markCloseNeeded()231     void markCloseNeeded() {
232         mCloseNeeded.store(true);
233     }
234 
getTypeText()235     virtual const char *getTypeText() const { return "Base"; }
236 
237 protected:
238 
239     /**
240      * Open the device.
241      */
242     aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
243                          aaudio_sharing_mode_t sharingMode);
244 
245     aaudio_result_t start_l() REQUIRES(mLock);
246     virtual aaudio_result_t close_l() REQUIRES(mLock);
247     virtual aaudio_result_t pause_l() REQUIRES(mLock);
248     virtual aaudio_result_t stop_l() REQUIRES(mLock);
249     void disconnect_l() REQUIRES(mLock);
250     aaudio_result_t flush_l() REQUIRES(mLock);
251 
252     class RegisterAudioThreadParam : public AAudioCommandParam {
253     public:
RegisterAudioThreadParam(pid_t ownerPid,pid_t clientThreadId,int priority)254         RegisterAudioThreadParam(pid_t ownerPid, pid_t clientThreadId, int priority)
255                 : AAudioCommandParam(), mOwnerPid(ownerPid),
256                   mClientThreadId(clientThreadId), mPriority(priority) { }
257         ~RegisterAudioThreadParam() = default;
258 
259         pid_t mOwnerPid;
260         pid_t mClientThreadId;
261         int mPriority;
262     };
263     aaudio_result_t registerAudioThread_l(
264             pid_t ownerPid, pid_t clientThreadId, int priority) REQUIRES(mLock);
265 
266     class UnregisterAudioThreadParam : public AAudioCommandParam {
267     public:
UnregisterAudioThreadParam(pid_t clientThreadId)268         UnregisterAudioThreadParam(pid_t clientThreadId)
269                 : AAudioCommandParam(), mClientThreadId(clientThreadId) { }
270         ~UnregisterAudioThreadParam() = default;
271 
272         pid_t mClientThreadId;
273     };
274     aaudio_result_t unregisterAudioThread_l(pid_t clientThreadId) REQUIRES(mLock);
275 
276     class GetDescriptionParam : public AAudioCommandParam {
277     public:
GetDescriptionParam(AudioEndpointParcelable * parcelable)278         GetDescriptionParam(AudioEndpointParcelable* parcelable)
279                 : AAudioCommandParam(), mParcelable(parcelable) { }
280         ~GetDescriptionParam() = default;
281 
282         AudioEndpointParcelable* mParcelable;
283     };
284     aaudio_result_t getDescription_l(AudioEndpointParcelable* parcelable) REQUIRES(mLock);
285 
286     void setState(aaudio_stream_state_t state);
287 
288     /**
289      * Device specific startup.
290      * @return AAUDIO_OK or negative error.
291      */
292     virtual aaudio_result_t startDevice();
293 
294     aaudio_result_t writeUpMessageQueue(AAudioServiceMessage *command);
295 
296     aaudio_result_t sendCurrentTimestamp_l() REQUIRES(mLock);
297 
298     aaudio_result_t sendXRunCount(int32_t xRunCount);
299 
300     /**
301      * @param positionFrames
302      * @param timeNanos
303      * @return AAUDIO_OK or AAUDIO_ERROR_UNAVAILABLE or other negative error
304      */
305     virtual aaudio_result_t getFreeRunningPosition_l(
306             int64_t *positionFrames, int64_t *timeNanos) = 0;
307 
308     virtual aaudio_result_t getHardwareTimestamp_l(int64_t *positionFrames, int64_t *timeNanos) = 0;
309 
310     virtual aaudio_result_t getAudioDataDescription_l(AudioEndpointParcelable* parcelable) = 0;
311 
312 
313     aaudio_stream_state_t   mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
314 
isDisconnected_l()315     bool isDisconnected_l() const REQUIRES(mLock) {
316         return mDisconnected;
317     }
setDisconnected_l(bool flag)318     void setDisconnected_l(bool flag) REQUIRES(mLock) {
319         mDisconnected = flag;
320     }
321 
standby_l()322     virtual aaudio_result_t standby_l() REQUIRES(mLock) {
323         return AAUDIO_ERROR_UNIMPLEMENTED;
324     }
325     class ExitStandbyParam : public AAudioCommandParam {
326     public:
ExitStandbyParam(AudioEndpointParcelable * parcelable)327         ExitStandbyParam(AudioEndpointParcelable* parcelable)
328                 : AAudioCommandParam(), mParcelable(parcelable) { }
329         ~ExitStandbyParam() = default;
330 
331         AudioEndpointParcelable* mParcelable;
332     };
exitStandby_l(AudioEndpointParcelable * parcelable __unused)333     virtual aaudio_result_t exitStandby_l(
334             AudioEndpointParcelable* parcelable __unused) REQUIRES(mLock) {
335         return AAUDIO_ERROR_UNAVAILABLE;
336     }
isStandby_l()337     bool isStandby_l() const REQUIRES(mLock) {
338         return mStandby;
339     }
setStandby_l(bool standby)340     void setStandby_l(bool standby) REQUIRES(mLock) {
341         mStandby = standby;
342     }
343 
isIdle_l()344     bool isIdle_l() const REQUIRES(mLock) {
345         return mState == AAUDIO_STREAM_STATE_OPEN || mState == AAUDIO_STREAM_STATE_PAUSED
346                 || mState == AAUDIO_STREAM_STATE_STOPPED;
347     }
348 
349     pid_t                   mRegisteredClientThread = ILLEGAL_THREAD_ID;
350 
351     std::mutex              mUpMessageQueueLock;
352     std::shared_ptr<SharedRingBuffer> mUpMessageQueue;
353 
354     enum : int32_t {
355         START,
356         PAUSE,
357         STOP,
358         FLUSH,
359         CLOSE,
360         DISCONNECT,
361         REGISTER_AUDIO_THREAD,
362         UNREGISTER_AUDIO_THREAD,
363         GET_DESCRIPTION,
364         EXIT_STANDBY,
365     };
366     AAudioThread            mCommandThread;
367     std::atomic<bool>       mThreadEnabled{false};
368     AAudioCommandQueue      mCommandQueue;
369 
370     int32_t                 mFramesPerBurst = 0;
371     android::AudioClient    mMmapClient; // set in open, used in MMAP start()
372     // TODO rename mClientHandle to mPortHandle to be more consistent with AudioFlinger.
373     audio_port_handle_t     mClientHandle = AUDIO_PORT_HANDLE_NONE;
374 
375     SimpleDoubleBuffer<Timestamp>  mAtomicStreamTimestamp;
376 
377     android::AAudioService &mAudioService;
378 
379     // The mServiceEndpoint variable can be accessed by multiple threads.
380     // So we access it by locally promoting a weak pointer to a smart pointer,
381     // which is thread-safe.
382     android::sp<AAudioServiceEndpoint> mServiceEndpoint;
383     android::wp<AAudioServiceEndpoint> mServiceEndpointWeak;
384 
385     std::string mMetricsId;  // set once during open()
386 
387 private:
388 
389     aaudio_result_t stopTimestampThread();
390 
391     /**
392      * Send a message to the client with an int64_t data value.
393      */
394     aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
395                                      int64_t dataLong = 0);
396     /**
397      * Send a message to the client with a double data value.
398      */
399     aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
400                                      double dataDouble);
401 
402     aaudio_result_t sendCommand(aaudio_command_opcode opCode,
403                                 std::shared_ptr<AAudioCommandParam> param = nullptr,
404                                 bool waitForReply = false,
405                                 int64_t timeoutNanos = 0);
406 
407     aaudio_result_t closeAndClear();
408 
409     /**
410      * @return true if the queue is getting full.
411      */
412     bool isUpMessageQueueBusy();
413 
414     aaudio_handle_t         mHandle = -1;
415     bool                    mFlowing = false;
416 
417     // This indicates that a stream that is being referenced by a binder call
418     // and needs to closed.
419     std::atomic<bool>       mCloseNeeded{false}; // TODO remove
420 
421     // This indicate that a running stream should not be processed because of an error,
422     // for example a full message queue. Note that this atomic is unrelated to mCloseNeeded.
423     std::atomic<bool>       mSuspended{false};
424 
GUARDED_BY(mLock)425     bool                    mDisconnected GUARDED_BY(mLock) {false};
426 
427     bool                    mStandby GUARDED_BY(mLock) = false;
428 
429 protected:
430     // Locking order is important.
431     // Acquire mLock before acquiring AAudioServiceEndpoint::mLockStreams
432     // The lock will be held by the command thread. All operations needing the lock must run from
433     // the command thread.
434     std::mutex              mLock; // Prevent start/stop/close etcetera from colliding
435 };
436 
437 } /* namespace aaudio */
438 
439 #endif //AAUDIO_AAUDIO_SERVICE_STREAM_BASE_H
440