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