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