xref: /aosp_15_r20/system/chre/platform/linux/pal_audio.cc (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker  *
4*84e33947SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker  *
8*84e33947SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker  *
10*84e33947SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker  * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker  */
16*84e33947SAndroid Build Coastguard Worker 
17*84e33947SAndroid Build Coastguard Worker #include "chre/pal/audio.h"
18*84e33947SAndroid Build Coastguard Worker 
19*84e33947SAndroid Build Coastguard Worker #include "chre/platform/linux/task_util/task_manager.h"
20*84e33947SAndroid Build Coastguard Worker #include "chre/platform/memory.h"
21*84e33947SAndroid Build Coastguard Worker #include "chre/util/macros.h"
22*84e33947SAndroid Build Coastguard Worker #include "chre/util/memory.h"
23*84e33947SAndroid Build Coastguard Worker #include "chre/util/unique_ptr.h"
24*84e33947SAndroid Build Coastguard Worker 
25*84e33947SAndroid Build Coastguard Worker #include <chrono>
26*84e33947SAndroid Build Coastguard Worker #include <cinttypes>
27*84e33947SAndroid Build Coastguard Worker #include <cstdint>
28*84e33947SAndroid Build Coastguard Worker 
29*84e33947SAndroid Build Coastguard Worker /**
30*84e33947SAndroid Build Coastguard Worker  * A simulated implementation of the audio PAL for the linux platform.
31*84e33947SAndroid Build Coastguard Worker  */
32*84e33947SAndroid Build Coastguard Worker namespace {
33*84e33947SAndroid Build Coastguard Worker 
34*84e33947SAndroid Build Coastguard Worker using ::chre::TaskManagerSingleton;
35*84e33947SAndroid Build Coastguard Worker 
36*84e33947SAndroid Build Coastguard Worker const struct chrePalSystemApi *gSystemApi = nullptr;
37*84e33947SAndroid Build Coastguard Worker const struct chrePalAudioCallbacks *gCallbacks = nullptr;
38*84e33947SAndroid Build Coastguard Worker 
39*84e33947SAndroid Build Coastguard Worker constexpr uint32_t kHandle0SampleRate = 16000;
40*84e33947SAndroid Build Coastguard Worker 
41*84e33947SAndroid Build Coastguard Worker //! Whether the handle 0 is currently enabled.
42*84e33947SAndroid Build Coastguard Worker std::optional<uint32_t> gHandle0TaskId;
43*84e33947SAndroid Build Coastguard Worker bool gIsHandle0Enabled = false;
44*84e33947SAndroid Build Coastguard Worker 
stopHandle0Task()45*84e33947SAndroid Build Coastguard Worker void stopHandle0Task() {
46*84e33947SAndroid Build Coastguard Worker   if (gHandle0TaskId.has_value()) {
47*84e33947SAndroid Build Coastguard Worker     TaskManagerSingleton::get()->cancelTask(gHandle0TaskId.value());
48*84e33947SAndroid Build Coastguard Worker     gHandle0TaskId.reset();
49*84e33947SAndroid Build Coastguard Worker   }
50*84e33947SAndroid Build Coastguard Worker }
51*84e33947SAndroid Build Coastguard Worker 
chrePalAudioApiClose(void)52*84e33947SAndroid Build Coastguard Worker void chrePalAudioApiClose(void) {
53*84e33947SAndroid Build Coastguard Worker   stopHandle0Task();
54*84e33947SAndroid Build Coastguard Worker }
55*84e33947SAndroid Build Coastguard Worker 
chrePalAudioApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalAudioCallbacks * callbacks)56*84e33947SAndroid Build Coastguard Worker bool chrePalAudioApiOpen(const struct chrePalSystemApi *systemApi,
57*84e33947SAndroid Build Coastguard Worker                          const struct chrePalAudioCallbacks *callbacks) {
58*84e33947SAndroid Build Coastguard Worker   chrePalAudioApiClose();
59*84e33947SAndroid Build Coastguard Worker 
60*84e33947SAndroid Build Coastguard Worker   bool success = false;
61*84e33947SAndroid Build Coastguard Worker   if (systemApi != nullptr && callbacks != nullptr) {
62*84e33947SAndroid Build Coastguard Worker     gSystemApi = systemApi;
63*84e33947SAndroid Build Coastguard Worker     gCallbacks = callbacks;
64*84e33947SAndroid Build Coastguard Worker     callbacks->audioAvailabilityCallback(0 /*handle*/, true /*available*/);
65*84e33947SAndroid Build Coastguard Worker     success = true;
66*84e33947SAndroid Build Coastguard Worker   }
67*84e33947SAndroid Build Coastguard Worker 
68*84e33947SAndroid Build Coastguard Worker   return success;
69*84e33947SAndroid Build Coastguard Worker }
70*84e33947SAndroid Build Coastguard Worker 
sendHandle0Events(uint32_t numSamples)71*84e33947SAndroid Build Coastguard Worker void sendHandle0Events(uint32_t numSamples) {
72*84e33947SAndroid Build Coastguard Worker   auto data = chre::MakeUniqueZeroFill<struct chreAudioDataEvent>();
73*84e33947SAndroid Build Coastguard Worker 
74*84e33947SAndroid Build Coastguard Worker   data->version = CHRE_AUDIO_DATA_EVENT_VERSION;
75*84e33947SAndroid Build Coastguard Worker   data->handle = 0;
76*84e33947SAndroid Build Coastguard Worker   data->timestamp = gSystemApi->getCurrentTime();
77*84e33947SAndroid Build Coastguard Worker   data->sampleRate = kHandle0SampleRate;
78*84e33947SAndroid Build Coastguard Worker   data->sampleCount = numSamples;
79*84e33947SAndroid Build Coastguard Worker   data->format = CHRE_AUDIO_DATA_FORMAT_8_BIT_U_LAW;
80*84e33947SAndroid Build Coastguard Worker   data->samplesULaw8 =
81*84e33947SAndroid Build Coastguard Worker       static_cast<const uint8_t *>(chre::memoryAlloc(numSamples));
82*84e33947SAndroid Build Coastguard Worker 
83*84e33947SAndroid Build Coastguard Worker   gCallbacks->audioDataEventCallback(data.release());
84*84e33947SAndroid Build Coastguard Worker }
85*84e33947SAndroid Build Coastguard Worker 
chrePalAudioApiRequestAudioDataEvent(uint32_t handle,uint32_t numSamples,uint64_t eventDelayNs)86*84e33947SAndroid Build Coastguard Worker bool chrePalAudioApiRequestAudioDataEvent(uint32_t handle, uint32_t numSamples,
87*84e33947SAndroid Build Coastguard Worker                                           uint64_t eventDelayNs) {
88*84e33947SAndroid Build Coastguard Worker   if (handle != 0) {
89*84e33947SAndroid Build Coastguard Worker     return false;
90*84e33947SAndroid Build Coastguard Worker   }
91*84e33947SAndroid Build Coastguard Worker 
92*84e33947SAndroid Build Coastguard Worker   stopHandle0Task();
93*84e33947SAndroid Build Coastguard Worker   if (numSamples > 0) {
94*84e33947SAndroid Build Coastguard Worker     gIsHandle0Enabled = true;
95*84e33947SAndroid Build Coastguard Worker     gHandle0TaskId = TaskManagerSingleton::get()->addTask(
96*84e33947SAndroid Build Coastguard Worker         [numSamples]() { sendHandle0Events(numSamples); },
97*84e33947SAndroid Build Coastguard Worker         std::chrono::nanoseconds(eventDelayNs), true /*isOneShot*/);
98*84e33947SAndroid Build Coastguard Worker     if (!gHandle0TaskId.has_value()) {
99*84e33947SAndroid Build Coastguard Worker       return false;
100*84e33947SAndroid Build Coastguard Worker     }
101*84e33947SAndroid Build Coastguard Worker   }
102*84e33947SAndroid Build Coastguard Worker 
103*84e33947SAndroid Build Coastguard Worker   return true;
104*84e33947SAndroid Build Coastguard Worker }
105*84e33947SAndroid Build Coastguard Worker 
chrePalAudioApiCancelAudioDataEvent(uint32_t handle)106*84e33947SAndroid Build Coastguard Worker void chrePalAudioApiCancelAudioDataEvent(uint32_t handle) {
107*84e33947SAndroid Build Coastguard Worker   if (handle == 0) {
108*84e33947SAndroid Build Coastguard Worker     gIsHandle0Enabled = false;
109*84e33947SAndroid Build Coastguard Worker     stopHandle0Task();
110*84e33947SAndroid Build Coastguard Worker   }
111*84e33947SAndroid Build Coastguard Worker }
112*84e33947SAndroid Build Coastguard Worker 
chrePalAudioApiReleaseAudioDataEvent(struct chreAudioDataEvent * event)113*84e33947SAndroid Build Coastguard Worker void chrePalAudioApiReleaseAudioDataEvent(struct chreAudioDataEvent *event) {
114*84e33947SAndroid Build Coastguard Worker   if (event->format == CHRE_AUDIO_DATA_FORMAT_8_BIT_U_LAW) {
115*84e33947SAndroid Build Coastguard Worker     chre::memoryFree((void *)event->samplesULaw8);
116*84e33947SAndroid Build Coastguard Worker   } else if (event->format == CHRE_AUDIO_DATA_FORMAT_16_BIT_SIGNED_PCM) {
117*84e33947SAndroid Build Coastguard Worker     chre::memoryFree((void *)event->samplesS16);
118*84e33947SAndroid Build Coastguard Worker   }
119*84e33947SAndroid Build Coastguard Worker   chre::memoryFree(event);
120*84e33947SAndroid Build Coastguard Worker }
121*84e33947SAndroid Build Coastguard Worker 
chrePalAudioApiGetSourceCount(void)122*84e33947SAndroid Build Coastguard Worker uint32_t chrePalAudioApiGetSourceCount(void) {
123*84e33947SAndroid Build Coastguard Worker   return 1;
124*84e33947SAndroid Build Coastguard Worker }
125*84e33947SAndroid Build Coastguard Worker 
chrePalAudioApiGetAudioSource(uint32_t handle,struct chreAudioSource * audioSource)126*84e33947SAndroid Build Coastguard Worker bool chrePalAudioApiGetAudioSource(uint32_t handle,
127*84e33947SAndroid Build Coastguard Worker                                    struct chreAudioSource *audioSource) {
128*84e33947SAndroid Build Coastguard Worker   if (handle != 0) {
129*84e33947SAndroid Build Coastguard Worker     return false;
130*84e33947SAndroid Build Coastguard Worker   }
131*84e33947SAndroid Build Coastguard Worker 
132*84e33947SAndroid Build Coastguard Worker   *audioSource = {
133*84e33947SAndroid Build Coastguard Worker       .name = "Test Source",
134*84e33947SAndroid Build Coastguard Worker       .sampleRate = kHandle0SampleRate,
135*84e33947SAndroid Build Coastguard Worker       .minBufferDuration = 1,
136*84e33947SAndroid Build Coastguard Worker       .maxBufferDuration = 1000000000,
137*84e33947SAndroid Build Coastguard Worker       .format = CHRE_AUDIO_DATA_FORMAT_8_BIT_U_LAW,
138*84e33947SAndroid Build Coastguard Worker   };
139*84e33947SAndroid Build Coastguard Worker 
140*84e33947SAndroid Build Coastguard Worker   return true;
141*84e33947SAndroid Build Coastguard Worker }
142*84e33947SAndroid Build Coastguard Worker 
143*84e33947SAndroid Build Coastguard Worker }  // namespace
144*84e33947SAndroid Build Coastguard Worker 
chrePalAudioIsHandle0Enabled()145*84e33947SAndroid Build Coastguard Worker bool chrePalAudioIsHandle0Enabled() {
146*84e33947SAndroid Build Coastguard Worker   return gIsHandle0Enabled;
147*84e33947SAndroid Build Coastguard Worker }
148*84e33947SAndroid Build Coastguard Worker 
chrePalAudioGetApi(uint32_t requestedApiVersion)149*84e33947SAndroid Build Coastguard Worker const chrePalAudioApi *chrePalAudioGetApi(uint32_t requestedApiVersion) {
150*84e33947SAndroid Build Coastguard Worker   static const struct chrePalAudioApi kApi = {
151*84e33947SAndroid Build Coastguard Worker       .moduleVersion = CHRE_PAL_AUDIO_API_CURRENT_VERSION,
152*84e33947SAndroid Build Coastguard Worker       .open = chrePalAudioApiOpen,
153*84e33947SAndroid Build Coastguard Worker       .close = chrePalAudioApiClose,
154*84e33947SAndroid Build Coastguard Worker       .requestAudioDataEvent = chrePalAudioApiRequestAudioDataEvent,
155*84e33947SAndroid Build Coastguard Worker       .cancelAudioDataEvent = chrePalAudioApiCancelAudioDataEvent,
156*84e33947SAndroid Build Coastguard Worker       .releaseAudioDataEvent = chrePalAudioApiReleaseAudioDataEvent,
157*84e33947SAndroid Build Coastguard Worker       .getSourceCount = chrePalAudioApiGetSourceCount,
158*84e33947SAndroid Build Coastguard Worker       .getAudioSource = chrePalAudioApiGetAudioSource,
159*84e33947SAndroid Build Coastguard Worker   };
160*84e33947SAndroid Build Coastguard Worker 
161*84e33947SAndroid Build Coastguard Worker   if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
162*84e33947SAndroid Build Coastguard Worker                                         requestedApiVersion)) {
163*84e33947SAndroid Build Coastguard Worker     return nullptr;
164*84e33947SAndroid Build Coastguard Worker   } else {
165*84e33947SAndroid Build Coastguard Worker     return &kApi;
166*84e33947SAndroid Build Coastguard Worker   }
167*84e33947SAndroid Build Coastguard Worker }