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