• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/slpi/power_control_util.h"
25 #include "chre/util/memory.h"
26 #include "wcd_spi.h"
27 
28 static_assert(
29     sizeof(wcd_spi_audio_source_s) == sizeof(struct chreAudioSource),
30     "WCD SPI/CHRE audio sources must be equal in size");
31 static_assert(
32     offsetof(wcd_spi_audio_source_s, name)
33         == offsetof(struct chreAudioSource, name),
34     "WCD SPI/CHRE audio source name must have the same offset");
35 static_assert(
36     offsetof(wcd_spi_audio_source_s, sample_rate_hz)
37         == offsetof(struct chreAudioSource, sampleRate),
38     "WCD SPI/CHRE audio source sample rate must have the same offset");
39 static_assert(
40     offsetof(wcd_spi_audio_source_s, min_buffer_duration_ns)
41         == offsetof(struct chreAudioSource, minBufferDuration),
42     "WCD SPI/CHRE audio source min buffer duration must have the same offset");
43 static_assert(
44     offsetof(wcd_spi_audio_source_s, max_buffer_duration_ns)
45         == offsetof(struct chreAudioSource, maxBufferDuration),
46     "WCD SPI/CHRE audio source max buffer duration must have the same offset");
47 static_assert(
48     offsetof(wcd_spi_audio_source_s, format)
49         == offsetof(struct chreAudioSource, format),
50     "WCD SPI/CHRE audio source format must have the same offset");
51 
52 namespace chre {
53 namespace {
54 
handleWcdSpiAudioDataEvent(const wcd_spi_audio_data_event_s * event)55 void handleWcdSpiAudioDataEvent(const wcd_spi_audio_data_event_s *event) {
56   LOGD("WCD SPI audio data callback");
57 
58   auto *dataEvent = memoryAlloc<struct chreAudioDataEvent>();
59   if (dataEvent == nullptr) {
60     LOGE("Failed to allocate data event");
61   } else {
62     dataEvent->handle = event->handle;
63     dataEvent->timestamp = event->timestamp_ns;
64     dataEvent->sampleRate = event->sample_rate_hz;
65     dataEvent->sampleCount = event->sample_count;
66     dataEvent->format = event->format;
67 
68     // The sample pointers are a union, so the value will be correct regardless
69     // of the sample format. This is just a shallow copy of the data pointer,
70     // not the contents of the buffer itself.
71     dataEvent->samplesULaw8 = event->samples_ulaw8;
72 
73     EventLoopManagerSingleton::get()->getAudioRequestManager()
74         .handleAudioDataEvent(dataEvent);
75   }
76 }
77 
handleWcdSpiAudioAvailability(uint32_t handle,bool available)78 void handleWcdSpiAudioAvailability(uint32_t handle, bool available) {
79   LOGD("WCD SPI audio handle %" PRIu32 " available: %d", handle, available);
80   EventLoopManagerSingleton::get()->getAudioRequestManager()
81       .handleAudioAvailability(handle, available);
82 }
83 
84 }  // anonymous namespace
85 
PlatformAudio()86 PlatformAudio::PlatformAudio() {}
87 
~PlatformAudio()88 PlatformAudio::~PlatformAudio() {
89   wcd_spi_client_deinit();
90 }
91 
init()92 void PlatformAudio::init() {
93   wcd_spi_client_init(handleWcdSpiAudioDataEvent,
94                       handleWcdSpiAudioAvailability);
95 }
96 
setHandleEnabled(uint32_t handle,bool enabled)97 void PlatformAudio::setHandleEnabled(uint32_t handle, bool enabled) {
98   uint32_t lastNumAudioClients = mNumAudioClients;
99 
100   if (enabled) {
101     mNumAudioClients++;
102   } else if (mNumAudioClients > 0) {
103     mNumAudioClients--;
104   } else {
105     LOGE("Invalid request to change handle enabled state");
106   }
107 
108   if (lastNumAudioClients == 0 && mNumAudioClients > 0) {
109     LOGD("Enabling WCD SLPI");
110     sendAudioRequest();
111   } else if (lastNumAudioClients > 0 && mNumAudioClients == 0) {
112     LOGD("Disabling WCD SLPI");
113     sendAudioRelease();
114   }
115 }
116 
requestAudioDataEvent(uint32_t handle,uint32_t numSamples,Nanoseconds eventDelay)117 bool PlatformAudio::requestAudioDataEvent(uint32_t handle,
118                                           uint32_t numSamples,
119                                           Nanoseconds eventDelay) {
120   slpiForceBigImage();
121   return wcd_spi_client_request_audio_data_event(handle, numSamples,
122                                                  eventDelay.toRawNanoseconds());
123 }
124 
cancelAudioDataEventRequest(uint32_t handle)125 void PlatformAudio::cancelAudioDataEventRequest(uint32_t handle) {
126   slpiForceBigImage();
127   wcd_spi_client_cancel_audio_data_event(handle);
128 }
129 
releaseAudioDataEvent(struct chreAudioDataEvent * event)130 void PlatformAudio::releaseAudioDataEvent(struct chreAudioDataEvent *event) {
131   wcd_spi_client_release_audio_data_event(event->handle);
132   memoryFree(event);
133 }
134 
getSourceCount()135 size_t PlatformAudio::getSourceCount() {
136   slpiForceBigImage();
137   return wcd_spi_client_get_source_count();
138 }
139 
getAudioSource(uint32_t handle,chreAudioSource * source)140 bool PlatformAudio::getAudioSource(uint32_t handle,
141                                    chreAudioSource *source) {
142   slpiForceBigImage();
143   wcd_spi_audio_source_s wcd_spi_audio_source;
144   bool result = wcd_spi_client_get_source(handle, &wcd_spi_audio_source);
145   if (result) {
146     // The WCD SPI and CHRE source definitions are binary compatible so a simple
147     // memcpy will suffice.
148     memcpy(source, &wcd_spi_audio_source, sizeof(*source));
149   }
150 
151   return result;
152 }
153 
154 }  // namespace chre
155