• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 ATRACE_TAG (ATRACE_TAG_THERMAL | ATRACE_TAG_HAL)
18 
19 #include "powerhal_helper.h"
20 
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/properties.h>
24 #include <android-base/stringprintf.h>
25 #include <android-base/strings.h>
26 #include <android/binder_manager.h>
27 
28 #include <iterator>
29 #include <set>
30 #include <sstream>
31 #include <thread>
32 #include <vector>
33 
34 #include "thermal_throttling.h"
35 
36 namespace aidl {
37 namespace android {
38 namespace hardware {
39 namespace thermal {
40 namespace implementation {
41 
42 using ::android::base::StringPrintf;
43 
PowerHalService()44 PowerHalService::PowerHalService()
45     : power_hal_aidl_exist_(true), power_hal_aidl_(nullptr), power_hal_ext_aidl_(nullptr) {
46     connect();
47 }
48 
connect()49 bool PowerHalService::connect() {
50     std::lock_guard<std::mutex> lock(lock_);
51 
52     if (!power_hal_aidl_exist_) {
53         return false;
54     }
55 
56     if (power_hal_aidl_ && power_hal_ext_aidl_) {
57         return true;
58     }
59 
60     const std::string kInstance = std::string(IPower::descriptor) + "/default";
61     ndk::SpAIBinder power_binder =
62             ndk::SpAIBinder(AServiceManager_waitForService(kInstance.c_str()));
63     ndk::SpAIBinder ext_power_binder;
64 
65     if (power_binder.get() == nullptr) {
66         LOG(ERROR) << "Cannot get Power Hal Binder";
67         power_hal_aidl_exist_ = false;
68         return false;
69     }
70 
71     power_hal_aidl_ = IPower::fromBinder(power_binder);
72 
73     if (power_hal_aidl_ == nullptr) {
74         power_hal_aidl_exist_ = false;
75         LOG(ERROR) << "Cannot get Power Hal AIDL" << kInstance.c_str();
76         return false;
77     }
78 
79     if (STATUS_OK != AIBinder_getExtension(power_binder.get(), ext_power_binder.getR()) ||
80         ext_power_binder.get() == nullptr) {
81         LOG(ERROR) << "Cannot get Power Hal Extension Binder";
82         power_hal_aidl_exist_ = false;
83         return false;
84     }
85 
86     power_hal_ext_aidl_ = IPowerExt::fromBinder(ext_power_binder);
87     if (power_hal_ext_aidl_ == nullptr) {
88         LOG(ERROR) << "Cannot get Power Hal Extension AIDL";
89         power_hal_aidl_exist_ = false;
90     }
91 
92     if (power_hal_ext_aidl_death_recipient_.get() == nullptr) {
93         power_hal_ext_aidl_death_recipient_ = ndk::ScopedAIBinder_DeathRecipient(
94                 AIBinder_DeathRecipient_new(onPowerHalExtAidlBinderDied));
95     }
96 
97     auto linked = AIBinder_linkToDeath(power_hal_ext_aidl_->asBinder().get(),
98                                        power_hal_ext_aidl_death_recipient_.get(), this);
99 
100     if (linked != STATUS_OK) {
101         LOG(ERROR) << "Failed to register power_hal_ext death recipient";
102     }
103 
104     return true;
105 }
106 
reconnect()107 void PowerHalService::reconnect() {
108     ATRACE_CALL();
109     if (!connect()) {
110         LOG(ERROR) << " Failed to reconnect power_hal_ext";
111         return;
112     }
113 
114     LOG(INFO) << "Resend the power hints when power_hal_ext is reconnected";
115     std::lock_guard<std::shared_mutex> _lock(powerhint_status_mutex_);
116     for (const auto &[sensor_name, supported_powerhint] : supported_powerhint_map_) {
117         std::stringstream log_buf;
118         for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
119             bool mode = severity <= supported_powerhint.prev_hint_severity;
120             setMode(sensor_name, severity, mode);
121             log_buf << toString(severity).c_str() << ":" << mode << " ";
122         }
123 
124         LOG(INFO) << sensor_name << " send powerhint: " << log_buf.str();
125         log_buf.clear();
126     }
127     return;
128 }
129 
updateSupportedPowerHints(const std::unordered_map<std::string,SensorInfo> & sensor_info_map_)130 void PowerHalService::updateSupportedPowerHints(
131         const std::unordered_map<std::string, SensorInfo> &sensor_info_map_) {
132     for (auto const &name_status_pair : sensor_info_map_) {
133         if (!(name_status_pair.second.send_powerhint)) {
134             continue;
135         }
136         ThrottlingSeverity current_severity = ThrottlingSeverity::NONE;
137         for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
138             if (severity == ThrottlingSeverity::NONE) {
139                 supported_powerhint_map_[name_status_pair.first]
140                         .hint_severity_map[ThrottlingSeverity::NONE] = ThrottlingSeverity::NONE;
141                 continue;
142             }
143 
144             bool isSupported = false;
145             ndk::ScopedAStatus isSupportedResult;
146 
147             if (power_hal_ext_aidl_ != nullptr) {
148                 isSupported = isModeSupported(name_status_pair.first, severity);
149             }
150             if (isSupported)
151                 current_severity = severity;
152             supported_powerhint_map_[name_status_pair.first].hint_severity_map[severity] =
153                     current_severity;
154         }
155     }
156 }
157 
sendPowerExtHint(const Temperature & t)158 void PowerHalService::sendPowerExtHint(const Temperature &t) {
159     ATRACE_CALL();
160     std::lock_guard<std::shared_mutex> _lock(powerhint_status_mutex_);
161     ThrottlingSeverity prev_hint_severity = supported_powerhint_map_[t.name].prev_hint_severity;
162     ThrottlingSeverity current_hint_severity =
163             supported_powerhint_map_[t.name].hint_severity_map[t.throttlingStatus];
164     std::stringstream log_buf;
165 
166     if (!power_hal_aidl_exist_) {
167         LOG(ERROR) << "power_hal_aidl is not exist";
168         return;
169     }
170 
171     if (prev_hint_severity == current_hint_severity) {
172         return;
173     }
174 
175     for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
176         if (severity != supported_powerhint_map_[t.name].hint_severity_map[severity]) {
177             continue;
178         }
179         bool mode = severity <= current_hint_severity;
180         setMode(t.name, severity, mode);
181         log_buf << toString(severity).c_str() << ":" << mode << " ";
182     }
183 
184     LOG(INFO) << t.name << " send powerhint: " << log_buf.str();
185 
186     supported_powerhint_map_[t.name].prev_hint_severity = current_hint_severity;
187 }
188 
isModeSupported(const std::string & type,const ThrottlingSeverity & t)189 bool PowerHalService::isModeSupported(const std::string &type, const ThrottlingSeverity &t) {
190     bool isSupported = false;
191     if (!connect()) {
192         return false;
193     }
194     std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
195     lock_.lock();
196     if (!power_hal_ext_aidl_->isModeSupported(power_hint, &isSupported).isOk()) {
197         LOG(ERROR) << "Fail to check supported mode, Hint: " << power_hint;
198         power_hal_ext_aidl_ = nullptr;
199         power_hal_aidl_ = nullptr;
200         lock_.unlock();
201         return false;
202     }
203     lock_.unlock();
204     return isSupported;
205 }
206 
setMode(const std::string & type,const ThrottlingSeverity & t,const bool & enable,const bool error_on_exit)207 void PowerHalService::setMode(const std::string &type, const ThrottlingSeverity &t,
208                               const bool &enable, const bool error_on_exit) {
209     if (!connect()) {
210         return;
211     }
212 
213     std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
214     lock_.lock();
215     if (!power_hal_ext_aidl_->setMode(power_hint, enable).isOk()) {
216         LOG(ERROR) << "Fail to set mode, Hint: " << power_hint;
217         power_hal_ext_aidl_ = nullptr;
218         power_hal_aidl_ = nullptr;
219         lock_.unlock();
220         if (!error_on_exit) {
221             setMode(type, t, enable, true);
222         }
223         return;
224     }
225     lock_.unlock();
226 }
227 
228 }  // namespace implementation
229 }  // namespace thermal
230 }  // namespace hardware
231 }  // namespace android
232 }  // namespace aidl
233