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 }