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