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 #define LOG_TAG "audio_hw_primary"
18
19 #include <cinttypes>
20
21 #include <utils/Log.h>
22 #include <utils/Mutex.h>
23
24 #include <android/hardware/power/1.2/IPower.h>
25 #include <aidl/android/hardware/power/Boost.h>
26 #include <aidl/android/hardware/power/IPower.h>
27 #include <aidl/android/hardware/power/Mode.h>
28 #include <android/binder_manager.h>
29
30 #include "audio_perf.h"
31
32 // Protect gPowerHal_1_2_ and gPowerHal_Aidl_
33 static android::sp<android::hardware::power::V1_2::IPower> gPowerHal_1_2_;
34 static std::shared_ptr<aidl::android::hardware::power::IPower> gPowerHal_Aidl_;
35 static std::mutex gPowerHalMutex;
36 static constexpr int kDefaultBoostDurationMs = 2000;
37 static constexpr int kBoostOff = -1;
38
39 static const std::string kInstance =
40 std::string(aidl::android::hardware::power::IPower::descriptor) + "/default";
41
42 enum hal_version {
43 NONE,
44 HIDL_1_2,
45 AIDL,
46 };
47
48 // Connnect PowerHAL
connectPowerHalLocked()49 static hal_version connectPowerHalLocked() {
50 static bool gPowerHalHidlExists = true;
51 static bool gPowerHalAidlExists = true;
52
53 if (!gPowerHalHidlExists && !gPowerHalAidlExists) {
54 return NONE;
55 }
56
57 if (gPowerHalHidlExists) {
58 // (re)connect if handle is null
59 if (!gPowerHal_1_2_) {
60 gPowerHal_1_2_ =
61 android::hardware::power::V1_2::IPower::getService();
62 }
63 if (gPowerHal_1_2_) {
64 ALOGV("Successfully connected to Power Hal Hidl service.");
65 return HIDL_1_2;
66 } else {
67 // no more try on this handle
68 gPowerHalHidlExists = false;
69 }
70 }
71
72 if (gPowerHalAidlExists) {
73 // (re)connect if handle is null
74 if (!gPowerHal_Aidl_) {
75 ndk::SpAIBinder pwBinder = ndk::SpAIBinder(
76 AServiceManager_getService(kInstance.c_str()));
77 gPowerHal_Aidl_ = aidl::android::hardware::power::IPower::fromBinder(pwBinder);
78 }
79 if (gPowerHal_Aidl_) {
80 ALOGV("Successfully connected to Power Hal Aidl service.");
81 return AIDL;
82 } else {
83 // no more try on this handle
84 gPowerHalAidlExists = false;
85 }
86 }
87
88 return NONE;
89 }
90
audio_streaming_hint_start()91 bool audio_streaming_hint_start() {
92 std::lock_guard<std::mutex> lock(gPowerHalMutex);
93 switch(connectPowerHalLocked()) {
94 case NONE:
95 return false;
96 case HIDL_1_2:
97 {
98 auto ret = gPowerHal_1_2_->powerHintAsync_1_2(
99 android::hardware::power::V1_2::PowerHint::AUDIO_STREAMING,
100 1);
101 if (!ret.isOk()) {
102 ALOGE("powerHint failed, error: %s",
103 ret.description().c_str());
104 gPowerHal_1_2_ = nullptr;
105 return false;
106 }
107 return true;
108 }
109 case AIDL:
110 {
111 auto ret = gPowerHal_Aidl_->setBoost(
112 aidl::android::hardware::power::Boost::AUDIO_LAUNCH,
113 kDefaultBoostDurationMs);
114 if (!ret.isOk()) {
115 std::string err = ret.getDescription();
116 ALOGE("Failed to set power hint. Error: %s", err.c_str());
117 gPowerHal_Aidl_ = nullptr;
118 return false;
119 }
120 return true;
121 }
122 default:
123 ALOGE("Unknown HAL state");
124 return false;
125 }
126 }
127
audio_streaming_hint_end()128 bool audio_streaming_hint_end() {
129 std::lock_guard<std::mutex> lock(gPowerHalMutex);
130 switch(connectPowerHalLocked()) {
131 case NONE:
132 return false;
133 case HIDL_1_2:
134 {
135 auto ret = gPowerHal_1_2_->powerHintAsync_1_2(
136 android::hardware::power::V1_2::PowerHint::AUDIO_STREAMING,
137 0);
138 if (!ret.isOk()) {
139 ALOGE("powerHint failed, error: %s",
140 ret.description().c_str());
141 gPowerHal_1_2_ = nullptr;
142 return false;
143 }
144 return true;
145 }
146 case AIDL:
147 {
148 auto ret = gPowerHal_Aidl_->setBoost(
149 aidl::android::hardware::power::Boost::AUDIO_LAUNCH,
150 kBoostOff);
151 if (!ret.isOk()) {
152 std::string err = ret.getDescription();
153 ALOGE("Failed to set power hint. Error: %s", err.c_str());
154 gPowerHal_Aidl_ = nullptr;
155 return false;
156 }
157 return true;
158 }
159 default:
160 ALOGE("Unknown HAL state");
161 return false;
162 }
163 }
164
audio_low_latency_hint_start()165 bool audio_low_latency_hint_start() {
166 std::lock_guard<std::mutex> lock(gPowerHalMutex);
167 switch(connectPowerHalLocked()) {
168 case NONE:
169 return false;
170 case HIDL_1_2:
171 {
172 auto ret = gPowerHal_1_2_->powerHintAsync_1_2(
173 android::hardware::power::V1_2::PowerHint::AUDIO_LOW_LATENCY,
174 1);
175 if (!ret.isOk()) {
176 ALOGE("powerHint failed, error: %s",
177 ret.description().c_str());
178 gPowerHal_1_2_ = nullptr;
179 return false;
180 }
181 return true;
182 }
183 case AIDL:
184 {
185 auto ret = gPowerHal_Aidl_->setMode(
186 aidl::android::hardware::power::Mode::AUDIO_STREAMING_LOW_LATENCY,
187 true);
188 if (!ret.isOk()) {
189 std::string err = ret.getDescription();
190 ALOGE("Failed to set power hint. Error: %s", err.c_str());
191 gPowerHal_Aidl_ = nullptr;
192 return false;
193 }
194 return true;
195 }
196 default:
197 ALOGE("Unknown HAL state");
198 return false;
199 }
200 }
201
audio_low_latency_hint_end()202 bool audio_low_latency_hint_end() {
203 std::lock_guard<std::mutex> lock(gPowerHalMutex);
204 switch(connectPowerHalLocked()) {
205 case NONE:
206 return false;
207 case HIDL_1_2:
208 {
209 auto ret = gPowerHal_1_2_->powerHintAsync_1_2(
210 android::hardware::power::V1_2::PowerHint::AUDIO_LOW_LATENCY,
211 0);
212 if (!ret.isOk()) {
213 ALOGE("powerHint failed, error: %s",
214 ret.description().c_str());
215 gPowerHal_1_2_ = nullptr;
216 return false;
217 }
218 return true;
219 }
220 case AIDL:
221 {
222 auto ret = gPowerHal_Aidl_->setMode(
223 aidl::android::hardware::power::Mode::AUDIO_STREAMING_LOW_LATENCY,
224 false);
225 if (!ret.isOk()) {
226 std::string err = ret.getDescription();
227 ALOGE("Failed to set power hint. Error: %s", err.c_str());
228 gPowerHal_Aidl_ = nullptr;
229 return false;
230 }
231 return true;
232 }
233 default:
234 ALOGE("Unknown HAL state");
235 return false;
236 }
237 }
238