1 /*
2 * Copyright (C) 2018 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 DEBUG false // STOPSHIP if true
18 #include "Log.h"
19
20 #include <android/hardware/thermal/1.0/IThermal.h>
21 #include "external/ResourceThermalManagerPuller.h"
22 #include "external/StatsPuller.h"
23
24 #include "ResourceThermalManagerPuller.h"
25 #include "logd/LogEvent.h"
26 #include "statslog.h"
27 #include "stats_log_util.h"
28
29 #include <chrono>
30
31 using android::hardware::hidl_death_recipient;
32 using android::hardware::hidl_vec;
33 using android::hidl::base::V1_0::IBase;
34 using android::hardware::thermal::V1_0::IThermal;
35 using android::hardware::thermal::V1_0::Temperature;
36 using android::hardware::thermal::V1_0::ThermalStatus;
37 using android::hardware::thermal::V1_0::ThermalStatusCode;
38 using android::hardware::Return;
39 using android::hardware::Void;
40
41 using std::chrono::duration_cast;
42 using std::chrono::nanoseconds;
43 using std::chrono::system_clock;
44 using std::make_shared;
45 using std::shared_ptr;
46
47 namespace android {
48 namespace os {
49 namespace statsd {
50
51 bool getThermalHalLocked();
52 sp<android::hardware::thermal::V1_0::IThermal> gThermalHal = nullptr;
53 std::mutex gThermalHalMutex;
54
55 struct ThermalHalDeathRecipient : virtual public hidl_death_recipient {
serviceDiedandroid::os::statsd::ThermalHalDeathRecipient56 virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override {
57 std::lock_guard<std::mutex> lock(gThermalHalMutex);
58 ALOGE("ThermalHAL just died");
59 gThermalHal = nullptr;
60 getThermalHalLocked();
61 }
62 };
63
64 sp<ThermalHalDeathRecipient> gThermalHalDeathRecipient = nullptr;
65
66 // The caller must be holding gThermalHalMutex.
getThermalHalLocked()67 bool getThermalHalLocked() {
68 if (gThermalHal == nullptr) {
69 gThermalHal = IThermal::getService();
70 if (gThermalHal == nullptr) {
71 ALOGE("Unable to get Thermal service.");
72 } else {
73 if (gThermalHalDeathRecipient == nullptr) {
74 gThermalHalDeathRecipient = new ThermalHalDeathRecipient();
75 }
76 hardware::Return<bool> linked = gThermalHal->linkToDeath(
77 gThermalHalDeathRecipient, 0x451F /* cookie */);
78 if (!linked.isOk()) {
79 ALOGE("Transaction error in linking to ThermalHAL death: %s",
80 linked.description().c_str());
81 gThermalHal = nullptr;
82 } else if (!linked) {
83 ALOGW("Unable to link to ThermalHal death notifications");
84 gThermalHal = nullptr;
85 } else {
86 ALOGD("Link to death notification successful");
87 }
88 }
89 }
90 return gThermalHal != nullptr;
91 }
92
ResourceThermalManagerPuller()93 ResourceThermalManagerPuller::ResourceThermalManagerPuller() :
94 StatsPuller(android::util::TEMPERATURE) {
95 }
96
PullInternal(vector<shared_ptr<LogEvent>> * data)97 bool ResourceThermalManagerPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
98 std::lock_guard<std::mutex> lock(gThermalHalMutex);
99 if (!getThermalHalLocked()) {
100 ALOGE("Thermal Hal not loaded");
101 return false;
102 }
103
104 int64_t wallClockTimestampNs = getWallClockNs();
105 int64_t elapsedTimestampNs = getElapsedRealtimeNs();
106
107 data->clear();
108 bool resultSuccess = true;
109
110 Return<void> ret = gThermalHal->getTemperatures(
111 [&](ThermalStatus status, const hidl_vec<Temperature>& temps) {
112 if (status.code != ThermalStatusCode::SUCCESS) {
113 ALOGE("Failed to get temperatures from ThermalHAL. Status: %d", status.code);
114 resultSuccess = false;
115 return;
116 }
117 if (mTagId == android::util::TEMPERATURE) {
118 for (size_t i = 0; i < temps.size(); ++i) {
119 auto ptr = make_shared<LogEvent>(android::util::TEMPERATURE,
120 wallClockTimestampNs, elapsedTimestampNs);
121 ptr->write((static_cast<int>(temps[i].type)));
122 ptr->write(temps[i].name);
123 // Convert the temperature to an int.
124 int32_t temp = static_cast<int>(temps[i].currentValue * 10);
125 ptr->write(temp);
126 ptr->init();
127 data->push_back(ptr);
128 }
129 } else {
130 ALOGE("Unsupported tag in ResourceThermalManagerPuller: %d", mTagId);
131 }
132 });
133 if (!ret.isOk()) {
134 ALOGE("getThermalHalLocked() failed: thermal HAL service not available. Description: %s",
135 ret.description().c_str());
136 if (ret.isDeadObject()) {
137 gThermalHal = nullptr;
138 }
139 return false;
140 }
141 return resultSuccess;
142 }
143
144 } // namespace statsd
145 } // namespace os
146 } // namespace android
147