blob: 4911faafa57d1500a87bd687abac431e565be407 [file] [log] [blame]
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -07001/*
2 * Copyright (C) 2021 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 "libPixelUsbOverheat"
18
19#include "include/pixelusb/UsbOverheatEvent.h"
20
Xiang Wang192ce4e2023-02-08 14:30:38 -080021#include <aidl/android/hardware/thermal/IThermal.h>
22#include <android/binder_manager.h>
Xiang Wangf03a78b2023-02-15 15:26:17 -080023#include <thermalutils/ThermalHidlWrapper.h>
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -070024#include <time.h>
25
26namespace android {
27namespace hardware {
28namespace google {
29namespace pixel {
30namespace usb {
31
32// Start monitoring the temperature
33static volatile bool monitorTemperature;
34
35constexpr int kEpollEvents = 10;
36constexpr char kOverheatLock[] = "overheat";
37constexpr char kWakeLockPath[] = "/sys/power/wake_lock";
38constexpr char kWakeUnlockPath[] = "/sys/power/wake_unlock";
39
40int addEpollFdWakeUp(const unique_fd &epfd, const unique_fd &fd) {
Xiang Wang192ce4e2023-02-08 14:30:38 -080041 struct epoll_event event {};
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -070042 int ret;
43
44 event.data.fd = fd;
45 event.events = EPOLLIN | EPOLLWAKEUP;
46
47 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
48 if (ret)
49 ALOGE("epoll_ctl error %d", errno);
50
51 return ret;
52}
53
54UsbOverheatEvent::UsbOverheatEvent(const ZoneInfo &monitored_zone,
55 const std::vector<ZoneInfo> &queried_zones,
56 const int &monitor_interval_sec)
57 : monitored_zone_(monitored_zone),
58 queried_zones_(queried_zones),
59 monitor_interval_sec_(monitor_interval_sec),
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -070060 monitor_() {
61 int fd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
62 if (fd < 0) {
63 ALOGE("timerfd_create failed: %d", errno);
64 }
65
66 unique_fd timerFd(timerfd_create(CLOCK_BOOTTIME_ALARM, 0));
67 if (timerFd == -1) {
68 ALOGE("timerFd failed to create %d", errno);
69 abort();
70 }
71
72 unique_fd epollFd(epoll_create(2));
73 if (epollFd == -1) {
74 ALOGE("epoll_fd_ failed to create %d", errno);
75 abort();
76 }
77
78 unique_fd eventFd(eventfd(0, 0));
79 if (eventFd == -1) {
80 ALOGE("event_fd_ failed to create %d", errno);
81 abort();
82 }
83
84 if (addEpollFdWakeUp(epollFd, timerFd) == -1) {
85 ALOGE("Adding timerFd failed");
86 abort();
87 }
88
89 if (addEpollFdWakeUp(epollFd, eventFd) == -1) {
90 ALOGE("Adding eventFd failed");
91 abort();
92 }
93
Yi Kongdfbde372022-06-23 02:15:49 +080094 epoll_fd_ = std::move(epollFd);
95 timer_fd_ = std::move(timerFd);
96 event_fd_ = std::move(eventFd);
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -070097
98 monitor_ = unique_ptr<thread>(new thread(this->monitorThread, this));
99 registerListener();
100}
101
Xiang Wang192ce4e2023-02-08 14:30:38 -0800102UsbOverheatEvent::~UsbOverheatEvent() {
103 unregisterThermalCallback();
104}
105
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700106static int wakelock_cnt = 0;
107static std::mutex wakelock_lock;
108
109static void wakeLockAcquire() {
110 lock_guard<mutex> lock(wakelock_lock);
111
112 wakelock_cnt++;
113 if (wakelock_cnt == 1) {
114 ALOGV("Acquire wakelock");
115 if (!WriteStringToFile(kOverheatLock, kWakeLockPath)) {
116 ALOGE("Failed to acquire wake lock string");
117 }
118 }
119}
120
121static void wakeLockRelease() {
122 lock_guard<mutex> lock(wakelock_lock);
123
124 wakelock_cnt--;
125 if (wakelock_cnt == 0) {
126 ALOGV("Release wakelock");
127 if (!WriteStringToFile(kOverheatLock, kWakeUnlockPath)) {
128 ALOGE("Failed to acquire wake lock string");
129 }
130 }
131}
132
133void *UsbOverheatEvent::monitorThread(void *param) {
Xiang Wang192ce4e2023-02-08 14:30:38 -0800134 auto *overheatEvent = reinterpret_cast<UsbOverheatEvent *>(param);
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700135 struct epoll_event events[kEpollEvents];
136 struct itimerspec delay = itimerspec();
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700137
138 while (true) {
139 uint64_t fired;
140 float temperature = 0;
141 string status;
142
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700143 for (vector<ZoneInfo>::size_type i = 0; i < overheatEvent->queried_zones_.size(); i++) {
144 if (overheatEvent->getCurrentTemperature(overheatEvent->queried_zones_[i].name_,
145 &temperature)) {
146 if (i == 0)
147 overheatEvent->max_overheat_temp_ =
148 max(temperature, overheatEvent->max_overheat_temp_);
149 status.append(overheatEvent->queried_zones_[i].name_);
150 status.append(":");
151 status.append(std::to_string(temperature));
152 status.append(" ");
153 }
154 }
155 ALOGW("%s", status.c_str());
156
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700157 delay.it_value.tv_sec = monitorTemperature ? overheatEvent->monitor_interval_sec_ : 0;
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700158 int ret = timerfd_settime(overheatEvent->timer_fd_, 0, &delay, NULL);
159 if (ret < 0) {
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700160 ALOGE("timerfd_settime failed. err:%d tv_sec:%ld", errno, delay.it_value.tv_sec);
161 continue;
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700162 }
163
164 wakeLockRelease();
165 int nrEvents = epoll_wait(overheatEvent->epoll_fd_, events, kEpollEvents, -1);
166 wakeLockAcquire();
167 if (nrEvents <= 0) {
168 ALOGE("nrEvents negative skipping");
169 continue;
170 }
171
172 for (int i = 0; i < nrEvents; i++) {
173 ALOGV("event=%u on fd=%d\n", events[i].events, events[i].data.fd);
174
175 if (events[i].data.fd == overheatEvent->timer_fd_) {
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700176 ALOGI("Wake up caused by timer fd");
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700177 int numRead = read(overheatEvent->timer_fd_, &fired, sizeof(fired));
178 if (numRead != sizeof(fired)) {
179 ALOGV("numRead incorrect");
180 }
181 if (fired != 1) {
182 ALOGV("Fired not set to 1");
183 }
184 } else {
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700185 ALOGI("Wake up caused by event fd");
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700186 read(overheatEvent->event_fd_, &fired, sizeof(fired));
187 }
188 }
189 }
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700190}
191
192bool UsbOverheatEvent::registerListener() {
193 ALOGV("UsbOverheatEvent::registerListener");
Xiang Wang192ce4e2023-02-08 14:30:38 -0800194 const std::lock_guard<std::mutex> lock(thermal_hal_mutex_);
195 if (connectAidlThermalService()) {
196 return true;
197 }
198
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700199 sp<IServiceManager> sm = IServiceManager::getService();
200 if (sm == NULL) {
201 ALOGE("Hardware service manager is not running");
202 return false;
203 }
204 Return<bool> result = sm->registerForNotifications(IThermal::descriptor, "", this);
205 if (result.isOk()) {
Xiang Wang192ce4e2023-02-08 14:30:38 -0800206 ALOGI("Thermal HIDL service connected!");
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700207 return true;
208 }
209 ALOGE("Failed to register for hardware service manager notifications: %s",
210 result.description().c_str());
211 return false;
212}
213
Xiang Wang192ce4e2023-02-08 14:30:38 -0800214bool UsbOverheatEvent::connectAidlThermalService() {
215 const std::string thermal_instance_name =
216 std::string(::aidl::android::hardware::thermal::IThermal::descriptor) + "/default";
217 if (AServiceManager_isDeclared(thermal_instance_name.c_str())) {
218 auto thermal_aidl_service = ::aidl::android::hardware::thermal::IThermal::fromBinder(
219 ndk::SpAIBinder(AServiceManager_waitForService(thermal_instance_name.c_str())));
220 if (thermal_aidl_service) {
221 thermal_service_ = sp<::aidl::android::hardware::thermal::ThermalHidlWrapper>::make(
222 thermal_aidl_service);
223 if (thermal_aidl_death_recipient_.get() == nullptr) {
224 thermal_aidl_death_recipient_ = ndk::ScopedAIBinder_DeathRecipient(
225 AIBinder_DeathRecipient_new(onThermalAidlBinderDied));
226 }
227 auto linked = AIBinder_linkToDeath(thermal_aidl_service->asBinder().get(),
228 thermal_aidl_death_recipient_.get(), this);
229 if (linked != STATUS_OK) {
230 ALOGE("Failed to register AIDL thermal death recipient");
231 }
232 is_thermal_callback_registered_ = registerThermalCallback("AIDL");
233 return is_thermal_callback_registered_;
234 } else {
235 ALOGE("Unable to get Thermal AIDL service");
236 }
237 } else {
238 ALOGW("Thermal AIDL service is not declared");
239 }
240 return false;
241}
242
243void UsbOverheatEvent::unregisterThermalCallback() {
244 const std::lock_guard<std::mutex> lock(thermal_hal_mutex_);
245 if (is_thermal_callback_registered_) {
246 ThermalStatus returnStatus;
247 auto ret = thermal_service_->unregisterThermalChangedCallback(
248 this, [&returnStatus](ThermalStatus status) { returnStatus = status; });
249 if (!ret.isOk() || returnStatus.code != ThermalStatusCode::SUCCESS) {
250 ALOGE("Failed to unregister thermal callback");
251 }
252 }
253}
254
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700255void UsbOverheatEvent::wakeupMonitor() {
256 // <flag> value does not have any significance here
257 uint64_t flag = 100;
Badhri Jagan Sridharanf6b07c82021-08-16 18:24:38 -0700258
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700259 unsigned long ret = TEMP_FAILURE_RETRY(write(event_fd_, &flag, sizeof(flag)));
260 if (ret < 0) {
261 ALOGE("Error writing eventfd errno=%d", errno);
262 }
263}
264
265bool UsbOverheatEvent::startRecording() {
266 ALOGI("Start recording. monitorTemperature:%d", monitorTemperature ? 1 : 0);
Badhri Jagan Sridharanf6b07c82021-08-16 18:24:38 -0700267 // Bail out if temperature was being monitored previously
268 if (monitorTemperature)
269 return true;
270
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700271 wakeLockAcquire();
272 monitorTemperature = true;
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700273 wakeupMonitor();
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700274 return true;
275}
276
277bool UsbOverheatEvent::stopRecording() {
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700278 ALOGI("Stop recording. monitorTemperature:%d", monitorTemperature ? 1 : 0);
Badhri Jagan Sridharanf6b07c82021-08-16 18:24:38 -0700279 // Bail out if temperature was not being monitored previously
280 if (!monitorTemperature)
281 return true;
282
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700283 wakeLockRelease();
284 monitorTemperature = false;
Badhri Jagan Sridharanfda25972021-08-23 14:24:42 -0700285 wakeupMonitor();
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700286
287 return true;
288}
289
290bool UsbOverheatEvent::getCurrentTemperature(const string &name, float *temp) {
291 ThermalStatus thermal_status;
292 hidl_vec<Temperature> thermal_temperatures;
Xiang Wang192ce4e2023-02-08 14:30:38 -0800293 const std::lock_guard<std::mutex> lock(thermal_hal_mutex_);
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700294 if (thermal_service_ == NULL)
295 return false;
296
297 auto ret = thermal_service_->getCurrentTemperatures(
298 false, TemperatureType::USB_PORT,
299 [&](ThermalStatus status, hidl_vec<Temperature> temperatures) {
300 thermal_status = status;
301 thermal_temperatures = temperatures;
302 });
303
304 if (ret.isOk() && thermal_status.code == ThermalStatusCode::SUCCESS) {
305 for (auto temperature : thermal_temperatures) {
306 if (temperature.name == name) {
307 *temp = temperature.value;
308 return true;
309 }
310 }
311 }
312 return false;
313}
314
315float UsbOverheatEvent::getMaxOverheatTemperature() {
316 return max_overheat_temp_;
317}
318
319Return<void> UsbOverheatEvent::onRegistration(const hidl_string & /*fully_qualified_name*/,
320 const hidl_string & /*instance_name*/,
321 bool /*pre_existing*/) {
322 ThermalStatus thermal_status;
Xiang Wang192ce4e2023-02-08 14:30:38 -0800323 const std::lock_guard<std::mutex> lock(thermal_hal_mutex_);
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700324 thermal_service_ = IThermal::getService();
325 if (thermal_service_ == NULL) {
Xiang Wang192ce4e2023-02-08 14:30:38 -0800326 ALOGE("Unable to get Themal HIDL Service");
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700327 return Void();
328 }
Xiang Wang192ce4e2023-02-08 14:30:38 -0800329 is_thermal_callback_registered_ = registerThermalCallback("HIDL");
330 return Void();
331}
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700332
Xiang Wang192ce4e2023-02-08 14:30:38 -0800333bool UsbOverheatEvent::registerThermalCallback(const string &service_str) {
334 ThermalStatus thermal_status;
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700335 auto ret = thermal_service_->registerThermalChangedCallback(
336 this, true, monitored_zone_.type_,
337 [&](ThermalStatus status) { thermal_status = status; });
338
339 if (!ret.isOk() || thermal_status.code != ThermalStatusCode::SUCCESS) {
Xiang Wang192ce4e2023-02-08 14:30:38 -0800340 ALOGE("Failed to register thermal changed callback using %s client", service_str.c_str());
341 return false;
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700342 }
Xiang Wang192ce4e2023-02-08 14:30:38 -0800343 return true;
Badhri Jagan Sridharan400cc0b2021-07-13 09:54:29 -0700344}
345
346Return<void> UsbOverheatEvent::notifyThrottling(const Temperature &temperature) {
347 ALOGV("notifyThrottling '%s' T=%2.2f throttlingStatus=%d", temperature.name.c_str(),
348 temperature.value, temperature.throttlingStatus);
349 if (temperature.type == monitored_zone_.type_) {
350 if (temperature.throttlingStatus >= monitored_zone_.severity_) {
351 startRecording();
352 } else {
353 stopRecording();
354 }
355 }
356 return Void();
357}
358
359ZoneInfo::ZoneInfo(const TemperatureType &type, const string &name,
360 const ThrottlingSeverity &severity)
361 : type_(type), name_(name), severity_(severity) {}
362} // namespace usb
363} // namespace pixel
364} // namespace google
365} // namespace hardware
366} // namespace android