audio_request_manager.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  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. #include "chre/core/audio_request_manager.h"
  17. #include "chre/core/event_loop_manager.h"
  18. #include "chre/platform/fatal_error.h"
  19. #include "chre/platform/system_time.h"
  20. #include "chre/util/system/debug_dump.h"
  21. /*
  22. * TODO(P1-62e045): Evict pending audio events from the event queue as needed.
  23. *
  24. * Under the following conditions, an audio data event may be posted to the
  25. * CHRE event queue when it should not be.
  26. *
  27. * 1. Nanoapp changes request
  28. * 2. Nanoapp removes request
  29. *
  30. * A previously scheduled audio data event may be residing in the event queue
  31. * and will be dispatched to the nanoapp after it has cancelled the request.
  32. *
  33. * The solution is to evict any audio events for a given audio handle that are
  34. * directed to a nanoapp before scheduling the next request to the platform.
  35. */
  36. namespace chre {
  37. void AudioRequestManager::init() {
  38. mPlatformAudio.init();
  39. size_t sourceCount = mPlatformAudio.getSourceCount();
  40. if (!mAudioRequestLists.reserve(sourceCount)) {
  41. FATAL_ERROR_OOM();
  42. }
  43. for (size_t i = 0; i < sourceCount; i++) {
  44. mAudioRequestLists.emplace_back();
  45. }
  46. }
  47. bool AudioRequestManager::configureSource(const Nanoapp *nanoapp,
  48. uint32_t handle,
  49. bool enable,
  50. uint64_t bufferDuration,
  51. uint64_t deliveryInterval) {
  52. uint32_t numSamples;
  53. return validateConfigureSourceArguments(handle, enable, bufferDuration,
  54. deliveryInterval, &numSamples)
  55. && doConfigureSource(nanoapp->getInstanceId(), handle, enable, numSamples,
  56. Nanoseconds(deliveryInterval));
  57. }
  58. void AudioRequestManager::handleAudioDataEvent(
  59. const struct chreAudioDataEvent *audioDataEvent) {
  60. uint32_t handle = audioDataEvent->handle;
  61. if (handle >= mAudioRequestLists.size()) {
  62. LOGE("Received audio event for unknown handle %" PRIu32, handle);
  63. } else {
  64. mAudioRequestLists[handle].lastEventTimestamp
  65. = SystemTime::getMonotonicTime();
  66. }
  67. auto callback = [](uint16_t /* eventType */, void *eventData) {
  68. auto *event = static_cast<struct chreAudioDataEvent *>(eventData);
  69. EventLoopManagerSingleton::get()->getAudioRequestManager()
  70. .handleAudioDataEventSync(event);
  71. };
  72. // Cast off the event const so that it can be provided to the free callback as
  73. // non-const. The event is provided to nanoapps as const and the runtime
  74. // itself will not modify this memory so this is safe.
  75. EventLoopManagerSingleton::get()->deferCallback(
  76. SystemCallbackType::AudioHandleDataEvent,
  77. const_cast<struct chreAudioDataEvent *>(audioDataEvent), callback);
  78. }
  79. void AudioRequestManager::handleAudioAvailability(uint32_t handle, bool available) {
  80. struct CallbackState {
  81. uint32_t handle;
  82. bool available;
  83. };
  84. auto *cbState = memoryAlloc<CallbackState>();
  85. if (cbState == nullptr) {
  86. LOG_OOM();
  87. } else {
  88. cbState->handle = handle;
  89. cbState->available = available;
  90. auto callback = [](uint16_t /* eventType */, void *eventData) {
  91. auto *state = static_cast<CallbackState *>(eventData);
  92. EventLoopManagerSingleton::get()->getAudioRequestManager()
  93. .handleAudioAvailabilitySync(state->handle, state->available);
  94. memoryFree(state);
  95. };
  96. EventLoopManagerSingleton::get()->deferCallback(
  97. SystemCallbackType::AudioAvailabilityChange, cbState, callback);
  98. }
  99. }
  100. void AudioRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
  101. size_t bufferSize) const {
  102. debugDumpPrint(buffer, bufferPos, bufferSize, "\nAudio:\n");
  103. for (size_t i = 0; i < mAudioRequestLists.size(); i++) {
  104. uint32_t handle = static_cast<uint32_t>(i);
  105. struct chreAudioSource source;
  106. mPlatformAudio.getAudioSource(handle, &source);
  107. Nanoseconds timeSinceLastAudioEvent = SystemTime::getMonotonicTime()
  108. - mAudioRequestLists[i].lastEventTimestamp;
  109. debugDumpPrint(buffer, bufferPos, bufferSize,
  110. " handle=%" PRIu32 ", name=\"%s\", available=%d, sampleRate=%" PRIu32
  111. ", buffer(ms)=[%" PRIu64 ",%" PRIu64 "], format=%" PRIu8
  112. ", timeSinceLastAudioEvent(ms)=%" PRIu64 "\n",
  113. handle, source.name, mAudioRequestLists[i].available, source.sampleRate,
  114. Milliseconds(Nanoseconds(source.minBufferDuration)).getMilliseconds(),
  115. Milliseconds(Nanoseconds(source.maxBufferDuration)).getMilliseconds(),
  116. source.format, Milliseconds(timeSinceLastAudioEvent).getMilliseconds());
  117. for (const auto& request : mAudioRequestLists[i].requests) {
  118. for (const auto& instanceId : request.instanceIds) {
  119. debugDumpPrint(buffer, bufferPos, bufferSize,
  120. " nanoappId=%" PRIu32 ", numSamples=%" PRIu32
  121. ", interval(ms)=%" PRIu64 "\n", instanceId, request.numSamples,
  122. Milliseconds(Nanoseconds(request.deliveryInterval))
  123. .getMilliseconds());
  124. }
  125. }
  126. }
  127. }
  128. bool AudioRequestManager::validateConfigureSourceArguments(
  129. uint32_t handle, bool enable, uint64_t bufferDuration,
  130. uint64_t deliveryInterval, uint32_t *numSamples) {
  131. bool success = false;
  132. if (handle >= mAudioRequestLists.size()) {
  133. LOGE("Provided audio handle out of range");
  134. } else if (enable) {
  135. chreAudioSource audioSource;
  136. if (!mPlatformAudio.getAudioSource(handle, &audioSource)) {
  137. LOGE("Failed to query for audio source");
  138. } else if (bufferDuration > deliveryInterval) {
  139. LOGE("Buffer duration must be less than or equal to delivery interval");
  140. } else if (bufferDuration < audioSource.minBufferDuration
  141. || bufferDuration > audioSource.maxBufferDuration) {
  142. LOGE("Invalid buffer duration %" PRIu64 " not in range [%" PRIu64
  143. ",%" PRIu64 "]", bufferDuration, audioSource.minBufferDuration,
  144. audioSource.maxBufferDuration);
  145. } else {
  146. *numSamples = getSampleCountFromRateAndDuration(
  147. audioSource.sampleRate, Nanoseconds(bufferDuration));
  148. success = true;
  149. }
  150. } else {
  151. // Disabling the request, no need to validate bufferDuration or
  152. // deliveryInterval.
  153. success = true;
  154. }
  155. return success;
  156. }
  157. bool AudioRequestManager::doConfigureSource(
  158. uint32_t instanceId, uint32_t handle, bool enable, uint32_t numSamples,
  159. Nanoseconds deliveryInterval) {
  160. size_t requestIndex;
  161. size_t requestInstanceIdIndex;
  162. auto *audioRequest = findAudioRequestByInstanceId(
  163. handle, instanceId, &requestIndex, &requestInstanceIdIndex);
  164. AudioRequestList& requestList = mAudioRequestLists[handle];
  165. size_t lastNumRequests = requestList.requests.size();
  166. bool success = false;
  167. if (audioRequest == nullptr) {
  168. if (enable) {
  169. success = createAudioRequest(handle, instanceId, numSamples,
  170. deliveryInterval);
  171. } else {
  172. LOGW("Nanoapp disabling nonexistent audio request");
  173. }
  174. } else {
  175. if (audioRequest->instanceIds.size() > 1) {
  176. // If there are other clients listening in this configuration, remove
  177. // just the instance ID.
  178. audioRequest->instanceIds.erase(requestInstanceIdIndex);
  179. } else {
  180. // If this is the last client listening in this configuration, remove
  181. // the entire request.
  182. requestList.requests.erase(requestIndex);
  183. }
  184. // If the client is disabling, there is nothing to do, otherwise a request
  185. // must be created successfully.
  186. success = (!enable || createAudioRequest(handle, instanceId, numSamples,
  187. deliveryInterval));
  188. }
  189. if (success) {
  190. scheduleNextAudioDataEvent(handle);
  191. updatePlatformHandleEnabled(handle, lastNumRequests);
  192. }
  193. return success;
  194. }
  195. void AudioRequestManager::updatePlatformHandleEnabled(
  196. uint32_t handle, size_t lastNumRequests) {
  197. size_t numRequests = mAudioRequestLists[handle].requests.size();
  198. if (lastNumRequests == 0 && numRequests > 0) {
  199. mPlatformAudio.setHandleEnabled(handle, true /* enabled */);
  200. } else if (lastNumRequests > 0 && numRequests == 0) {
  201. mPlatformAudio.setHandleEnabled(handle, false /* enabled */);
  202. }
  203. }
  204. bool AudioRequestManager::createAudioRequest(
  205. uint32_t handle, uint32_t instanceId, uint32_t numSamples,
  206. Nanoseconds deliveryInterval) {
  207. AudioRequestList& requestList = mAudioRequestLists[handle];
  208. size_t matchingRequestIndex;
  209. auto *matchingAudioRequest = findAudioRequestByConfiguration(
  210. handle, numSamples, deliveryInterval, &matchingRequestIndex);
  211. bool success = false;
  212. if (matchingAudioRequest != nullptr) {
  213. if (!matchingAudioRequest->instanceIds.push_back(instanceId)) {
  214. LOG_OOM();
  215. } else {
  216. success = true;
  217. }
  218. } else {
  219. Nanoseconds timeNow = SystemTime::getMonotonicTime();
  220. Nanoseconds nextEventTimestamp = timeNow + deliveryInterval;
  221. if (!requestList.requests.emplace_back(numSamples, deliveryInterval,
  222. nextEventTimestamp)) {
  223. LOG_OOM();
  224. } else if (!requestList.requests.back().instanceIds.push_back(instanceId)) {
  225. requestList.requests.pop_back();
  226. LOG_OOM();
  227. } else {
  228. success = true;
  229. }
  230. }
  231. if (success) {
  232. postAudioSamplingChangeEvent(instanceId, handle, requestList.available);
  233. }
  234. return success;
  235. }
  236. AudioRequestManager::AudioRequest *AudioRequestManager::
  237. findAudioRequestByInstanceId(
  238. uint32_t handle, uint32_t instanceId, size_t *index,
  239. size_t *instanceIdIndex) {
  240. AudioRequest *foundAudioRequest = nullptr;
  241. auto& requests = mAudioRequestLists[handle].requests;
  242. for (size_t i = 0; i < requests.size(); i++) {
  243. auto& audioRequest = requests[i];
  244. size_t foundInstanceIdIndex = audioRequest.instanceIds.find(instanceId);
  245. if (foundInstanceIdIndex != audioRequest.instanceIds.size()) {
  246. foundAudioRequest = &audioRequest;
  247. *index = i;
  248. *instanceIdIndex = foundInstanceIdIndex;
  249. break;
  250. }
  251. }
  252. return foundAudioRequest;
  253. }
  254. AudioRequestManager::AudioRequest *AudioRequestManager::
  255. findAudioRequestByConfiguration(
  256. uint32_t handle, uint32_t numSamples, Nanoseconds deliveryInterval,
  257. size_t *index) {
  258. AudioRequest *foundAudioRequest = nullptr;
  259. auto& requests = mAudioRequestLists[handle].requests;
  260. for (size_t i = 0; i < requests.size(); i++) {
  261. auto& audioRequest = requests[i];
  262. if (audioRequest.numSamples == numSamples
  263. && audioRequest.deliveryInterval == deliveryInterval) {
  264. foundAudioRequest = &audioRequest;
  265. *index = i;
  266. break;
  267. }
  268. }
  269. return foundAudioRequest;
  270. }
  271. AudioRequestManager::AudioRequest *AudioRequestManager::findNextAudioRequest(
  272. uint32_t handle) {
  273. Nanoseconds earliestNextEventTimestamp = Nanoseconds(UINT64_MAX);
  274. AudioRequest *nextRequest = nullptr;
  275. auto& reqList = mAudioRequestLists[handle];
  276. for (auto& req : reqList.requests) {
  277. if (req.nextEventTimestamp < earliestNextEventTimestamp) {
  278. earliestNextEventTimestamp = req.nextEventTimestamp;
  279. nextRequest = &req;
  280. }
  281. }
  282. return nextRequest;
  283. }
  284. void AudioRequestManager::handleAudioDataEventSync(
  285. struct chreAudioDataEvent *event) {
  286. uint32_t handle = event->handle;
  287. if (handle < mAudioRequestLists.size()) {
  288. auto& reqList = mAudioRequestLists[handle];
  289. AudioRequest *nextAudioRequest = reqList.nextAudioRequest;
  290. if (nextAudioRequest != nullptr) {
  291. postAudioDataEventFatal(event, nextAudioRequest->instanceIds);
  292. nextAudioRequest->nextEventTimestamp = SystemTime::getMonotonicTime()
  293. + nextAudioRequest->deliveryInterval;
  294. } else {
  295. LOGW("Received audio data event with no pending audio request");
  296. mPlatformAudio.releaseAudioDataEvent(event);
  297. }
  298. scheduleNextAudioDataEvent(handle);
  299. } else {
  300. LOGE("Audio data event handle out of range: %" PRIu32, handle);
  301. }
  302. }
  303. void AudioRequestManager::handleAudioAvailabilitySync(uint32_t handle,
  304. bool available) {
  305. if (handle < mAudioRequestLists.size()) {
  306. if (mAudioRequestLists[handle].available != available) {
  307. mAudioRequestLists[handle].available = available;
  308. postAudioSamplingChangeEvents(handle);
  309. }
  310. scheduleNextAudioDataEvent(handle);
  311. } else {
  312. LOGE("Audio availability handle out of range: %" PRIu32, handle);
  313. }
  314. }
  315. void AudioRequestManager::scheduleNextAudioDataEvent(uint32_t handle) {
  316. auto& reqList = mAudioRequestLists[handle];
  317. AudioRequest *nextRequest = findNextAudioRequest(handle);
  318. // Clear the next request and it will be reset below if needed.
  319. reqList.nextAudioRequest = nullptr;
  320. if (reqList.available && nextRequest != nullptr) {
  321. Nanoseconds curTime = SystemTime::getMonotonicTime();
  322. Nanoseconds eventDelay = Nanoseconds(0);
  323. if (nextRequest->nextEventTimestamp > curTime) {
  324. eventDelay = nextRequest->nextEventTimestamp - curTime;
  325. }
  326. reqList.nextAudioRequest = nextRequest;
  327. mPlatformAudio.requestAudioDataEvent(
  328. handle, nextRequest->numSamples, eventDelay);
  329. } else {
  330. mPlatformAudio.cancelAudioDataEventRequest(handle);
  331. }
  332. }
  333. void AudioRequestManager::postAudioSamplingChangeEvents(uint32_t handle) {
  334. const auto& requestList = mAudioRequestLists[handle];
  335. for (const auto& request : requestList.requests) {
  336. for (const auto& instanceId : request.instanceIds) {
  337. postAudioSamplingChangeEvent(instanceId, handle, requestList.available);
  338. }
  339. }
  340. }
  341. void AudioRequestManager::postAudioSamplingChangeEvent(uint32_t instanceId,
  342. uint32_t handle,
  343. bool available) {
  344. auto *event = memoryAlloc<struct chreAudioSourceStatusEvent>();
  345. event->handle = handle;
  346. event->status.enabled = true;
  347. event->status.suspended = !available;
  348. EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  349. CHRE_EVENT_AUDIO_SAMPLING_CHANGE, event, freeEventDataCallback,
  350. instanceId);
  351. }
  352. void AudioRequestManager::postAudioDataEventFatal(
  353. struct chreAudioDataEvent *event,
  354. const DynamicVector<uint32_t>& instanceIds) {
  355. if (instanceIds.empty()) {
  356. LOGW("Received audio data event for no clients");
  357. mPlatformAudio.releaseAudioDataEvent(event);
  358. } else {
  359. for (const auto &instanceId : instanceIds) {
  360. EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  361. CHRE_EVENT_AUDIO_DATA, event, freeAudioDataEventCallback, instanceId);
  362. }
  363. mAudioDataEventRefCounts.emplace_back(
  364. event, static_cast<uint32_t>(instanceIds.size()));
  365. }
  366. }
  367. void AudioRequestManager::handleFreeAudioDataEvent(
  368. struct chreAudioDataEvent *audioDataEvent) {
  369. size_t audioDataEventRefCountIndex =
  370. mAudioDataEventRefCounts.find(AudioDataEventRefCount(audioDataEvent));
  371. if (audioDataEventRefCountIndex == mAudioDataEventRefCounts.size()) {
  372. LOGE("Freeing invalid audio data event");
  373. } else {
  374. auto& audioDataEventRefCount =
  375. mAudioDataEventRefCounts[audioDataEventRefCountIndex];
  376. if (audioDataEventRefCount.refCount == 0) {
  377. LOGE("Attempting to free an event with zero published events");
  378. } else {
  379. audioDataEventRefCount.refCount--;
  380. if (audioDataEventRefCount.refCount == 0) {
  381. mAudioDataEventRefCounts.erase(audioDataEventRefCountIndex);
  382. mPlatformAudio.releaseAudioDataEvent(audioDataEvent);
  383. }
  384. }
  385. }
  386. }
  387. void AudioRequestManager::freeAudioDataEventCallback(uint16_t eventType,
  388. void *eventData) {
  389. auto *event = static_cast<struct chreAudioDataEvent *>(eventData);
  390. EventLoopManagerSingleton::get()->getAudioRequestManager()
  391. .handleFreeAudioDataEvent(event);
  392. }
  393. } // namespace chre