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
handleAudioDataEvent(struct chreAudioDataEvent * event)30 void handleAudioDataEvent(struct chreAudioDataEvent *event) {
31 EventLoopManagerSingleton::get()
32 ->getAudioRequestManager()
33 .handleAudioDataEvent(event);
34 }
35
handleAudioAvailability(uint32_t handle,bool available)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
PlatformAudio()50 PlatformAudio::PlatformAudio() {}
51
~PlatformAudio()52 PlatformAudio::~PlatformAudio() {
53 if (mAudioApi != nullptr) {
54 LOGV("Platform audio closing");
55 prePalApiCall();
56 mAudioApi->close();
57 LOGV("Platform audio closed");
58 }
59 }
60
init()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
setHandleEnabled(uint32_t handle,bool enabled)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
requestAudioDataEvent(uint32_t handle,uint32_t numSamples,Nanoseconds eventDelay)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
cancelAudioDataEventRequest(uint32_t handle)120 void PlatformAudio::cancelAudioDataEventRequest(uint32_t handle) {
121 if (mAudioApi != nullptr) {
122 prePalApiCall();
123 mAudioApi->cancelAudioDataEvent(handle);
124 }
125 }
126
releaseAudioDataEvent(struct chreAudioDataEvent * event)127 void PlatformAudio::releaseAudioDataEvent(struct chreAudioDataEvent *event) {
128 if (mAudioApi != nullptr) {
129 prePalApiCall();
130 mAudioApi->releaseAudioDataEvent(event);
131 }
132 }
133
getSourceCount()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
getAudioSource(uint32_t handle,struct chreAudioSource * source) const144 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
onHostAwake()155 void PlatformAudioBase::onHostAwake() {
156 if (mCurrentAudioEnabled && !mTargetAudioEnabled) {
157 LOGD("Disabling audio");
158 mCurrentAudioEnabled = mTargetAudioEnabled;
159 sendAudioRelease();
160 }
161 }
162
163 } // namespace chre
164