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 #include <cerrno> 18 #include <vector> 19 20 #include <android-base/file.h> 21 #include <android-base/logging.h> 22 23 #include "Thermal.h" 24 #include "thermal-helper.h" 25 26 namespace android { 27 namespace hardware { 28 namespace thermal { 29 namespace V1_1 { 30 namespace implementation { 31 32 Thermal::Thermal() : enabled(initThermal()) {} 33 34 namespace { 35 36 // Saves the IThermalCallback client object registered from the 37 // framework for sending thermal events to the framework thermal event bus. 38 sp<IThermalCallback> gThermalCallback; 39 40 struct ThermalDeathRecipient : hidl_death_recipient { 41 virtual void serviceDied( 42 uint64_t cookie __unused, const wp<IBase>& who __unused) { 43 gThermalCallback = nullptr; 44 LOG(ERROR) << "IThermalCallback HIDL service died"; 45 } 46 }; 47 48 sp<ThermalDeathRecipient> gThermalCallbackDied = nullptr; 49 50 } // anonymous namespace 51 52 // Methods from ::android::hardware::thermal::V1_0::IThermal follow. 53 Return<void> Thermal::getTemperatures(getTemperatures_cb _hidl_cb) { 54 ThermalStatus status; 55 status.code = ThermalStatusCode::SUCCESS; 56 hidl_vec<Temperature> temperatures; 57 temperatures.resize(kTemperatureNum); 58 59 if (!enabled) { 60 status.code = ThermalStatusCode::FAILURE; 61 status.debugMessage = "Unsupported hardware"; 62 _hidl_cb(status, temperatures); 63 LOG(ERROR) << "ThermalHAL not initialized properly."; 64 return Void(); 65 } 66 67 if (fillTemperatures(&temperatures) != kTemperatureNum) { 68 status.code = ThermalStatusCode::FAILURE; 69 status.debugMessage = "Error reading thermal sensors."; 70 } 71 _hidl_cb(status, temperatures); 72 73 for (auto& t : temperatures) { 74 LOG(DEBUG) << "getTemperatures " 75 << " Type: " << static_cast<int>(t.type) 76 << " Name: " << t.name 77 << " CurrentValue: " << t.currentValue 78 << " ThrottlingThreshold: " << t.throttlingThreshold 79 << " ShutdownThreshold: " << t.shutdownThreshold 80 << " VrThrottlingThreshold: " << t.vrThrottlingThreshold; 81 } 82 83 return Void(); 84 } 85 86 Return<void> Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb) { 87 ThermalStatus status; 88 status.code = ThermalStatusCode::SUCCESS; 89 hidl_vec<CpuUsage> cpuUsages; 90 cpuUsages.resize(kCpuNum); 91 92 if (!enabled) { 93 status.code = ThermalStatusCode::FAILURE; 94 status.debugMessage = "Unsupported hardware"; 95 _hidl_cb(status, cpuUsages); 96 LOG(ERROR) << "ThermalHAL not initialized properly."; 97 return Void(); 98 } 99 100 ssize_t ret = fillCpuUsages(&cpuUsages); 101 if (ret < 0) { 102 status.code = ThermalStatusCode::FAILURE; 103 status.debugMessage = strerror(-ret); 104 } 105 106 for (auto& u : cpuUsages) { 107 LOG(DEBUG) << "getCpuUsages " 108 << " Name: " << u.name 109 << " Active: " << u.active 110 << " Total: " << u.total 111 << " IsOnline: " << u.isOnline; 112 } 113 114 _hidl_cb(status, cpuUsages); 115 return Void(); 116 } 117 118 Return<void> Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb) { 119 ThermalStatus status; 120 status.code = ThermalStatusCode::SUCCESS; 121 hidl_vec<CoolingDevice> coolingDevices; 122 123 if (!enabled) { 124 status.code = ThermalStatusCode::FAILURE; 125 status.debugMessage = "Unsupported hardware"; 126 _hidl_cb(status, coolingDevices); 127 LOG(ERROR) << "ThermalHAL not initialized properly."; 128 return Void(); 129 } 130 131 LOG(DEBUG) << "No Cooling Device"; 132 _hidl_cb(status, coolingDevices); 133 return Void(); 134 } 135 136 // Methods from ::android::hardware::thermal::V1_1::IThermal follow. 137 138 Return<void> Thermal::registerThermalCallback( 139 const sp<IThermalCallback>& callback) { 140 gThermalCallback = callback; 141 142 if (gThermalCallback != nullptr) { 143 if (gThermalCallbackDied == nullptr) 144 gThermalCallbackDied = new ThermalDeathRecipient(); 145 146 if (gThermalCallbackDied != nullptr) 147 gThermalCallback->linkToDeath( 148 gThermalCallbackDied, 0x451F /* cookie, unused */); 149 LOG(INFO) << "ThermalCallback registered"; 150 } else { 151 LOG(INFO) << "ThermalCallback unregistered"; 152 } 153 return Void(); 154 } 155 156 // Local functions used internally by thermal-engine follow. 157 158 std::string Thermal::getSkinSensorType() { 159 return getTargetSkinSensorType(); 160 } 161 162 void Thermal::notifyThrottling( 163 bool isThrottling, const Temperature& temperature) { 164 if (gThermalCallback != nullptr) { 165 Return<void> ret = 166 gThermalCallback->notifyThrottling(isThrottling, temperature); 167 if (!ret.isOk()) { 168 if (ret.isDeadObject()) { 169 gThermalCallback = nullptr; 170 LOG(WARNING) << "Dropped throttling event, ThermalCallback died"; 171 } else { 172 LOG(WARNING) << 173 "Failed to send throttling event to ThermalCallback"; 174 } 175 } 176 } else { 177 LOG(WARNING) << 178 "Dropped throttling event, no ThermalCallback registered"; 179 } 180 } 181 182 Return<void> Thermal::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) { 183 if (handle != nullptr && handle->numFds >= 1) { 184 int fd = handle->data[0]; 185 std::ostringstream dump_buf; 186 187 if (!enabled) { 188 dump_buf << "ThermalHAL not initialized properly." << std::endl; 189 } else { 190 hidl_vec<Temperature> temperatures; 191 hidl_vec<CpuUsage> cpu_usages; 192 cpu_usages.resize(kCpuNum); 193 temperatures.resize(kTemperatureNum); 194 195 dump_buf << "getTemperatures:" << std::endl; 196 if (fillTemperatures(&temperatures) != kTemperatureNum) { 197 dump_buf << "Failed to read thermal sensors." << std::endl; 198 } else { 199 for (const auto& t : temperatures) { 200 dump_buf << "Name: " << t.name 201 << " Type: " << android::hardware::thermal::V1_0::toString(t.type) 202 << " CurrentValue: " << t.currentValue 203 << " ThrottlingThreshold: " << t.throttlingThreshold 204 << " ShutdownThreshold: " << t.shutdownThreshold 205 << " VrThrottlingThreshold: " << t.vrThrottlingThreshold 206 << std::endl; 207 } 208 } 209 210 dump_buf << "getCpuUsages:" << std::endl; 211 ssize_t ret = fillCpuUsages(&cpu_usages); 212 if (ret < 0) { 213 dump_buf << "Failed to get CPU usages." << std::endl; 214 } else { 215 for (const auto& usage : cpu_usages) { 216 dump_buf << "Name: " << usage.name 217 << " Active: " << usage.active 218 << " Total: " << usage.total 219 << " IsOnline: " << usage.isOnline 220 << std::endl; 221 } 222 } 223 224 } 225 std::string buf = dump_buf.str(); 226 if (!android::base::WriteStringToFd(buf, fd)) { 227 PLOG(ERROR) << "Failed to dump state to fd"; 228 } 229 fsync(fd); 230 } 231 return Void(); 232 } 233 234 } // namespace implementation 235 } // namespace V1_1 236 } // namespace thermal 237 } // namespace hardware 238 } // namespace android 239