• 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 "SharedRingBuffer.h"
37 #include "AAudioThread.h"
38 
39 namespace android {
40     class AAudioService;
41 }
42 
43 namespace aaudio {
44 
45 class AAudioServiceEndpoint;
46 
47 // We expect the queue to only have a few commands.
48 // This should be way more than we need.
49 #define QUEUE_UP_CAPACITY_COMMANDS (128)
50 
51 /**
52  * Each instance of AAudioServiceStreamBase corresponds to a client stream.
53  * It uses a subclass of AAudioServiceEndpoint to communicate with the underlying device or port.
54  */
55 class AAudioServiceStreamBase
56     : public virtual android::RefBase
57     , public AAudioStreamParameters
58     , public Runnable  {
59 
60 public:
61     explicit AAudioServiceStreamBase(android::AAudioService &aAudioService);
62 
63     virtual ~AAudioServiceStreamBase();
64 
65     enum {
66         ILLEGAL_THREAD_ID = 0
67     };
68 
69     static std::string dumpHeader();
70 
71     // does not include EOL
72     virtual std::string dump() const;
73 
74     /**
75      * Open the device.
76      */
77     virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request) = 0;
78 
79     // We log the CLOSE from the close() method. We needed this separate method to log the OPEN
80     // because we had to wait until we generated the handle.
81     void logOpen(aaudio_handle_t streamHandle);
82 
83     aaudio_result_t close() EXCLUDES(mLock);
84 
85     /**
86      * Start the flow of audio data.
87      *
88      * This is not guaranteed to be synchronous but it currently is.
89      * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
90      */
91     aaudio_result_t start() EXCLUDES(mLock);
92 
93     /**
94      * Stop the flow of data so that start() can resume without loss of data.
95      *
96      * This is not guaranteed to be synchronous but it currently is.
97      * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
98     */
99     aaudio_result_t pause() EXCLUDES(mLock);
100 
101     /**
102      * Stop the flow of data after the currently queued data has finished playing.
103      *
104      * This is not guaranteed to be synchronous but it currently is.
105      * An AAUDIO_SERVICE_EVENT_STOPPED will be sent to the client when complete.
106      *
107      */
108     aaudio_result_t stop() EXCLUDES(mLock);
109 
110     /**
111      * Discard any data held by the underlying HAL or Service.
112      *
113      * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
114      */
115     aaudio_result_t flush() EXCLUDES(mLock);
116 
startClient(const android::AudioClient & client,const audio_attributes_t * attr __unused,audio_port_handle_t * clientHandle __unused)117     virtual aaudio_result_t startClient(const android::AudioClient& client,
118                                         const audio_attributes_t *attr __unused,
119                                         audio_port_handle_t *clientHandle __unused) {
120         ALOGD("AAudioServiceStreamBase::startClient(%p, ...) AAUDIO_ERROR_UNAVAILABLE", &client);
121         return AAUDIO_ERROR_UNAVAILABLE;
122     }
123 
stopClient(audio_port_handle_t clientHandle __unused)124     virtual aaudio_result_t stopClient(audio_port_handle_t clientHandle __unused) {
125         ALOGD("AAudioServiceStreamBase::stopClient(%d) AAUDIO_ERROR_UNAVAILABLE", clientHandle);
126         return AAUDIO_ERROR_UNAVAILABLE;
127     }
128 
129     aaudio_result_t registerAudioThread(pid_t clientThreadId, int priority) EXCLUDES(mLock);
130 
131     aaudio_result_t unregisterAudioThread(pid_t clientThreadId) EXCLUDES(mLock);
132 
isRunning()133     bool isRunning() const {
134         return mState == AAUDIO_STREAM_STATE_STARTED;
135     }
136 
137     /**
138      * Fill in a parcelable description of stream.
139      */
140     aaudio_result_t getDescription(AudioEndpointParcelable &parcelable) EXCLUDES(mLock);
141 
setRegisteredThread(pid_t pid)142     void setRegisteredThread(pid_t pid) {
143         mRegisteredClientThread = pid;
144     }
145 
getRegisteredThread()146     pid_t getRegisteredThread() const {
147         return mRegisteredClientThread;
148     }
149 
getFramesPerBurst()150     int32_t getFramesPerBurst() const {
151         return mFramesPerBurst;
152     }
153 
154     void run() override; // to implement Runnable
155 
156     void disconnect() EXCLUDES(mLock);
157 
getAudioClient()158     const android::AudioClient &getAudioClient() {
159         return mMmapClient;
160     }
161 
getOwnerUserId()162     uid_t getOwnerUserId() const {
163         return VALUE_OR_FATAL(android::aidl2legacy_int32_t_uid_t(
164                 mMmapClient.attributionSource.uid));
165     }
166 
getOwnerProcessId()167     pid_t getOwnerProcessId() const {
168         return VALUE_OR_FATAL(android::aidl2legacy_int32_t_pid_t(
169                 mMmapClient.attributionSource.pid));
170     }
171 
getHandle()172     aaudio_handle_t getHandle() const {
173         return mHandle;
174     }
setHandle(aaudio_handle_t handle)175     void setHandle(aaudio_handle_t handle) {
176         mHandle = handle;
177     }
178 
getPortHandle()179     audio_port_handle_t getPortHandle() const {
180         return mClientHandle;
181     }
182 
getState()183     aaudio_stream_state_t getState() const {
184         return mState;
185     }
186 
187     void onVolumeChanged(float volume);
188 
189     /**
190      * Set false when the stream is started.
191      * Set true when data is first read from the stream.
192      * @param b
193      */
setFlowing(bool b)194     void setFlowing(bool b) {
195         mFlowing = b;
196     }
197 
isFlowing()198     bool isFlowing() const {
199         return mFlowing;
200     }
201 
202     /**
203      * Set false when the stream should not longer be processed.
204      * This may be caused by a message queue overflow.
205      * Set true when stream is started.
206      * @param suspended
207      */
setSuspended(bool suspended)208     void setSuspended(bool suspended) {
209         mSuspended = suspended;
210     }
211 
isSuspended()212     bool isSuspended() const {
213         return mSuspended;
214     }
215 
isCloseNeeded()216     bool isCloseNeeded() const {
217         return mCloseNeeded.load();
218     }
219 
220     /**
221      * Mark this stream as needing to be closed.
222      * Once marked for closing, it cannot be unmarked.
223      */
markCloseNeeded()224     void markCloseNeeded() {
225         mCloseNeeded.store(true);
226     }
227 
getTypeText()228     virtual const char *getTypeText() const { return "Base"; }
229 
230 protected:
231 
232     /**
233      * Open the device.
234      */
235     aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
236                          aaudio_sharing_mode_t sharingMode);
237 
238     virtual aaudio_result_t close_l() REQUIRES(mLock);
239     virtual aaudio_result_t pause_l() REQUIRES(mLock);
240     virtual aaudio_result_t stop_l() REQUIRES(mLock);
241     void disconnect_l() REQUIRES(mLock);
242 
243     void setState(aaudio_stream_state_t state);
244 
245     /**
246      * Device specific startup.
247      * @return AAUDIO_OK or negative error.
248      */
249     virtual aaudio_result_t startDevice();
250 
251     aaudio_result_t writeUpMessageQueue(AAudioServiceMessage *command);
252 
253     aaudio_result_t sendCurrentTimestamp() EXCLUDES(mLock);
254 
255     aaudio_result_t sendXRunCount(int32_t xRunCount);
256 
257     /**
258      * @param positionFrames
259      * @param timeNanos
260      * @return AAUDIO_OK or AAUDIO_ERROR_UNAVAILABLE or other negative error
261      */
262     virtual aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) = 0;
263 
264     virtual aaudio_result_t getHardwareTimestamp(int64_t *positionFrames, int64_t *timeNanos) = 0;
265 
266     virtual aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) = 0;
267 
268     aaudio_stream_state_t   mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
269 
isDisconnected_l()270     bool isDisconnected_l() const REQUIRES(mLock) {
271         return mDisconnected;
272     }
setDisconnected_l(bool flag)273     void setDisconnected_l(bool flag) REQUIRES(mLock) {
274         mDisconnected = flag;
275     }
276 
277     pid_t                   mRegisteredClientThread = ILLEGAL_THREAD_ID;
278 
279     std::mutex              mUpMessageQueueLock;
280     std::shared_ptr<SharedRingBuffer> mUpMessageQueue;
281 
282     AAudioThread            mTimestampThread;
283     // This is used by one thread to tell another thread to exit. So it must be atomic.
284     std::atomic<bool>       mThreadEnabled{false};
285 
286     int32_t                 mFramesPerBurst = 0;
287     android::AudioClient    mMmapClient; // set in open, used in MMAP start()
288     // TODO rename mClientHandle to mPortHandle to be more consistent with AudioFlinger.
289     audio_port_handle_t     mClientHandle = AUDIO_PORT_HANDLE_NONE;
290 
291     SimpleDoubleBuffer<Timestamp>  mAtomicStreamTimestamp;
292 
293     android::AAudioService &mAudioService;
294 
295     // The mServiceEndpoint variable can be accessed by multiple threads.
296     // So we access it by locally promoting a weak pointer to a smart pointer,
297     // which is thread-safe.
298     android::sp<AAudioServiceEndpoint> mServiceEndpoint;
299     android::wp<AAudioServiceEndpoint> mServiceEndpointWeak;
300 
301     std::string mMetricsId;  // set once during open()
302 
303 private:
304 
305     aaudio_result_t stopTimestampThread();
306 
307     /**
308      * Send a message to the client with an int64_t data value.
309      */
310     aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
311                                      int64_t dataLong = 0);
312     /**
313      * Send a message to the client with a double data value.
314      */
315     aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
316                                      double dataDouble);
317 
318     /**
319      * @return true if the queue is getting full.
320      */
321     bool isUpMessageQueueBusy();
322 
323     aaudio_handle_t         mHandle = -1;
324     bool                    mFlowing = false;
325 
326     // This indicates that a stream that is being referenced by a binder call
327     // and needs to closed.
328     std::atomic<bool>       mCloseNeeded{false}; // TODO remove
329 
330     // This indicate that a running stream should not be processed because of an error,
331     // for example a full message queue. Note that this atomic is unrelated to mCloseNeeded.
332     std::atomic<bool>       mSuspended{false};
333 
GUARDED_BY(mLock)334     bool                    mDisconnected GUARDED_BY(mLock) {false};
335 
336 protected:
337     // Locking order is important.
338     // Acquire mLock before acquiring AAudioServiceEndpoint::mLockStreams
339     std::mutex              mLock; // Prevent start/stop/close etcetera from colliding
340 };
341 
342 } /* namespace aaudio */
343 
344 #endif //AAUDIO_AAUDIO_SERVICE_STREAM_BASE_H
345