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