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