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