• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 CHRE_CORE_AUDIO_REQUEST_MANAGER_H_
18 #define CHRE_CORE_AUDIO_REQUEST_MANAGER_H_
19 
20 #include <cstdint>
21 
22 #include "chre/core/nanoapp.h"
23 #include "chre/core/settings.h"
24 #include "chre/platform/platform_audio.h"
25 #include "chre/util/dynamic_vector.h"
26 #include "chre/util/non_copyable.h"
27 #include "chre_api/chre/audio.h"
28 
29 namespace chre {
30 
31 /**
32  * Manages requests for audio resources from nanoapps and multiplexes these
33  * requests into the platform-specific implementation of the audio subsystem.
34  */
35 class AudioRequestManager : public NonCopyable {
36  public:
37   /**
38    * Initializes the platform-specific audio module. Must be called prior to
39    * invoking any other methods in this class.
40    *
41    * Sets up the initial condition for the audio request manager including
42    * initial allocation of requests managers.
43    */
44   void init();
45 
46   /**
47    * Obtains an audio source from the platform audio implementation.
48    *
49    * @param handle The audio source to query for.
50    * @param audioSource The audio source to populate with the details of this
51    *        handle, if found.
52    * @return true if the query was successful.
53    */
getAudioSource(uint32_t handle,struct chreAudioSource * audioSource)54   bool getAudioSource(uint32_t handle, struct chreAudioSource *audioSource) {
55     return mPlatformAudio.getAudioSource(handle, audioSource);
56   }
57 
58   /**
59    * Updates the current request for audio from a nanoapp for a given audio
60    * source.
61    *
62    * @param nanoapp A non-null pointer to the nanoapp requesting this change.
63    * @param handle The audio source handle for which this request is directed
64    *        toward.
65    * @param enable true if enabling the source, false if disabling.
66    * @param bufferDuration The amount of data to deliver to the nanoapp.
67    * @param deliveryInterval How frequently to deliver this data.
68    * @return true if the request was successful, false otherwise. When enabling,
69    *         the bufferDuration must be less than or equal to deliveryInterval.
70    *
71    * @see chreAudioConfigureSource()
72    */
73   bool configureSource(const Nanoapp *nanoapp, uint32_t handle, bool enable,
74                        uint64_t bufferDuration, uint64_t deliveryInterval);
75 
76   /**
77    * Disables all the active requests for a nanoapp.
78    *
79    * @param nanoapp A non-null pointer to the nanoapp.
80    * @return the number of requests cancelled.
81    */
82   uint32_t disableAllAudioRequests(const Nanoapp *nanoapp);
83 
84   /**
85    * Handles a new batch of audio from the PlatformAudio interface.
86    *
87    * @param event The audio data event provided to the audio request manager.
88    *        Ownership of this event is transferred to the CHRE runtime until it
89    *        is released via the PlatformAudio::releaseAudioDataEvent platform
90    *        API.
91    */
92   void handleAudioDataEvent(const struct chreAudioDataEvent *event);
93 
94   /**
95    * Handles events from the platform related to whether or not audio is
96    * available.
97    *
98    * @param handle The handle for which audio data availability has changed.
99    * @param available true if requests for audio data will be processed and
100    *        data events posted, false otherwise.
101    */
102   void handleAudioAvailability(uint32_t handle, bool available);
103 
104   /**
105    * Prints state in a string buffer. Must only be called from the context of
106    * the main CHRE thread.
107    *
108    * @param debugDump The debug dump wrapper where a string can be printed
109    *     into one of the buffers.
110    */
111   void logStateToBuffer(DebugDumpWrapper &debugDump) const;
112 
113   /**
114    * Invoked when the host notifies CHRE that microphone access has been
115    * disabled via the user settings.
116    *
117    * @param setting The setting that changed.
118    * @param enabled Whether setting is enabled or not.
119    */
120   void onSettingChanged(Setting setting, bool enabled);
121 
122   /**
123    * @return the instance of platform audio to allow platform-specific
124    * funtionality to call it. Example: handling host awake events.
125    */
getPlatformAudio()126   PlatformAudio &getPlatformAudio() {
127     return mPlatformAudio;
128   }
129 
130  private:
131   /**
132    * One instance of an audio request from a nanoapp.
133    */
134   struct AudioRequest {
AudioRequestAudioRequest135     AudioRequest(uint32_t numSamples, Nanoseconds deliveryInterval,
136                  Nanoseconds nextEventTimestamp)
137         : numSamples(numSamples),
138           deliveryInterval(deliveryInterval),
139           nextEventTimestamp(nextEventTimestamp) {}
140 
141     //! The nanoapp instance IDs that own this request.
142     DynamicVector<uint16_t> instanceIds;
143 
144     //! The number of samples requested for this request.
145     uint32_t numSamples;
146 
147     //! The delivery interval for this request.
148     Nanoseconds deliveryInterval;
149 
150     //! The expected timestamp of the next event delivery.
151     Nanoseconds nextEventTimestamp;
152   };
153 
154   /**
155    * A list of audio requests for a given source. Note that each nanoapp may
156    * have at most one open request for a given source. When the source is
157    * disabled it is removed from this list.
158    */
159   struct AudioRequestList {
160     //! Whether or not the source is available. It is unavailable by default.
161     bool available = false;
162 
163     //! The timestamp when the last audio data event was received.
164     Nanoseconds lastEventTimestamp;
165 
166     //! The request to post the next event to.
167     AudioRequest *nextAudioRequest = nullptr;
168 
169     //! The list of requests for this source that are currently open.
170     DynamicVector<AudioRequest> requests;
171   };
172 
173   /**
174    * Keep track of the number of times an audio data event is published to a
175    * nanoapp.
176    *
177    * TODO: Add support for multicast events to the core event loop to avoid this
178    * kind of logic from appearing in the AudioRequestManager.
179    */
180   struct AudioDataEventRefCount {
181     /**
182      * Constructs an AudioDataEventRefCount object with an uninitialized
183      * refCount to allow searching in a list using the equality comparison
184      * below.
185      *
186      * @param event The event that this object tracks.
187      */
AudioDataEventRefCountAudioDataEventRefCount188     explicit AudioDataEventRefCount(struct chreAudioDataEvent *event)
189         : event(event) {}
190 
AudioDataEventRefCountAudioDataEventRefCount191     AudioDataEventRefCount(struct chreAudioDataEvent *event, uint32_t refCount)
192         : event(event), refCount(refCount) {}
193 
194     /**
195      * @param audioDataEventRefCount The other object to perform an equality
196      *        comparison against.
197      * @return true if the supplied AudioDataEventRefCount is tracking the same
198      *         published event as current object.
199      */
200     bool operator==(const AudioDataEventRefCount &other) const {
201       return (event == other.event);
202     }
203 
204     //! The event that is ref counted here.
205     struct chreAudioDataEvent *event;
206 
207     //! The number of outstanding published events.
208     uint32_t refCount;
209   };
210 
211   //! Maps published audio data events to a refcount that is used to determine
212   //! when to let the platform audio implementation know that this audio data
213   //! event no longer needed.
214   DynamicVector<AudioDataEventRefCount> mAudioDataEventRefCounts;
215 
216   //! Maps audio handles to requests from multiple nanoapps for an audio source.
217   //! The array index implies the audio handle which is being managed.
218   DynamicVector<AudioRequestList> mAudioRequestLists;
219 
220   //! The instance of platform audio that is managed by this AudioRequestManager
221   //! and used to service requests for audio data.
222   PlatformAudio mPlatformAudio;
223 
224   /**
225    * Validates the arguments provided to configureSource to ensure that the
226    * handle is valid and enable, bufferDuration and deliveryInterval are in a
227    * valid configuration.
228    *
229    * @see configureSource for paramater documentation.
230    *
231    * @param numSamples Assigned the number of samples for this request if the
232    *        return value is true.
233    * @return true if the arguments are configured in a valid arrangement.
234    */
235   bool validateConfigureSourceArguments(uint32_t handle, bool enable,
236                                         uint64_t bufferDuration,
237                                         uint64_t deliveryInterval,
238                                         uint32_t *numSamples);
239 
240   /**
241    * Performs the configuration of an audio source with validated arguments. See
242    * configureSource for more details.
243    *
244    * @param instanceId The instanceId of the nanoapp making the request.
245    * @param handle The audio source that is being configured.
246    * @param enable true if enabling the source, false if disabling.
247    * @param numSamples The number of samples being requested.
248    * @param deliveryInterval When to deliver the samples.
249    * @return true if successful, false otherwise.
250    */
251   bool doConfigureSource(uint16_t instanceId, uint32_t handle, bool enable,
252                          uint32_t numSamples, Nanoseconds deliveryInterval);
253 
254   /**
255    * Notify the platform if a given handle has been enabled or disabled.
256    *
257    * @param handle The handle that may have changed enabled state.
258    * @param lastNumRequests The last number of requests for a handle before it
259    *        was reconfigured.
260    */
261   void updatePlatformHandleEnabled(uint32_t handle, size_t lastNumRequests);
262 
263   /**
264    * Creates an audio request given a configuration and instance ID for a given
265    * handle.
266    *
267    * @param handle The handle to create a request for.
268    * @param instanceId The instance ID that will own this request.
269    * @param numSamples The number of samples requested.
270    * @param deliveryInterval When to deliver the samples.
271    * @return true if successful, false otherwise.
272    */
273   bool createAudioRequest(uint32_t handle, uint16_t instanceId,
274                           uint32_t numSamples, Nanoseconds deliveryInterval);
275 
276   /**
277    * Finds an audio request for a given audio handle and nanoapp instance ID. If
278    * no existing request is available, nullptr is returned.
279    *
280    * @param handle The audio handle to query for. This must be guaranteed by the
281    *     caller to be less than the size of the mAudioRequestLists member.
282    * @param instanceId The nanoapp instance ID that owns the existing request
283    *     for this handle.
284    * @param index Populated with the index of the request if it was found.
285    * @param instanceIdIndex Populated with the index of the instance ID within
286    *        the returned audio request if it was found.
287    * @return The AudioRequest for this handle and instanceId, nullptr if not
288    *     found.
289    */
290   AudioRequest *findAudioRequestByInstanceId(uint32_t handle,
291                                              uint16_t instanceId, size_t *index,
292                                              size_t *instanceIdIndex);
293 
294   /**
295    * Finds an audio request for a given handle and configuration. If no existing
296    * request is available, nullptr is returned.
297    *
298    * @param handle The audio handle to query for. This must be guaranteed by the
299    *        caller to be less than the size of the mAudioRequestLists member.
300    * @param numSamples The number of samples to match for.
301    * @param deliveryInterval The delivery interval to match for.
302    * @param index Populated with the index of the request if it was found.
303    * @return The AudioRequest for this handle and configuration, nullptr if not
304    *     found.
305    */
306   AudioRequest *findAudioRequestByConfiguration(uint32_t handle,
307                                                 uint32_t numSamples,
308                                                 Nanoseconds deliveryInterval,
309                                                 size_t *index);
310 
311   /**
312    * Finds the next expiring request for audio data for a given handle.
313    *
314    * @param handle the handle to determine the next request to service for
315    * @return The audio request for this handle that expires next. If no requests
316    *         are bound to this handle, nullptr is returned.
317    */
318   AudioRequest *findNextAudioRequest(uint32_t handle);
319 
320   /**
321    * Handles an audio data event from the platform synchronously. This is
322    * invoked on the CHRE thread through a scheduled callback.
323    *
324    * @param event The event to provide to nanoapps containg audio data.
325    */
326   void handleAudioDataEventSync(struct chreAudioDataEvent *event);
327 
328   /**
329    * Handles audio availability from the platform synchronously. This is
330    * invoked on the CHRE thread through a deferred callback. Refer to
331    * handleAudioAvailability for details on these supplied parameters.
332    */
333   void handleAudioAvailabilitySync(uint32_t handle, bool available);
334 
335   /**
336    * Iterates the list of outstanding requests for the provided handle and
337    * schedules the next request to the platform.
338    *
339    * @param handle the audio source for which to schedule a request.
340    */
341   void scheduleNextAudioDataEvent(uint32_t handle);
342 
343   /**
344    * Posts CHRE_EVENT_AUDIO_SAMPLING_CHANGE events to all nanoapps subscribed to
345    * the supplied handle with the current availability of the source.
346    *
347    * @param handle The handle for the audio source that is changing.
348    * @param suspended Boolean value that indicates if the source is suspended
349    */
350   void postAudioSamplingChangeEvents(uint32_t handle, bool suspended);
351 
352   /**
353    * Posts a CHRE_EVENT_AUDIO_SAMPLING_CHANGE event to the specified nanoapp.
354    *
355    * @param instanceId The instance ID of the nanoapp to post to.
356    * @param handle The handle for the audio source that is changing.
357    * @param available true if audio is available for the supplied handle, false
358    *        otherwise.
359    * @param suspended Boolean value that indicates if the source is suspended
360    */
361   void postAudioSamplingChangeEvent(uint16_t instanceId, uint32_t handle,
362                                     bool available, bool suspended);
363 
364   /**
365    * Posts the provided audio data event to a nanoapp with the given instance ID
366    * and fails fatally if the event is not posted. Fatal error is an acceptable
367    * error handling mechanism here because there is no way to satisfy the
368    * requirements of the API without posting an event.
369    *
370    * @param audioDataEvent The audio data event to send to a nanoapp.
371    * @param instanceIds The list of nanoapp instance IDs to direct the event to.
372    */
373   void postAudioDataEventFatal(struct chreAudioDataEvent *event,
374                                const DynamicVector<uint16_t> &instanceIds);
375 
376   /**
377    * Invoked by the freeAudioDataEventCallback to decrement the reference count
378    * of the most recently published event and free it if unreferenced.
379    *
380    * @param audioDataEvent the audio data event to process.
381    */
382   void handleFreeAudioDataEvent(struct chreAudioDataEvent *audioDataEvent);
383 
384   /**
385    * Releases an audio data event after nanoapps have consumed it.
386    *
387    * @param eventType the type of event being freed.
388    * @param eventData a pointer to the scan event to release.
389    */
390   static void freeAudioDataEventCallback(uint16_t eventType, void *eventData);
391 };
392 
393 }  // namespace chre
394 
395 #endif  // CHRE_CORE_AUDIO_REQUEST_MANAGER_H_
396