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