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