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 #include "chre/platform/platform_audio.h" 18 19 #include <cstring> 20 21 #include "chre/core/event_loop_manager.h" 22 #include "chre/platform/host_link.h" 23 #include "chre/platform/log.h" 24 #include "chre/platform/shared/pal_system_api.h" 25 #include "chre/platform/slpi/power_control_util.h" 26 27 namespace chre { 28 namespace { 29 30 void handleAudioDataEvent(struct chreAudioDataEvent *event) { 31 EventLoopManagerSingleton::get() 32 ->getAudioRequestManager() 33 .handleAudioDataEvent(event); 34 } 35 36 void handleAudioAvailability(uint32_t handle, bool available) { 37 LOGD("SPI audio handle %" PRIu32 " available: %d", handle, available); 38 EventLoopManagerSingleton::get() 39 ->getAudioRequestManager() 40 .handleAudioAvailability(handle, available); 41 } 42 43 } // anonymous namespace 44 45 const chrePalAudioCallbacks PlatformAudioBase::sAudioCallbacks = { 46 handleAudioDataEvent, 47 handleAudioAvailability, 48 }; 49 50 PlatformAudio::PlatformAudio() {} 51 52 PlatformAudio::~PlatformAudio() { 53 if (mAudioApi != nullptr) { 54 LOGD("Platform audio closing"); 55 prePalApiCall(); 56 mAudioApi->close(); 57 LOGD("Platform audio closed"); 58 } 59 } 60 61 void PlatformAudio::init() { 62 prePalApiCall(); 63 mAudioApi = chrePalAudioGetApi(CHRE_PAL_AUDIO_API_CURRENT_VERSION); 64 if (mAudioApi != nullptr) { 65 if (!mAudioApi->open(&gChrePalSystemApi, &sAudioCallbacks)) { 66 LOGD("Audio PAL open returned false"); 67 mAudioApi = nullptr; 68 } else { 69 LOGD("Opened audio PAL version 0x%08" PRIx32, mAudioApi->moduleVersion); 70 } 71 } else { 72 LOGW("Requested audio PAL (version 0x%08" PRIx32 ") not found", 73 CHRE_PAL_AUDIO_API_CURRENT_VERSION); 74 } 75 } 76 77 void PlatformAudio::setHandleEnabled(uint32_t handle, bool enabled) { 78 uint32_t lastNumAudioClients = mNumAudioClients; 79 80 if (enabled) { 81 mNumAudioClients++; 82 } else if (mNumAudioClients > 0) { 83 mNumAudioClients--; 84 } else { 85 LOGE("Invalid request to change handle enabled state"); 86 } 87 88 if (lastNumAudioClients == 0 && mNumAudioClients > 0) { 89 mTargetAudioEnabled = true; 90 if (!mCurrentAudioEnabled) { 91 LOGD("Enabling audio"); 92 mCurrentAudioEnabled = true; 93 sendAudioRequest(); 94 } 95 } else if (lastNumAudioClients > 0 && mNumAudioClients == 0) { 96 mTargetAudioEnabled = false; 97 if (EventLoopManagerSingleton::get() 98 ->getEventLoop() 99 .getPowerControlManager() 100 .hostIsAwake()) { 101 onHostAwake(); 102 } else { 103 LOGD("Deferring disable audio"); 104 } 105 } 106 } 107 108 bool PlatformAudio::requestAudioDataEvent(uint32_t handle, uint32_t numSamples, 109 Nanoseconds eventDelay) { 110 bool success = false; 111 if (mAudioApi != nullptr) { 112 prePalApiCall(); 113 success = mAudioApi->requestAudioDataEvent(handle, numSamples, 114 eventDelay.toRawNanoseconds()); 115 } 116 117 return success; 118 } 119 120 void PlatformAudio::cancelAudioDataEventRequest(uint32_t handle) { 121 if (mAudioApi != nullptr) { 122 prePalApiCall(); 123 mAudioApi->cancelAudioDataEvent(handle); 124 } 125 } 126 127 void PlatformAudio::releaseAudioDataEvent(struct chreAudioDataEvent *event) { 128 if (mAudioApi != nullptr) { 129 prePalApiCall(); 130 mAudioApi->releaseAudioDataEvent(event); 131 } 132 } 133 134 size_t PlatformAudio::getSourceCount() { 135 size_t sourceCount = 0; 136 if (mAudioApi != nullptr) { 137 prePalApiCall(); 138 sourceCount = mAudioApi->getSourceCount(); 139 } 140 141 return sourceCount; 142 } 143 144 bool PlatformAudio::getAudioSource(uint32_t handle, 145 struct chreAudioSource *source) const { 146 bool success = false; 147 if (mAudioApi != nullptr) { 148 prePalApiCall(); 149 success = mAudioApi->getAudioSource(handle, source); 150 } 151 152 return success; 153 } 154 155 void PlatformAudioBase::onHostAwake() { 156 if (mCurrentAudioEnabled && !mTargetAudioEnabled) { 157 LOGD("Disabling audio"); 158 mCurrentAudioEnabled = mTargetAudioEnabled; 159 sendAudioRelease(); 160 } 161 } 162 163 } // namespace chre 164