• 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 numSamplesIn, Nanoseconds deliveryIntervalIn,
136                  Nanoseconds nextEventTimestampIn)
137         : numSamples(numSamplesIn),
138           deliveryInterval(deliveryIntervalIn),
139           nextEventTimestamp(nextEventTimestampIn) {}
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     AudioDataEventRefCount(struct chreAudioDataEvent *eventIn,
182                            const uint32_t refCountIn = 0)
eventAudioDataEventRefCount183         : event(eventIn), refCount(refCountIn) {}
184 
185     /**
186      * @param audioDataEventRefCount The other object to perform an equality
187      *        comparison against.
188      * @return true if the supplied AudioDataEventRefCount is tracking the same
189      *         published event as current object.
190      */
191     bool operator==(const AudioDataEventRefCount &other) const {
192       return (event == other.event);
193     }
194 
195     //! The event that is ref counted here.
196     struct chreAudioDataEvent *event;
197 
198     //! The number of outstanding published events.
199     uint32_t refCount;
200   };
201 
202   //! Maps published audio data events to a refcount that is used to determine
203   //! when to let the platform audio implementation know that this audio data
204   //! event no longer needed.
205   DynamicVector<AudioDataEventRefCount> mAudioDataEventRefCounts;
206 
207   //! Maps audio handles to requests from multiple nanoapps for an audio source.
208   //! The array index implies the audio handle which is being managed.
209   DynamicVector<AudioRequestList> mAudioRequestLists;
210 
211   //! The instance of platform audio that is managed by this AudioRequestManager
212   //! and used to service requests for audio data.
213   PlatformAudio mPlatformAudio;
214 
215   /**
216    * Validates the arguments provided to configureSource to ensure that the
217    * handle is valid and enable, bufferDuration and deliveryInterval are in a
218    * valid configuration.
219    *
220    * @see configureSource for paramater documentation.
221    *
222    * @param numSamples Assigned the number of samples for this request if the
223    *        return value is true.
224    * @return true if the arguments are configured in a valid arrangement.
225    */
226   bool validateConfigureSourceArguments(uint32_t handle, bool enable,
227                                         uint64_t bufferDuration,
228                                         uint64_t deliveryInterval,
229                                         uint32_t *numSamples);
230 
231   /**
232    * Performs the configuration of an audio source with validated arguments. See
233    * configureSource for more details.
234    *
235    * @param instanceId The instanceId of the nanoapp making the request.
236    * @param handle The audio source that is being configured.
237    * @param enable true if enabling the source, false if disabling.
238    * @param numSamples The number of samples being requested.
239    * @param deliveryInterval When to deliver the samples.
240    * @return true if successful, false otherwise.
241    */
242   bool doConfigureSource(uint16_t instanceId, uint32_t handle, bool enable,
243                          uint32_t numSamples, Nanoseconds deliveryInterval);
244 
245   /**
246    * Notify the platform if a given handle has been enabled or disabled.
247    *
248    * @param handle The handle that may have changed enabled state.
249    * @param lastNumRequests The last number of requests for a handle before it
250    *        was reconfigured.
251    */
252   void updatePlatformHandleEnabled(uint32_t handle, size_t lastNumRequests);
253 
254   /**
255    * Creates an audio request given a configuration and instance ID for a given
256    * handle.
257    *
258    * @param handle The handle to create a request for.
259    * @param instanceId The instance ID that will own this request.
260    * @param numSamples The number of samples requested.
261    * @param deliveryInterval When to deliver the samples.
262    * @return true if successful, false otherwise.
263    */
264   bool createAudioRequest(uint32_t handle, uint16_t instanceId,
265                           uint32_t numSamples, Nanoseconds deliveryInterval);
266 
267   /**
268    * Finds an audio request for a given audio handle and nanoapp instance ID. If
269    * no existing request is available, nullptr is returned.
270    *
271    * @param handle The audio handle to query for. This must be guaranteed by the
272    *     caller to be less than the size of the mAudioRequestLists member.
273    * @param instanceId The nanoapp instance ID that owns the existing request
274    *     for this handle.
275    * @param index Populated with the index of the request if it was found.
276    * @param instanceIdIndex Populated with the index of the instance ID within
277    *        the returned audio request if it was found.
278    * @return The AudioRequest for this handle and instanceId, nullptr if not
279    *     found.
280    */
281   AudioRequest *findAudioRequestByInstanceId(uint32_t handle,
282                                              uint16_t instanceId, size_t *index,
283                                              size_t *instanceIdIndex);
284 
285   /**
286    * Finds an audio request for a given handle and configuration. If no existing
287    * request is available, nullptr is returned.
288    *
289    * @param handle The audio handle to query for. This must be guaranteed by the
290    *        caller to be less than the size of the mAudioRequestLists member.
291    * @param numSamples The number of samples to match for.
292    * @param deliveryInterval The delivery interval to match for.
293    * @param index Populated with the index of the request if it was found.
294    * @return The AudioRequest for this handle and configuration, nullptr if not
295    *     found.
296    */
297   AudioRequest *findAudioRequestByConfiguration(uint32_t handle,
298                                                 uint32_t numSamples,
299                                                 Nanoseconds deliveryInterval,
300                                                 size_t *index);
301 
302   /**
303    * Finds the next expiring request for audio data for a given handle.
304    *
305    * @param handle the handle to determine the next request to service for
306    * @return The audio request for this handle that expires next. If no requests
307    *         are bound to this handle, nullptr is returned.
308    */
309   AudioRequest *findNextAudioRequest(uint32_t handle);
310 
311   /**
312    * Handles an audio data event from the platform synchronously. This is
313    * invoked on the CHRE thread through a scheduled callback.
314    *
315    * @param event The event to provide to nanoapps containg audio data.
316    */
317   void handleAudioDataEventSync(struct chreAudioDataEvent *event);
318 
319   /**
320    * Handles audio availability from the platform synchronously. This is
321    * invoked on the CHRE thread through a deferred callback. Refer to
322    * handleAudioAvailability for details on these supplied parameters.
323    */
324   void handleAudioAvailabilitySync(uint32_t handle, bool available);
325 
326   /**
327    * Iterates the list of outstanding requests for the provided handle and
328    * schedules the next request to the platform.
329    *
330    * @param handle the audio source for which to schedule a request.
331    */
332   void scheduleNextAudioDataEvent(uint32_t handle);
333 
334   /**
335    * Posts CHRE_EVENT_AUDIO_SAMPLING_CHANGE events to all nanoapps subscribed to
336    * the supplied handle with the current availability of the source.
337    *
338    * @param handle The handle for the audio source that is changing.
339    * @param suspended Boolean value that indicates if the source is suspended
340    */
341   void postAudioSamplingChangeEvents(uint32_t handle, bool suspended);
342 
343   /**
344    * Posts a CHRE_EVENT_AUDIO_SAMPLING_CHANGE event to the specified nanoapp.
345    *
346    * @param instanceId The instance ID of the nanoapp to post to.
347    * @param handle The handle for the audio source that is changing.
348    * @param available true if audio is available for the supplied handle, false
349    *        otherwise.
350    * @param suspended Boolean value that indicates if the source is suspended
351    */
352   void postAudioSamplingChangeEvent(uint16_t instanceId, uint32_t handle,
353                                     bool available, bool suspended);
354 
355   /**
356    * Posts the provided audio data event to a nanoapp with the given instance ID
357    * and fails fatally if the event is not posted. Fatal error is an acceptable
358    * error handling mechanism here because there is no way to satisfy the
359    * requirements of the API without posting an event.
360    *
361    * @param audioDataEvent The audio data event to send to a nanoapp.
362    * @param instanceIds The list of nanoapp instance IDs to direct the event to.
363    */
364   void postAudioDataEventFatal(struct chreAudioDataEvent *event,
365                                const DynamicVector<uint16_t> &instanceIds);
366 
367   /**
368    * Invoked by the freeAudioDataEventCallback to decrement the reference count
369    * of the most recently published event and free it if unreferenced.
370    *
371    * @param audioDataEvent the audio data event to process.
372    */
373   void handleFreeAudioDataEvent(struct chreAudioDataEvent *audioDataEvent);
374 
375   /**
376    * Releases an audio data event after nanoapps have consumed it.
377    *
378    * @param eventType the type of event being freed.
379    * @param eventData a pointer to the scan event to release.
380    */
381   static void freeAudioDataEventCallback(uint16_t eventType, void *eventData);
382 };
383 
384 }  // namespace chre
385 
386 #endif  // CHRE_CORE_AUDIO_REQUEST_MANAGER_H_
387