• 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 = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
62     ndk::SpAIBinder ext_power_binder;
63 
64     if (power_binder.get() == nullptr) {
65         LOG(ERROR) << "Cannot get Power Hal Binder";
66         power_hal_aidl_exist_ = false;
67         return false;
68     }
69 
70     power_hal_aidl_ = IPower::fromBinder(power_binder);
71 
72     if (power_hal_aidl_ == nullptr) {
73         power_hal_aidl_exist_ = false;
74         LOG(ERROR) << "Cannot get Power Hal AIDL" << kInstance.c_str();
75         return false;
76     }
77 
78     if (STATUS_OK != AIBinder_getExtension(power_binder.get(), ext_power_binder.getR()) ||
79         ext_power_binder.get() == nullptr) {
80         LOG(ERROR) << "Cannot get Power Hal Extension Binder";
81         power_hal_aidl_exist_ = false;
82         return false;
83     }
84 
85     power_hal_ext_aidl_ = IPowerExt::fromBinder(ext_power_binder);
86     if (power_hal_ext_aidl_ == nullptr) {
87         LOG(ERROR) << "Cannot get Power Hal Extension AIDL";
88         power_hal_aidl_exist_ = false;
89     }
90 
91     if (power_hal_ext_aidl_death_recipient_.get() == nullptr) {
92         power_hal_ext_aidl_death_recipient_ = ndk::ScopedAIBinder_DeathRecipient(
93                 AIBinder_DeathRecipient_new(onPowerHalExtAidlBinderDied));
94     }
95 
96     auto linked = AIBinder_linkToDeath(power_hal_ext_aidl_->asBinder().get(),
97                                        power_hal_ext_aidl_death_recipient_.get(), this);
98 
99     if (linked != STATUS_OK) {
100         LOG(ERROR) << "Failed to register power_hal_ext death recipient";
101     }
102 
103     return true;
104 }
105 
reconnect()106 void PowerHalService::reconnect() {
107     ATRACE_CALL();
108     if (!connect()) {
109         LOG(ERROR) << " Failed to reconnect power_hal_ext";
110         return;
111     }
112 
113     LOG(INFO) << "Resend the power hints when power_hal_ext is reconnected";
114     std::lock_guard<std::shared_mutex> _lock(powerhint_status_mutex_);
115     for (const auto &[sensor_name, supported_powerhint] : supported_powerhint_map_) {
116         std::stringstream log_buf;
117         for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
118             bool mode = severity <= supported_powerhint.prev_hint_severity;
119             setMode(sensor_name, severity, mode);
120             log_buf << toString(severity).c_str() << ":" << mode << " ";
121         }
122 
123         LOG(INFO) << sensor_name << " send powerhint: " << log_buf.str();
124         log_buf.clear();
125     }
126     return;
127 }
128 
updateSupportedPowerHints(const std::unordered_map<std::string,SensorInfo> & sensor_info_map_)129 void PowerHalService::updateSupportedPowerHints(
130         const std::unordered_map<std::string, SensorInfo> &sensor_info_map_) {
131     for (auto const &name_status_pair : sensor_info_map_) {
132         if (!(name_status_pair.second.send_powerhint)) {
133             continue;
134         }
135         ThrottlingSeverity current_severity = ThrottlingSeverity::NONE;
136         for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
137             if (severity == ThrottlingSeverity::NONE) {
138                 supported_powerhint_map_[name_status_pair.first]
139                         .hint_severity_map[ThrottlingSeverity::NONE] = ThrottlingSeverity::NONE;
140                 continue;
141             }
142 
143             bool isSupported = false;
144             ndk::ScopedAStatus isSupportedResult;
145 
146             if (power_hal_ext_aidl_ != nullptr) {
147                 isSupported = isModeSupported(name_status_pair.first, severity);
148             }
149             if (isSupported)
150                 current_severity = severity;
151             supported_powerhint_map_[name_status_pair.first].hint_severity_map[severity] =
152                     current_severity;
153         }
154     }
155 }
156 
sendPowerExtHint(const Temperature & t)157 void PowerHalService::sendPowerExtHint(const Temperature &t) {
158     ATRACE_CALL();
159     std::lock_guard<std::shared_mutex> _lock(powerhint_status_mutex_);
160     ThrottlingSeverity prev_hint_severity = supported_powerhint_map_[t.name].prev_hint_severity;
161     ThrottlingSeverity current_hint_severity =
162             supported_powerhint_map_[t.name].hint_severity_map[t.throttlingStatus];
163     std::stringstream log_buf;
164 
165     if (!power_hal_aidl_exist_) {
166         LOG(ERROR) << "power_hal_aidl is not exist";
167         return;
168     }
169 
170     if (prev_hint_severity == current_hint_severity) {
171         return;
172     }
173 
174     for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
175         if (severity != supported_powerhint_map_[t.name].hint_severity_map[severity]) {
176             continue;
177         }
178         bool mode = severity <= current_hint_severity;
179         setMode(t.name, severity, mode);
180         log_buf << toString(severity).c_str() << ":" << mode << " ";
181     }
182 
183     LOG(INFO) << t.name << " send powerhint: " << log_buf.str();
184 
185     supported_powerhint_map_[t.name].prev_hint_severity = current_hint_severity;
186 }
187 
isModeSupported(const std::string & type,const ThrottlingSeverity & t)188 bool PowerHalService::isModeSupported(const std::string &type, const ThrottlingSeverity &t) {
189     bool isSupported = false;
190     if (!connect()) {
191         return false;
192     }
193     std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
194     lock_.lock();
195     if (!power_hal_ext_aidl_->isModeSupported(power_hint, &isSupported).isOk()) {
196         LOG(ERROR) << "Fail to check supported mode, Hint: " << power_hint;
197         power_hal_ext_aidl_ = nullptr;
198         power_hal_aidl_ = nullptr;
199         lock_.unlock();
200         return false;
201     }
202     lock_.unlock();
203     return isSupported;
204 }
205 
setMode(const std::string & type,const ThrottlingSeverity & t,const bool & enable,const bool error_on_exit)206 void PowerHalService::setMode(const std::string &type, const ThrottlingSeverity &t,
207                               const bool &enable, const bool error_on_exit) {
208     if (!connect()) {
209         return;
210     }
211 
212     std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
213     lock_.lock();
214     if (!power_hal_ext_aidl_->setMode(power_hint, enable).isOk()) {
215         LOG(ERROR) << "Fail to set mode, Hint: " << power_hint;
216         power_hal_ext_aidl_ = nullptr;
217         power_hal_aidl_ = nullptr;
218         lock_.unlock();
219         if (!error_on_exit) {
220             setMode(type, t, enable, true);
221         }
222         return;
223     }
224     lock_.unlock();
225 }
226 
227 }  // namespace implementation
228 }  // namespace thermal
229 }  // namespace hardware
230 }  // namespace android
231 }  // namespace aidl
232