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