mirror of
https://github.com/Evolution-X-Devices/device_oplus_mt6893-common
synced 2026-02-01 12:04:32 +00:00
ossi: Cleanup dead targets
* Adapt to LineageOS common MediaTek HALs. * Import thermal HIDL because we can't use AIDL implement.
This commit is contained in:
66
hidl/thermal/Android.bp
Normal file
66
hidl/thermal/Android.bp
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Copyright (C) 2018 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
cc_library_shared {
|
||||
name: "android.hardware.thermal@2.0-impl-mtk",
|
||||
defaults: ["hidl_defaults"],
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: ["Thermal.cpp",
|
||||
"thermal_watcher.cpp",
|
||||
"thermal_helper.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libc",
|
||||
"liblog",
|
||||
"libcutils",
|
||||
"libhardware",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libutils",
|
||||
"libhidlbase",
|
||||
"android.hardware.thermal@1.0",
|
||||
"android.hardware.thermal@2.0",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.thermal@2.0-service.mtk",
|
||||
defaults: ["hidl_defaults"],
|
||||
relative_install_path: "hw",
|
||||
vendor: true,
|
||||
init_rc: ["android.hardware.thermal@2.0-service.mtk.rc"],
|
||||
vintf_fragments: ["android.hardware.thermal@2.0-service.mtk.xml"],
|
||||
required: [
|
||||
"android.hardware.thermal@2.0-impl-mtk",
|
||||
],
|
||||
srcs: [
|
||||
"service.cpp"
|
||||
],
|
||||
shared_libs: [
|
||||
"libc",
|
||||
"liblog",
|
||||
"libcutils",
|
||||
"libhardware",
|
||||
"libcutils",
|
||||
"libbase",
|
||||
"libhidlbase",
|
||||
"libutils",
|
||||
"android.hardware.thermal@2.0",
|
||||
"android.hardware.thermal@1.0",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
228
hidl/thermal/Thermal.cpp
Normal file
228
hidl/thermal/Thermal.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "android.hardware.thermal@2.0-impl"
|
||||
|
||||
#include <cmath>
|
||||
#include <set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
|
||||
#include "Thermal.h"
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/thermal.h>
|
||||
#include "thermal_helper.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
using ::android::sp;
|
||||
using ::android::hardware::interfacesEqual;
|
||||
using ::android::hardware::thermal::V1_0::ThermalStatus;
|
||||
using ::android::hardware::thermal::V1_0::ThermalStatusCode;
|
||||
|
||||
std::set<sp<IThermalChangedCallback>> gCallbacks;
|
||||
Thermal::Thermal()
|
||||
: thermal_helper_(
|
||||
std::bind(&Thermal::sendThermalChangedCallback, this, std::placeholders::_1)) {
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::thermal::V1_0::IThermal follow.
|
||||
Return<void> Thermal::getTemperatures(getTemperatures_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
hidl_vec<Temperature_1_0> temperatures;
|
||||
|
||||
if (!thermal_helper_.fill_temperatures_1_0(&temperatures)) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "get temp fail";
|
||||
}
|
||||
_hidl_cb(status, temperatures);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
hidl_vec<CpuUsage> cpu_usages;
|
||||
|
||||
if (!thermal_helper_.fillCpuUsages(&cpu_usages)) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "Failed to get CPU usages.";
|
||||
}
|
||||
_hidl_cb(status, cpu_usages);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
hidl_vec<CoolingDevice_1_0> cooling_devices;
|
||||
_hidl_cb(status, cooling_devices);
|
||||
return Void();
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::thermal::V2_0::IThermal follow.
|
||||
Return<void> Thermal::getCurrentTemperatures(bool filterType, TemperatureType type,
|
||||
getCurrentTemperatures_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
hidl_vec<Temperature_2_0> temperatures;
|
||||
if (!thermal_helper_.fill_temperatures(filterType, &temperatures, type)) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "get temp fail";
|
||||
}
|
||||
_hidl_cb(status, temperatures);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Return<void> Thermal::getTemperatureThresholds(bool filterType, TemperatureType type,
|
||||
getTemperatureThresholds_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
hidl_vec<TemperatureThreshold> temperature_thresholds;
|
||||
|
||||
if (!thermal_helper_.fill_thresholds(filterType, &temperature_thresholds, type)) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "get temperature thresholds fail";
|
||||
}
|
||||
_hidl_cb(status, temperature_thresholds);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> Thermal::getCurrentCoolingDevices(bool filterType, CoolingType type,
|
||||
getCurrentCoolingDevices_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
std::vector<CoolingDevice_2_0> cooling_devices;
|
||||
|
||||
if (!thermal_helper_.fill_cooling_devices(filterType, &cooling_devices, type)) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "get cooling devices fail";
|
||||
}
|
||||
_hidl_cb(status, cooling_devices);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> Thermal::registerThermalChangedCallback(const sp<IThermalChangedCallback>& callback,
|
||||
bool filterType, TemperatureType type,
|
||||
registerThermalChangedCallback_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
if (callback == nullptr) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "Invalid nullptr callback";
|
||||
LOG(ERROR) << status.debugMessage;
|
||||
_hidl_cb(status);
|
||||
return Void();
|
||||
} else {
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
}
|
||||
std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
|
||||
if (std::any_of(callbacks_.begin(), callbacks_.end(), [&](const CallbackSetting& c) {
|
||||
return interfacesEqual(c.callback, callback);
|
||||
})) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "Same callback interface registered already";
|
||||
LOG(ERROR) << status.debugMessage;
|
||||
} else {
|
||||
callbacks_.emplace_back(callback, filterType, type);
|
||||
LOG(INFO) << "A callback has been registered to ThermalHAL, isFilter: " << filterType
|
||||
<< " Type: " << android::hardware::thermal::V2_0::toString(type);
|
||||
}
|
||||
_hidl_cb(status);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> Thermal::unregisterThermalChangedCallback(
|
||||
const sp<IThermalChangedCallback>& callback, unregisterThermalChangedCallback_cb _hidl_cb) {
|
||||
ThermalStatus status;
|
||||
if (callback == nullptr) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "Invalid nullptr callback";
|
||||
LOG(ERROR) << status.debugMessage;
|
||||
_hidl_cb(status);
|
||||
return Void();
|
||||
} else {
|
||||
status.code = ThermalStatusCode::SUCCESS;
|
||||
}
|
||||
bool removed = false;
|
||||
std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
|
||||
callbacks_.erase(
|
||||
std::remove_if(callbacks_.begin(), callbacks_.end(),
|
||||
[&](const CallbackSetting& c) {
|
||||
if (interfacesEqual(c.callback, callback)) {
|
||||
LOG(INFO)
|
||||
<< "A callback has been unregistered from ThermalHAL, isFilter: "
|
||||
<< c.is_filter_type << " Type: "
|
||||
<< android::hardware::thermal::V2_0::toString(c.type);
|
||||
removed = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
callbacks_.end());
|
||||
if (!removed) {
|
||||
status.code = ThermalStatusCode::FAILURE;
|
||||
status.debugMessage = "The callback was not registered before";
|
||||
LOG(ERROR) << status.debugMessage;
|
||||
}
|
||||
_hidl_cb(status);
|
||||
return Void();
|
||||
}
|
||||
|
||||
void Thermal::sendThermalChangedCallback(const std::vector<Temperature_2_0> &temps) {
|
||||
std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
|
||||
for (auto &t : temps) {
|
||||
LOG(INFO) << "Sending notification: "
|
||||
<< " Type: " << android::hardware::thermal::V2_0::toString(t.type)
|
||||
<< " Name: " << t.name << " CurrentValue: " << t.value << " ThrottlingStatus: "
|
||||
<< android::hardware::thermal::V2_0::toString(t.throttlingStatus);
|
||||
callbacks_.erase(
|
||||
std::remove_if(callbacks_.begin(), callbacks_.end(),
|
||||
[&](const CallbackSetting &c) {
|
||||
if (!c.is_filter_type || t.type == c.type) {
|
||||
Return<void> ret = c.callback->notifyThrottling(t);
|
||||
LOG(INFO) << "sendThermalChangedCallback";
|
||||
return !ret.isOk();
|
||||
}
|
||||
LOG(ERROR)
|
||||
<< "a Thermal callback is dead, removed from callback list.";
|
||||
return false;
|
||||
}),
|
||||
callbacks_.end());
|
||||
}
|
||||
}
|
||||
|
||||
IThermal* HIDL_FETCH_IThermal(const char* /* name */) {
|
||||
return new Thermal();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
98
hidl/thermal/Thermal.h
Normal file
98
hidl/thermal/Thermal.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android/hardware/thermal/2.0/IThermal.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <hardware/thermal.h>
|
||||
#include "thermal_helper.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::sp;
|
||||
using ::android::hardware::hidl_array;
|
||||
using ::android::hardware::hidl_memory;
|
||||
using ::android::hardware::hidl_string;
|
||||
using ::android::hardware::hidl_vec;
|
||||
using ::android::hardware::Return;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::thermal::V1_0::CpuUsage;
|
||||
using ::android::hardware::thermal::V2_0::CoolingType;
|
||||
using ::android::hardware::thermal::V2_0::IThermal;
|
||||
using CoolingDevice_1_0 = ::android::hardware::thermal::V1_0::CoolingDevice;
|
||||
using CoolingDevice_2_0 = ::android::hardware::thermal::V2_0::CoolingDevice;
|
||||
using Temperature_1_0 = ::android::hardware::thermal::V1_0::Temperature;
|
||||
using Temperature_2_0 = ::android::hardware::thermal::V2_0::Temperature;
|
||||
using ::android::hardware::thermal::V2_0::IThermalChangedCallback;
|
||||
using ::android::hardware::thermal::V2_0::TemperatureThreshold;
|
||||
using ::android::hardware::thermal::V2_0::TemperatureType;
|
||||
|
||||
|
||||
struct CallbackSetting {
|
||||
CallbackSetting(sp<IThermalChangedCallback> callback, bool is_filter_type, TemperatureType type)
|
||||
: callback(callback), is_filter_type(is_filter_type), type(type) {}
|
||||
sp<IThermalChangedCallback> callback;
|
||||
bool is_filter_type;
|
||||
TemperatureType type;
|
||||
};
|
||||
|
||||
class Thermal : public IThermal {
|
||||
|
||||
public:
|
||||
//Thermal(thermal_module_t* module);
|
||||
Thermal();
|
||||
~Thermal() = default;
|
||||
|
||||
// Methods from ::android::hardware::thermal::V1_0::IThermal follow.
|
||||
Return<void> getTemperatures(getTemperatures_cb _hidl_cb) override;
|
||||
Return<void> getCpuUsages(getCpuUsages_cb _hidl_cb) override;
|
||||
Return<void> getCoolingDevices(getCoolingDevices_cb _hidl_cb) override;
|
||||
|
||||
// Methods from ::android::hardware::thermal::V2_0::IThermal follow.
|
||||
Return<void> getCurrentTemperatures(bool filterType, TemperatureType type,
|
||||
getCurrentTemperatures_cb _hidl_cb) override;
|
||||
Return<void> getTemperatureThresholds(bool filterType, TemperatureType type,
|
||||
getTemperatureThresholds_cb _hidl_cb) override;
|
||||
Return<void> registerThermalChangedCallback(
|
||||
const sp<IThermalChangedCallback>& callback, bool filterType, TemperatureType type,
|
||||
registerThermalChangedCallback_cb _hidl_cb) override;
|
||||
Return<void> unregisterThermalChangedCallback(
|
||||
const sp<IThermalChangedCallback>& callback,
|
||||
unregisterThermalChangedCallback_cb _hidl_cb) override;
|
||||
Return<void> getCurrentCoolingDevices(bool filterType, CoolingType type,
|
||||
getCurrentCoolingDevices_cb _hidl_cb) override;
|
||||
|
||||
// Helper function for calling callbacks
|
||||
void sendThermalChangedCallback(const std::vector<Temperature_2_0> &temps);
|
||||
private:
|
||||
ThermalHelper thermal_helper_;
|
||||
std::mutex thermal_callback_mutex_;
|
||||
std::vector<CallbackSetting> callbacks_;
|
||||
};
|
||||
extern "C" IThermal* HIDL_FETCH_IThermal(const char* name);
|
||||
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
7
hidl/thermal/android.hardware.thermal@2.0-service.mtk.rc
Normal file
7
hidl/thermal/android.hardware.thermal@2.0-service.mtk.rc
Normal file
@@ -0,0 +1,7 @@
|
||||
service vendor.thermal-hal-2-0.mtk /vendor/bin/hw/android.hardware.thermal@2.0-service.mtk
|
||||
interface android.hardware.thermal@1.0::IThermal default
|
||||
interface android.hardware.thermal@2.0::IThermal default
|
||||
socket thermal_hal_socket stream 660 root system
|
||||
class hal
|
||||
user system
|
||||
group system
|
||||
12
hidl/thermal/android.hardware.thermal@2.0-service.mtk.xml
Normal file
12
hidl/thermal/android.hardware.thermal@2.0-service.mtk.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="hidl">
|
||||
<name>android.hardware.thermal</name>
|
||||
<transport>hwbinder</transport>
|
||||
<version>1.0</version>
|
||||
<version>2.0</version>
|
||||
<interface>
|
||||
<name>IThermal</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
</manifest>
|
||||
39
hidl/thermal/service.cpp
Normal file
39
hidl/thermal/service.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "android.hardware.thermal@2.0-service"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
#include "Thermal.h"
|
||||
#include <android/hardware/thermal/1.0/IThermal.h>
|
||||
#include <hidl/LegacySupport.h>
|
||||
|
||||
using ::android::OK;
|
||||
using ::android::status_t;
|
||||
|
||||
// libhwbinder:
|
||||
using ::android::hardware::configureRpcThreadpool;
|
||||
using ::android::hardware::joinRpcThreadpool;
|
||||
|
||||
// Generated HIDL files:
|
||||
using ::android::hardware::thermal::V2_0::IThermal;
|
||||
using ::android::hardware::thermal::V2_0::implementation::Thermal;
|
||||
using android::hardware::defaultPassthroughServiceImplementation;
|
||||
|
||||
int main() {
|
||||
return defaultPassthroughServiceImplementation<IThermal>();
|
||||
}
|
||||
888
hidl/thermal/thermal_helper.cpp
Normal file
888
hidl/thermal/thermal_helper.cpp
Normal file
@@ -0,0 +1,888 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
|
||||
#include "thermal_helper.h"
|
||||
#include "thermal_map_table_type.h"
|
||||
#include "thermal_map_table.h"
|
||||
|
||||
|
||||
#define TH_LOG_TAG "thermal_hal"
|
||||
#define TH_DLOG(_priority_, _fmt_, args...) /*LOG_PRI(_priority_, TH_LOG_TAG, _fmt_, ##args)*/
|
||||
#define TH_LOG(_priority_, _fmt_, args...) LOG_PRI(_priority_, TH_LOG_TAG, _fmt_, ##args)
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::thermal::V1_0::ThermalStatus;
|
||||
using ::android::hardware::thermal::V1_0::ThermalStatusCode;
|
||||
using ::android::hardware::thermal::V2_0::implementation::kMtkTempThreshold;
|
||||
using ::android::hardware::thermal::V2_0::implementation::tz_data;
|
||||
using ::android::hardware::thermal::V2_0::implementation::tz_data_v1;
|
||||
using ::android::hardware::thermal::V2_0::implementation::tz_data_v2;
|
||||
using ::android::hardware::thermal::V2_0::implementation::tz_data_v3;
|
||||
using ::android::hardware::thermal::V2_0::implementation::cdata;
|
||||
|
||||
|
||||
|
||||
ThermalHelper::ThermalHelper(const NotificationCallback &cb)
|
||||
: thermal_watcher_(new ThermalWatcher(
|
||||
std::bind(&ThermalHelper::thermalWatcherCallbackFunc, this, std::placeholders::_1))),
|
||||
cb_(cb) {
|
||||
thermal_zone_num = 0;
|
||||
cooling_device_num = 0;
|
||||
tz_map_version = get_tz_map_version();
|
||||
ALOGW("%s:tz_map_version %d", __func__, tz_map_version);
|
||||
thermal_watcher_->initThermalWatcher(tz_map_version);
|
||||
// Need start watching after status map initialized
|
||||
is_initialized_ = thermal_watcher_->startThermalWatcher();
|
||||
if (!is_initialized_) {
|
||||
LOG(FATAL) << "ThermalHAL could not start watching thread properly.";
|
||||
}
|
||||
}
|
||||
|
||||
ThrottlingSeverity ThermalHelper::getSeverityFromThresholds(float value, TemperatureType_2_0 type) {
|
||||
ThrottlingSeverity ret_hot = ThrottlingSeverity::NONE;
|
||||
int typetoint = static_cast<int>(type);
|
||||
|
||||
if (typetoint < 0)
|
||||
return ret_hot;
|
||||
|
||||
for (size_t i = static_cast<size_t>(ThrottlingSeverity::SHUTDOWN);
|
||||
i > static_cast<size_t>(ThrottlingSeverity::NONE); --i) {
|
||||
if (!std::isnan(kMtkTempThreshold[typetoint].hotThrottlingThresholds[i]) && kMtkTempThreshold[typetoint].hotThrottlingThresholds[i] <= value &&
|
||||
ret_hot == ThrottlingSeverity::NONE) {
|
||||
ret_hot = static_cast<ThrottlingSeverity>(i);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_hot;
|
||||
}
|
||||
|
||||
float ThermalHelper::get_max_temp(int type) {
|
||||
|
||||
FILE *file;
|
||||
float temp = 0;
|
||||
char temp_path[TZPATH_LENGTH];
|
||||
float max_temp = INVALID_TEMP;
|
||||
int ret;
|
||||
|
||||
if (type < 0 || type >= TT_MAX) {
|
||||
return INVALID_TEMP;
|
||||
}
|
||||
for (int i = 0; i < MAX_MUTI_TZ_NUM; i++) {
|
||||
ret = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/temp", tz_data[type].tz_idx[i]);
|
||||
if (ret < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, ret);
|
||||
}
|
||||
file = fopen(temp_path, "r");
|
||||
if (file == NULL) {
|
||||
//ALOGW("%s: failed to open type %d path %s", __func__, type, temp_path);
|
||||
break;
|
||||
} else {
|
||||
if ((fscanf(file, "%f", &temp) > 0) && (temp > max_temp)){
|
||||
max_temp = temp;
|
||||
}
|
||||
}
|
||||
|
||||
ret = fclose(file);
|
||||
if (ret) {
|
||||
ALOGW("%s: fclose fail: %d", __func__, ret);
|
||||
}
|
||||
}
|
||||
|
||||
return max_temp;
|
||||
}
|
||||
|
||||
bool ThermalHelper::read_temperature(int type, Temperature_1_0 *ret_temp) {
|
||||
|
||||
float temp;
|
||||
bool ret = false;
|
||||
|
||||
if (type < 0 || type > TT_SKIN) {
|
||||
return ret;
|
||||
}
|
||||
temp = get_max_temp(type);
|
||||
ret_temp->name = tz_data[type].label;
|
||||
ret_temp->type = static_cast<TemperatureType_1_0>(type);
|
||||
ret_temp->currentValue = temp * 0.001;
|
||||
ret_temp->throttlingThreshold = kMtkTempThreshold[type].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::SEVERE)];
|
||||
ret_temp->shutdownThreshold = kMtkTempThreshold[type].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::SHUTDOWN)];
|
||||
ret_temp->vrThrottlingThreshold = kMtkTempThreshold[type].vrThrottlingThreshold;
|
||||
ret = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ThermalHelper::read_temperature(int type, Temperature_2_0 *ret_temp) {
|
||||
|
||||
float temp;
|
||||
bool ret = false;
|
||||
|
||||
if (type < 0 || type >= TT_MAX) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
temp = get_max_temp(type);
|
||||
ret_temp->name = tz_data[type].label;
|
||||
ret_temp->type = static_cast<TemperatureType_2_0>(type);
|
||||
ret_temp->value = temp * 0.001;
|
||||
ret_temp->throttlingStatus = getSeverityFromThresholds(ret_temp->value, ret_temp->type);
|
||||
ret = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ThermalHelper::fillCpuUsages(hidl_vec<CpuUsage> *cpu_usages) {
|
||||
int vals, ret;
|
||||
ssize_t read;
|
||||
uint64_t user, nice, system, idle, active, total;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
int size = 0;
|
||||
FILE *file = NULL;
|
||||
unsigned int max_core_num, cpu_array;
|
||||
unsigned int cpu_num = 0;
|
||||
FILE *core_num_file = NULL;
|
||||
std::vector<CpuUsage> ret_cpu_usages;
|
||||
int i;
|
||||
|
||||
/*======get device max core num=======*/
|
||||
core_num_file = fopen(CORENUM_PATH, "r");
|
||||
if (core_num_file == NULL) {
|
||||
ALOGW("thermal_hal: %s: failed to open:CORENUM_PATH %s", __func__, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fscanf(core_num_file, "%*d-%d", &max_core_num) != 1) {
|
||||
ALOGW("thermal_hal: %s: unable to parse CORENUM_PATH", __func__);
|
||||
ret = fclose(core_num_file);
|
||||
if (ret) {
|
||||
ALOGW("%s: fclose fail: %d", __func__, ret);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ret = fclose(core_num_file);
|
||||
if (ret) {
|
||||
ALOGW("%s: fclose fail: %d", __func__, ret);
|
||||
}
|
||||
|
||||
cpu_array = sizeof(CPU_ALL_LABEL) / sizeof(CPU_ALL_LABEL[0]);
|
||||
|
||||
if (((max_core_num + 1) > cpu_array) || ((max_core_num + 1) <= 0)) {
|
||||
ALOGW("thermal_hal: %s: max_core_num = %d, cpu_array = %d", __func__, max_core_num, cpu_array);
|
||||
return false;
|
||||
}
|
||||
max_core_num += 1;
|
||||
|
||||
ALOGW("%s: max_core_num=%d", __func__, max_core_num);
|
||||
/*======get device max core num=======*/
|
||||
|
||||
|
||||
file = fopen(CPU_USAGE_FILE, "r");
|
||||
if (file == NULL) {
|
||||
ALOGW("thermal_hal: %s: failed to open: CPU_USAGE_FILE: %s", __func__, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((read = getline(&line, &len, file)) != -1) {
|
||||
CpuUsage cpu_usage;
|
||||
|
||||
// Skip non "cpu[0-9]" lines.
|
||||
if (strnlen(line, read) < 4 || strncmp(line, "cpu", 3) != 0 || !isdigit(line[3])) {
|
||||
free(line);
|
||||
line = NULL;
|
||||
len = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
vals = sscanf(line, "cpu%d %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, &cpu_num, &user,
|
||||
&nice, &system, &idle);
|
||||
|
||||
free(line);
|
||||
line = NULL;
|
||||
len = 0;
|
||||
|
||||
|
||||
if (vals != 5) {
|
||||
ALOGW("thermal_hal: %s: failed to read CPU information from file: %s", __func__, strerror(errno));
|
||||
ret = fclose(file);
|
||||
if (ret) {
|
||||
ALOGW("%s: fclose fail: %d", __func__, ret);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
active = user + nice + system;
|
||||
total = active + idle;
|
||||
|
||||
if (cpu_num < max_core_num) {
|
||||
cpu_usage.name = CPU_ALL_LABEL[cpu_num];
|
||||
cpu_usage.active = active;
|
||||
cpu_usage.total = total;
|
||||
cpu_usage.isOnline = 1;
|
||||
ret_cpu_usages.emplace_back(std::move(cpu_usage));
|
||||
} else {
|
||||
ALOGW("thermal_hal: %s: cpu_num %d > max_core_num %d", __func__, cpu_num, max_core_num);
|
||||
ret = fclose(file);
|
||||
if (ret) {
|
||||
ALOGW("%s: fclose fail: %d", __func__, ret);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size++;
|
||||
}
|
||||
/*if there are hotplug off CPUs, set cpu_usage.total = 0*/
|
||||
for (i = size; i < max_core_num; i++) {
|
||||
CpuUsage cpu_usage;
|
||||
cpu_usage.name = CPU_ALL_LABEL[i];
|
||||
cpu_usage.active = 0;
|
||||
cpu_usage.total = 0;
|
||||
cpu_usage.isOnline = 0;
|
||||
ret_cpu_usages.emplace_back(std::move(cpu_usage));
|
||||
}
|
||||
|
||||
ALOGW("%s end loop, size %d, cpu_num = %d, max_core_num = %d", __func__, size, cpu_num, max_core_num);
|
||||
|
||||
ret = fclose(file);
|
||||
if (ret) {
|
||||
ALOGW("%s: fclose fail: %d", __func__, ret);
|
||||
}
|
||||
*cpu_usages = ret_cpu_usages;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool ThermalHelper::fill_temperatures_1_0(hidl_vec<Temperature_1_0> *temperatures) {
|
||||
|
||||
bool ret = false;
|
||||
std::vector<Temperature_1_0> ret_temps;
|
||||
int current_index = 0;
|
||||
|
||||
for (int i = 0; i <= TT_SKIN; i++) {
|
||||
Temperature_1_0 ret_temp;
|
||||
if (!is_tz_path_valided(i))
|
||||
init_tz_path();
|
||||
|
||||
if (tz_data[i].tz_idx[0] == -1) {
|
||||
continue;
|
||||
}
|
||||
if (read_temperature(i, &ret_temp)) {
|
||||
LOG(INFO) << "fill_temperatures_1_0 "
|
||||
<< " name: " << ret_temp.name
|
||||
<< " throttlingStatus: " << ret_temp.throttlingThreshold
|
||||
<< " value: " << ret_temp.currentValue;
|
||||
ret_temps.emplace_back(std::move(ret_temp));
|
||||
ret = true;
|
||||
} else {
|
||||
ALOGW("%s: read temp fail type:%d", __func__, i);
|
||||
return false;
|
||||
}
|
||||
++current_index;
|
||||
}
|
||||
*temperatures = ret_temps;
|
||||
return current_index > 0;
|
||||
}
|
||||
|
||||
bool ThermalHelper::fill_temperatures(bool filterType, hidl_vec<Temperature_2_0> *temperatures, TemperatureType_2_0 type) {
|
||||
|
||||
bool ret = false;
|
||||
std::vector<Temperature_2_0> ret_temps;
|
||||
int typetoint = static_cast<int>(type);
|
||||
|
||||
if (!is_tz_path_valided(typetoint))
|
||||
init_tz_path();
|
||||
|
||||
for (int i = 0; i < TT_MAX; i++) {
|
||||
Temperature_2_0 ret_temp;
|
||||
if ((filterType && i != typetoint) || (tz_data[i].tz_idx[0] == -1)) {
|
||||
continue;
|
||||
}
|
||||
if (read_temperature(i, &ret_temp)) {
|
||||
LOG(INFO) << "fill_temperatures "
|
||||
<< "filterType" << filterType
|
||||
<< " name: " << ret_temp.name
|
||||
<< " type: " << android::hardware::thermal::V2_0::toString(ret_temp.type)
|
||||
<< " throttlingStatus: " << android::hardware::thermal::V2_0::toString(ret_temp.throttlingStatus)
|
||||
<< " value: " << ret_temp.value
|
||||
<< " ret_temps size " << ret_temps.size();
|
||||
ret_temps.emplace_back(std::move(ret_temp));
|
||||
ret = true;
|
||||
} else {
|
||||
ALOGW("%s: read temp fail type:%d", __func__, i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*temperatures = ret_temps;
|
||||
|
||||
return ret;
|
||||
}
|
||||
bool ThermalHelper::fill_thresholds(bool filterType, hidl_vec<TemperatureThreshold> *Threshold, TemperatureType_2_0 type) {
|
||||
|
||||
FILE *file;
|
||||
bool ret = false;
|
||||
std::vector<TemperatureThreshold> ret_thresholds;
|
||||
int typetoint = static_cast<int>(type);
|
||||
char temp_path[TZPATH_LENGTH];
|
||||
int r;
|
||||
|
||||
for (int i = 0; i < TT_MAX; i++) {
|
||||
TemperatureThreshold ret_threshold;
|
||||
if (filterType && i != typetoint) {
|
||||
continue;
|
||||
}
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", tz_data[i].tz_idx[0]);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
file = fopen(temp_path, "r");
|
||||
if (file) {
|
||||
ret_threshold = {kMtkTempThreshold[i]};
|
||||
LOG(INFO) << "fill_thresholds "
|
||||
<< "filterType" << filterType
|
||||
<< " name: " << ret_threshold.name
|
||||
<< " type: " << android::hardware::thermal::V2_0::toString(ret_threshold.type)
|
||||
<< " hotThrottlingThresholds: " << ret_threshold.hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::SEVERE)]
|
||||
<< " vrThrottlingThreshold: " << ret_threshold.vrThrottlingThreshold
|
||||
<< " ret_thresholds size " << ret_thresholds.size();
|
||||
ret_thresholds.emplace_back(std::move(ret_threshold));
|
||||
ret = true;
|
||||
r = fclose(file);
|
||||
if (r) {
|
||||
ALOGW("%s: fclose fail: %d", __func__, r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ALOGW("%s: %s not support", __func__, kMtkTempThreshold[i].name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
*Threshold = ret_thresholds;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ThermalHelper::fill_cooling_devices(bool filterType, std::vector<CoolingDevice_2_0> *CoolingDevice, CoolingType type) {
|
||||
|
||||
std::vector<CoolingDevice_2_0> ret_coolings;
|
||||
bool ret = false;
|
||||
|
||||
if (!is_cooling_path_valided())
|
||||
init_cl_path();
|
||||
|
||||
for (int i = 0; i < MAX_COOLING; i++) {
|
||||
if (filterType && type != cdata[i].cl_2_0.type) {
|
||||
continue;
|
||||
}
|
||||
if (cdata[i].cl_idx != -1) {
|
||||
CoolingDevice_2_0 coolingdevice;
|
||||
coolingdevice.name = cdata[i].cl_2_0.name;
|
||||
coolingdevice.type = cdata[i].cl_2_0.type;
|
||||
coolingdevice.value = cdata[i].cl_2_0.value;
|
||||
LOG(INFO) << "fill_cooling_devices "
|
||||
<< "filterType" << filterType
|
||||
<< " name: " << coolingdevice.name
|
||||
<< " type: " << android::hardware::thermal::V2_0::toString(coolingdevice.type)
|
||||
<< " value: " << coolingdevice.value
|
||||
<< " ret_coolings size " << ret_coolings.size();
|
||||
ret_coolings.emplace_back(std::move(coolingdevice));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
*CoolingDevice = ret_coolings;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ThermalHelper::init_cl_path() {
|
||||
|
||||
char temp_path[CDPATH_LENGTH];
|
||||
char temp_value_path[CDPATH_LENGTH];
|
||||
char buf[CDNAME_SZ];
|
||||
int fd = -1;
|
||||
int fd_value = -1;
|
||||
int read_len = 0;
|
||||
int i = 0;
|
||||
bool ret = true;
|
||||
int r;
|
||||
|
||||
/*initial cdata*/
|
||||
for (int j = 0; j < MAX_COOLING; ++j) {
|
||||
cdata[j].cl_2_0.value = 0;
|
||||
cdata[j].cl_idx = -1;
|
||||
}
|
||||
cooling_device_num = 0;
|
||||
while(1) {
|
||||
r = snprintf(temp_path, CDPATH_LENGTH, CDPATH_PREFIX"%d/type", i);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ALOGW("%s:find out cooling path", __func__);
|
||||
cooling_device_num = i;
|
||||
break;
|
||||
} else {
|
||||
CoolingDevice_2_0 coolingdevice;
|
||||
read_len = read(fd, buf, CDNAME_SZ);
|
||||
for (int j = 0; j < MAX_COOLING; ++j) {
|
||||
if (std::strncmp(buf, cdata[j].cl_2_0.name.c_str(), std::strlen(cdata[j].cl_2_0.name.c_str())) == 0) {
|
||||
cdata[j].cl_idx = i;
|
||||
r = snprintf(temp_value_path, CDPATH_LENGTH, CDPATH_PREFIX"%d/cur_state", i);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd_value = open(temp_value_path, O_RDONLY);
|
||||
if (fd_value == -1) {
|
||||
ALOGW("%s:get value fail", __func__);
|
||||
ret = false;
|
||||
break;
|
||||
} else {
|
||||
read_len = read(fd_value, buf, CDNAME_SZ);
|
||||
cdata[j].cl_2_0.value = std::atoi(buf);
|
||||
LOG(INFO) << "init_cl_path"
|
||||
<< "cl_idx" << cdata[j].cl_idx
|
||||
<< " name: " << cdata[j].cl_2_0.name
|
||||
<< " value: " << cdata[j].cl_2_0.value;
|
||||
}
|
||||
close(fd_value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
i++;
|
||||
close(fd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ThermalHelper::is_cooling_path_valided() {
|
||||
char temp_path[CDPATH_LENGTH];
|
||||
char buf[CDNAME_SZ];
|
||||
int fd = -1;
|
||||
int read_len = 0;
|
||||
bool ret = true;
|
||||
int r;
|
||||
|
||||
/*check if cooling device number are changed*/
|
||||
r = snprintf(temp_path, CDPATH_LENGTH, CDPATH_PREFIX"%d/type", (cooling_device_num - 1));
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
LOG(INFO) << "cl_num are changed" << cooling_device_num;
|
||||
return false;
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
r = snprintf(temp_path, CDPATH_LENGTH, CDPATH_PREFIX"%d/type", cooling_device_num);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
LOG(INFO) << "cl_num are increased" << cooling_device_num;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < MAX_COOLING; i++) {
|
||||
if (cdata[i].cl_idx != -1) {
|
||||
r = snprintf(temp_path, CDPATH_LENGTH, CDPATH_PREFIX"%d/type", cdata[i].cl_idx);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ALOGW("%s:cl path error %d %s" , __func__, i, temp_path);
|
||||
ret = false;
|
||||
break;
|
||||
} else {
|
||||
read_len = read(fd, buf, CDNAME_SZ);
|
||||
if (std::strncmp(buf, cdata[i].cl_2_0.name.c_str(), std::strlen(cdata[i].cl_2_0.name.c_str())) != 0) {
|
||||
ret = false;
|
||||
close(fd);
|
||||
LOG(INFO) << " cl name mismatch "<< i << cdata[i].cl_2_0.name;
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ThermalHelper::is_tz_path_valided(int type) {
|
||||
char temp_path[TZPATH_LENGTH];
|
||||
char buf[TZNAME_SZ];
|
||||
int fd = -1;
|
||||
int read_len = 0;
|
||||
bool ret = true;
|
||||
int r;
|
||||
|
||||
if (type < 0 || type >= TT_MAX) {
|
||||
return false;
|
||||
}
|
||||
/*check if thermal zone number are changed*/
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", (thermal_zone_num - 1));
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
LOG(INFO) << "thermal_zone_num are changed" << thermal_zone_num;
|
||||
return false;
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", thermal_zone_num);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
LOG(INFO) << "thermal_zone_num are increased" << thermal_zone_num;
|
||||
return false;
|
||||
}
|
||||
if (tz_data[type].tz_idx[0] != -1) {
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", tz_data[type].tz_idx[0]);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ALOGW("%s:tz path error %d %s" , __func__, type, temp_path);
|
||||
ret = false;
|
||||
} else {
|
||||
read_len = read(fd, buf, TZNAME_SZ);
|
||||
/*/sys/class/thermal/thermal_zone{$tz_idx}/type should equal tzName*/
|
||||
if (std::strncmp(buf, tz_data[type].tzName, strlen(tz_data[type].tzName)) != 0) {
|
||||
ret = false;
|
||||
LOG(INFO) << " tz name mismatch "<< type << tz_data[type].tzName;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ThermalHelper::get_tz_map() {
|
||||
int v2_idx = 0;
|
||||
int v3_idx = 0;
|
||||
int r;
|
||||
|
||||
if (tz_map_version == TZ_MAP_LEGANCY) {
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
r = snprintf(tz_data[j].tzName, sizeof(tz_data_v1[j].tzName), "%s", tz_data_v1[j].tzName);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
tz_data[j].muti_tz_num = 1;
|
||||
tz_data[j].tz_idx[0] = tz_data_v1[j].tz_idx[0];
|
||||
}
|
||||
} else if (tz_map_version == TZ_MAP_V2) {
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
r = snprintf(tz_data[j].tzName, sizeof(tz_data_v2[v2_idx].tzName), "%s", tz_data_v2[v2_idx].tzName);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
tz_data[j].muti_tz_num = tz_data_v2[v2_idx].muti_tz_num;
|
||||
for (int l = 0; l < tz_data[j].muti_tz_num ; ++l)
|
||||
tz_data[j].tz_idx[l] = tz_data_v2[v2_idx + l].tz_idx[0];
|
||||
if (tz_data[j].muti_tz_num > 1)
|
||||
v2_idx += (tz_data[j].muti_tz_num - 1);
|
||||
v2_idx++;
|
||||
}
|
||||
} else if (tz_map_version == TZ_MAP_V3) {
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
r = snprintf(tz_data[j].tzName, sizeof(tz_data_v3[v3_idx].tzName), "%s", tz_data_v3[v3_idx].tzName);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
tz_data[j].muti_tz_num = tz_data_v3[v3_idx].muti_tz_num;
|
||||
for (int l = 0; l < tz_data[j].muti_tz_num ; ++l)
|
||||
tz_data[j].tz_idx[l] = tz_data_v3[v3_idx + l].tz_idx[0];
|
||||
if (tz_data[j].muti_tz_num > 1)
|
||||
v3_idx += (tz_data[j].muti_tz_num - 1);
|
||||
v3_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
ALOGW("%s: tz%d, name=%s, label=%s, muti_tz_num=%d", __func__, j, tz_data[j].tzName, tz_data[j].label, tz_data[j].muti_tz_num);
|
||||
ALOGW("tz_idx0:%d, tz_idx1:%d,tz_idx2:%d,tz_idx3:%d,tz_idx4:%d,", tz_data[j].tz_idx[0], tz_data[j].tz_idx[1], tz_data[j].tz_idx[2], tz_data[j].tz_idx[3], tz_data[j].tz_idx[4]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int ThermalHelper::get_tz_map_version() {
|
||||
char temp_path[TZPATH_LENGTH];
|
||||
char buf[TZNAME_SZ];
|
||||
int fd = -1;
|
||||
int read_len = 0;
|
||||
int i = 0;
|
||||
int version = 0;
|
||||
int soc_max_exist = 0;
|
||||
int ap_ntc_exist = 0;
|
||||
int r;
|
||||
|
||||
while(1) {
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", i);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ALOGW("%s:find out tz path", __func__);
|
||||
break;
|
||||
} else {
|
||||
read_len = read(fd, buf, TZNAME_SZ);
|
||||
if (std::strncmp(buf, tz_data_v1[0].tzName, strlen(tz_data_v1[0].tzName)) == 0) {
|
||||
version = TZ_MAP_LEGANCY;
|
||||
close(fd);
|
||||
break;
|
||||
ALOGW("support legancy tz data");
|
||||
} else {
|
||||
if (std::strncmp(buf, tz_data_v2[0].tzName, strlen(tz_data_v2[0].tzName)) == 0)
|
||||
soc_max_exist = 1;
|
||||
if (std::strncmp(buf, tz_data_v2[TT_SKIN].tzName, strlen(tz_data_v2[TT_SKIN].tzName)) == 0)
|
||||
ap_ntc_exist = 1;
|
||||
}
|
||||
i++;
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
if ((soc_max_exist == 1) && (ap_ntc_exist == 1))
|
||||
version = TZ_MAP_V2;
|
||||
else if ((soc_max_exist == 1) && (ap_ntc_exist == 0))
|
||||
version = TZ_MAP_V3;
|
||||
else
|
||||
version = TZ_MAP_LEGANCY;
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
void ThermalHelper::init_tz_path() {
|
||||
|
||||
if (tz_map_version == TZ_MAP_LEGANCY)
|
||||
init_tz_path_v1();
|
||||
else if (tz_map_version == TZ_MAP_V2)
|
||||
init_tz_path_v2();
|
||||
else if (tz_map_version == TZ_MAP_V3)
|
||||
init_tz_path_v3();
|
||||
get_tz_map();
|
||||
}
|
||||
|
||||
void ThermalHelper::init_tz_path_v1() {
|
||||
char temp_path[TZPATH_LENGTH];
|
||||
char buf[TZNAME_SZ];
|
||||
int fd = -1;
|
||||
int read_len = 0;
|
||||
int i = 0;
|
||||
int r;
|
||||
|
||||
/*initial tz_data*/
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
for (int k = 0; k < MAX_MUTI_TZ_NUM; ++k)
|
||||
tz_data[j].tz_idx[k] = -1;
|
||||
}
|
||||
thermal_zone_num = 0;
|
||||
|
||||
while(1) {
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", i);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ALOGW("%s:find out tz path", __func__);
|
||||
thermal_zone_num = i;
|
||||
break;
|
||||
} else {
|
||||
read_len = read(fd, buf, TZNAME_SZ);
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
if (std::strncmp(buf, tz_data_v1[j].tzName, strlen(tz_data_v1[j].tzName)) == 0) {
|
||||
tz_data_v1[j].tz_idx[0] = i;
|
||||
ALOGW("tz_data_v1[%d].tz_idx:%d",j,i);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ThermalHelper::init_tz_path_v2() {
|
||||
char temp_path[TZPATH_LENGTH];
|
||||
char buf[TZNAME_SZ];
|
||||
int fd = -1;
|
||||
int read_len = 0;
|
||||
int i = 0;
|
||||
int r;
|
||||
|
||||
/*initial tz_data*/
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
for (int k = 0; k < MAX_MUTI_TZ_NUM; ++k)
|
||||
tz_data[j].tz_idx[k] = -1;
|
||||
tz_data_v2[j].tz_idx[0] = -1;
|
||||
}
|
||||
thermal_zone_num = 0;
|
||||
|
||||
while(1) {
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", i);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ALOGW("%s:find out tz path", __func__);
|
||||
thermal_zone_num = i;
|
||||
break;
|
||||
} else {
|
||||
read_len = read(fd, buf, TZNAME_SZ);
|
||||
for (int j = 0; j < TZ_DATA_NUM_MAX; ++j) {
|
||||
if (tz_data_v2[j].tz_idx[0] != -1)
|
||||
continue;
|
||||
if (std::strncmp(buf, tz_data_v2[j].tzName, strlen(tz_data_v2[j].tzName)) == 0) {
|
||||
tz_data_v2[j].tz_idx[0] = i;
|
||||
ALOGW("tz_data_v2[%d].tz_idx:%d",j,i);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ThermalHelper::init_tz_path_v3() {
|
||||
char temp_path[TZPATH_LENGTH];
|
||||
char buf[TZNAME_SZ];
|
||||
int fd = -1;
|
||||
int read_len = 0;
|
||||
int i = 0;
|
||||
int r;
|
||||
|
||||
/*initial tz_data*/
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
for (int k = 0; k < MAX_MUTI_TZ_NUM; ++k)
|
||||
tz_data[j].tz_idx[k] = -1;
|
||||
tz_data_v3[j].tz_idx[0] = -1;
|
||||
}
|
||||
thermal_zone_num = 0;
|
||||
|
||||
while(1) {
|
||||
r = snprintf(temp_path, TZPATH_LENGTH, TZPATH_PREFIX"%d/type", i);
|
||||
if (r < 0) {
|
||||
ALOGW("%s: snprintf fail: %d", __func__, r);
|
||||
}
|
||||
fd = open(temp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ALOGW("%s:find out tz path", __func__);
|
||||
thermal_zone_num = i;
|
||||
break;
|
||||
} else {
|
||||
read_len = read(fd, buf, TZNAME_SZ);
|
||||
for (int j = 0; j < TZ_DATA_NUM_MAX; ++j) {
|
||||
if (tz_data_v3[j].tz_idx[0] != -1)
|
||||
continue;
|
||||
if (std::strncmp(buf, tz_data_v3[j].tzName, strlen(tz_data_v3[j].tzName)) == 0) {
|
||||
tz_data_v3[j].tz_idx[0] = i;
|
||||
ALOGW("tz_data_v3[%d].tz_idx:%d",j,i);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// This is called in the different thread context and will update sensor_status
|
||||
// uevent_sensors is the set of sensors which trigger uevent from thermal core driver.
|
||||
bool ThermalHelper::thermalWatcherCallbackFunc(const std::set<std::string> &uevent_sensors) {
|
||||
std::vector<Temperature_2_0> temps;
|
||||
bool thermal_triggered = false;
|
||||
Temperature_2_0 temp;
|
||||
|
||||
if (uevent_sensors.size() != 0) {
|
||||
// writer lock
|
||||
std::unique_lock<std::mutex> _lock(sensor_status_map_mutex_);
|
||||
for (const auto &name : uevent_sensors) {
|
||||
for (int i = 0; i < TT_MAX; i++) {
|
||||
if (strncmp(name.c_str(), tz_data[i].label, strlen(tz_data[i].label)) == 0) {
|
||||
if (!is_tz_path_valided(i))
|
||||
init_tz_path();
|
||||
if (read_temperature(i,&temp))
|
||||
temps.push_back(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
thermal_triggered = true;
|
||||
}
|
||||
if (!temps.empty() && cb_) {
|
||||
cb_(temps);
|
||||
}
|
||||
|
||||
return thermal_triggered;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
120
hidl/thermal/thermal_helper.h
Normal file
120
hidl/thermal/thermal_helper.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of The Linux Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/thermal/2.0/IThermal.h>
|
||||
#include "thermal_watcher.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::hidl_vec;
|
||||
using ::android::hardware::thermal::V1_0::CpuUsage;
|
||||
using ::android::hardware::thermal::V2_0::CoolingType;
|
||||
using ::android::hardware::thermal::V2_0::IThermal;
|
||||
using CoolingDevice_1_0 = ::android::hardware::thermal::V1_0::CoolingDevice;
|
||||
using CoolingDevice_2_0 = ::android::hardware::thermal::V2_0::CoolingDevice;
|
||||
using Temperature_1_0 = ::android::hardware::thermal::V1_0::Temperature;
|
||||
using Temperature_2_0 = ::android::hardware::thermal::V2_0::Temperature;
|
||||
using TemperatureType_1_0 = ::android::hardware::thermal::V1_0::TemperatureType;
|
||||
using TemperatureType_2_0 = ::android::hardware::thermal::V2_0::TemperatureType;
|
||||
using ::android::hardware::thermal::V2_0::TemperatureThreshold;
|
||||
using ::android::hardware::thermal::V2_0::ThrottlingSeverity;
|
||||
|
||||
using NotificationCallback = std::function<void(const std::vector<Temperature_2_0> &temps)>;
|
||||
using NotificationTime = std::chrono::time_point<std::chrono::steady_clock>;
|
||||
|
||||
struct SensorStatus {
|
||||
ThrottlingSeverity severity;
|
||||
ThrottlingSeverity prev_hot_severity;
|
||||
ThrottlingSeverity prev_cold_severity;
|
||||
};
|
||||
|
||||
class ThermalHelper {
|
||||
public:
|
||||
ThermalHelper(const NotificationCallback &cb);
|
||||
~ThermalHelper() = default;
|
||||
// Dissallow copy and assign.
|
||||
ThermalHelper(const ThermalHelper &) = delete;
|
||||
void operator=(const ThermalHelper &) = delete;
|
||||
bool isInitializedOk() const { return is_initialized_; }
|
||||
ThrottlingSeverity getSeverityFromThresholds(float value, TemperatureType_2_0 type);
|
||||
bool fillCpuUsages(hidl_vec<CpuUsage> *cpu_usages);
|
||||
bool fill_temperatures_1_0(hidl_vec<Temperature_1_0> *temperatures);
|
||||
bool fill_temperatures(bool filterType, hidl_vec<Temperature_2_0> *temperatures, TemperatureType_2_0 type);
|
||||
bool fill_thresholds(bool filterType, hidl_vec<TemperatureThreshold> *Threshold, TemperatureType_2_0 type);
|
||||
bool fill_cooling_devices(bool filterType, std::vector<CoolingDevice_2_0> *CoolingDevice, CoolingType type);
|
||||
void init_tz_path(void);
|
||||
void init_tz_path_v1(void);
|
||||
void init_tz_path_v2(void);
|
||||
void init_tz_path_v3(void);
|
||||
void get_tz_map(void);
|
||||
int get_tz_map_version(void);
|
||||
float get_max_temp(int type);
|
||||
bool init_cl_path(void);
|
||||
bool read_temperature(int type, Temperature_1_0 *ret_temp);
|
||||
bool read_temperature(int type, Temperature_2_0 *ret_temp);
|
||||
int get_tz_num() const { return thermal_zone_num; };
|
||||
int get_cooling_num() const { return cooling_device_num; }
|
||||
bool is_tz_path_valided(int type);
|
||||
bool is_cooling_path_valided();
|
||||
|
||||
private:
|
||||
// For thermal_watcher_'s polling thread
|
||||
bool thermalWatcherCallbackFunc(const std::set<std::string> &uevent_sensors);
|
||||
sp<ThermalWatcher> thermal_watcher_;
|
||||
bool is_initialized_;
|
||||
const NotificationCallback cb_;
|
||||
|
||||
mutable std::mutex sensor_status_map_mutex_;
|
||||
std::map<std::string, SensorStatus> sensor_status_map_;
|
||||
int thermal_zone_num;
|
||||
int cooling_device_num;
|
||||
int tz_map_version;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
1322
hidl/thermal/thermal_map_table.h
Normal file
1322
hidl/thermal/thermal_map_table.h
Normal file
File diff suppressed because it is too large
Load Diff
155
hidl/thermal/thermal_map_table_type.h
Normal file
155
hidl/thermal/thermal_map_table_type.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <float.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
#include <hardware/thermal.h>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/thermal/2.0/IThermal.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::hidl_vec;
|
||||
using ::android::hardware::thermal::V1_0::CpuUsage;
|
||||
using ::android::hardware::thermal::V2_0::CoolingType;
|
||||
using ::android::hardware::thermal::V2_0::IThermal;
|
||||
using ::android::hardware::thermal::V2_0::TemperatureThreshold;
|
||||
using ::android::hardware::thermal::V2_0::TemperatureType;
|
||||
using ::android::hardware::thermal::V2_0::ThrottlingSeverity;
|
||||
|
||||
using CoolingDevice_1_0 = ::android::hardware::thermal::V1_0::CoolingDevice;
|
||||
using CoolingDevice_2_0 = ::android::hardware::thermal::V2_0::CoolingDevice;
|
||||
using Temperature_1_0 = ::android::hardware::thermal::V1_0::Temperature;
|
||||
using Temperature_2_0 = ::android::hardware::thermal::V2_0::Temperature;
|
||||
using TemperatureType_1_0 = ::android::hardware::thermal::V1_0::TemperatureType;
|
||||
using TemperatureType_2_0 = ::android::hardware::thermal::V2_0::TemperatureType;
|
||||
|
||||
#define CPU_USAGE_FILE "/proc/stat"
|
||||
#define CORENUM_PATH "/sys/devices/system/cpu/possible"
|
||||
|
||||
#define TZPATH_LENGTH 40
|
||||
#define TZPATH_PREFIX "/sys/class/thermal/thermal_zone"
|
||||
#define TZNAME_SZ 20
|
||||
|
||||
#define CDPATH_LENGTH 50
|
||||
#define CDPATH_PREFIX "/sys/class/thermal/cooling_device"
|
||||
#define CDNAME_SZ 25
|
||||
|
||||
#define CPU_TZ_NAME "mtktscpu"
|
||||
#define GPU_TZ_NAME "mtktscpu"
|
||||
#define BATTERY_TZ_NAME "mtktsbattery"
|
||||
#define SKIN_TZ_NAME "mtktsAP"
|
||||
#define USB_PORT_TZ_NAME "notsupport"
|
||||
#define POWER_AMPLIFIER_TZ_NAME "mtktsbtsmdpa"
|
||||
#define BCL_VOLTAGE_TZ_NAME "notsupport"
|
||||
#define BCL_CURRENT_TZ_NAME "notsupport"
|
||||
#define BCL_PERCENTAGE_TZ_NAME "notsupport"
|
||||
#define NPU_TZ_NAME "mtktscpu"
|
||||
|
||||
#define MAX_MUTI_TZ_NUM 5
|
||||
#define INVALID_TEMP -274000
|
||||
|
||||
enum TempType {
|
||||
TT_UNKNOWN = -1,
|
||||
TT_CPU = 0,
|
||||
TT_GPU = 1,
|
||||
TT_BATTERY = 2,
|
||||
TT_SKIN = 3,
|
||||
TT_USB_PORT = 4,
|
||||
TT_POWER_AMPLIFIER = 5,
|
||||
|
||||
/** Battery Charge Limit - virtual thermal sensors */
|
||||
TT_BCL_VOLTAGE = 6,
|
||||
TT_BCL_CURRENT = 7,
|
||||
TT_BCL_PERCENTAGE = 8,
|
||||
|
||||
/** Neural Processing Unit */
|
||||
TT_NPU = 9,
|
||||
TT_MAX = 10,
|
||||
};
|
||||
|
||||
|
||||
typedef struct _TZ_DATA {
|
||||
char tzName[TZNAME_SZ];
|
||||
const char label[TZNAME_SZ];
|
||||
int tz_idx[MAX_MUTI_TZ_NUM];
|
||||
int muti_tz_num;
|
||||
} TZ_DATA;
|
||||
|
||||
|
||||
#define MAX_COOLING 140
|
||||
|
||||
typedef struct _COOLING_DATA {
|
||||
CoolingDevice_2_0 cl_2_0;
|
||||
int cl_idx; /* /sys/class/thermal/cooling_device{$cl_idx} */
|
||||
} COOLING_DATA;
|
||||
|
||||
/** Device cooling device types */
|
||||
enum coolingType {
|
||||
CT_UNKNOWN = -1,
|
||||
CT_FAN = 0,
|
||||
CT_BATTERY = 1,
|
||||
CT_CPU = 2,
|
||||
CT_GPU = 3,
|
||||
CT_MODEM = 4,
|
||||
CT_NPU = 5,
|
||||
CT_COMPONENT = 6,
|
||||
CT_MAX = 7,
|
||||
};
|
||||
|
||||
/** tz map version */
|
||||
enum tz_version {
|
||||
TZ_MAP_UNKNOWN = 0,
|
||||
TZ_MAP_LEGANCY = 1,
|
||||
TZ_MAP_V2 = 2,
|
||||
TZ_MAP_V3= 3,
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
331
hidl/thermal/thermal_watcher.cpp
Normal file
331
hidl/thermal/thermal_watcher.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <cutils/uevent.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include "thermal_watcher.h"
|
||||
#include "thermal_map_table_type.h"
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <cutils/sockets.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
|
||||
#define THERMAL_HAL_SOCKET_NAME "thermal_hal_socket"
|
||||
#define THERMAL_HAL_SOCKET_IDENTIFY_WORD "TYPE"
|
||||
#define BUFFER_SIZE (128)
|
||||
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using std::chrono_literals::operator""ms;
|
||||
extern TZ_DATA tz_data[TT_MAX];
|
||||
extern TemperatureThreshold kMtkTempThreshold[TT_MAX];
|
||||
|
||||
static int create_socket_server(void)
|
||||
{
|
||||
int ret, socket_fd;
|
||||
|
||||
socket_fd = android_get_control_socket(THERMAL_HAL_SOCKET_NAME);
|
||||
if (socket_fd == -1) {
|
||||
ALOGE("Failed to create a local socket\n");
|
||||
return -1;
|
||||
}
|
||||
ret = listen(socket_fd, 20);
|
||||
if (ret == -1) {
|
||||
ALOGE("Failed to listen socket\n");
|
||||
close(socket_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return socket_fd;
|
||||
}
|
||||
|
||||
void ThermalWatcher::initThermalWatcher(int tz_version) {
|
||||
|
||||
if (tz_version == TZ_MAP_LEGANCY)
|
||||
event_fd_.reset((TEMP_FAILURE_RETRY(uevent_open_socket(64 * 1024, true))));
|
||||
else
|
||||
event_fd_.reset((TEMP_FAILURE_RETRY(create_socket_server())));
|
||||
|
||||
if (event_fd_.get() < 0) {
|
||||
LOG(ERROR) << "failed to open thermal hal socket";
|
||||
is_polling_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
fcntl(event_fd_, F_SETFL, O_NONBLOCK);
|
||||
|
||||
looper_->addFd(event_fd_.get(), 0, Looper::EVENT_INPUT, nullptr, nullptr);
|
||||
is_polling_ = false;
|
||||
thermal_triggered_ = true;
|
||||
tz_map_version = tz_version;
|
||||
}
|
||||
|
||||
bool ThermalWatcher::startThermalWatcher() {
|
||||
if (cb_) {
|
||||
auto ret = this->run("ThermalWatcherThread", PRIORITY_HIGHEST);
|
||||
if (ret != NO_ERROR) {
|
||||
LOG(ERROR) << "ThermalWatcherThread start fail";
|
||||
return false;
|
||||
} else {
|
||||
LOG(INFO) << "ThermalWatcherThread started";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ThermalWatcher::parseMsg(std::set<std::string> *sensors_set) {
|
||||
bool thermal_event = false;
|
||||
bool thermal_update = false;
|
||||
char *cp;
|
||||
int ret, client_socket;
|
||||
char buffer[BUFFER_SIZE];
|
||||
|
||||
while (true) {
|
||||
client_socket = accept(event_fd_.get(), NULL, NULL);
|
||||
if (client_socket == -1) {
|
||||
LOG(INFO) << "Wait to accept a connection";
|
||||
break;
|
||||
}
|
||||
|
||||
ret = recv(client_socket, buffer, BUFFER_SIZE,0);
|
||||
if (ret == -1) {
|
||||
LOG(ERROR) << "Socket recv failed";
|
||||
} else {
|
||||
if (ret < BUFFER_SIZE)
|
||||
buffer[ret] = '\0';
|
||||
else
|
||||
buffer[ret - 1] = '\0';
|
||||
|
||||
ALOGW("%s: Get from client %s", __func__, buffer);
|
||||
cp = buffer;
|
||||
while (*cp) {
|
||||
ret = strncmp(cp, THERMAL_HAL_SOCKET_IDENTIFY_WORD, 4);
|
||||
if (ret != 0){
|
||||
LOG(ERROR) << "Message format error\n";
|
||||
break;
|
||||
}
|
||||
std::string uevent = cp;
|
||||
if (uevent.find("TYPE=") == 0) {
|
||||
if (uevent.find("TYPE=thermal_hal_notify") != std::string::npos) {
|
||||
thermal_event = true;
|
||||
} else if (uevent.find("TYPE=thermal_hal_update") != std::string::npos) {
|
||||
thermal_update = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (thermal_event) {
|
||||
auto start_pos = uevent.find("NAME=");
|
||||
if (start_pos != std::string::npos) {
|
||||
start_pos += 5;
|
||||
std::string name = uevent.substr(start_pos);
|
||||
ALOGW("%s:name.c_str():%s", __func__, name.c_str());
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
if (strncmp(name.c_str(), tz_data[j].label, strlen(tz_data[j].label)) == 0) {
|
||||
ALOGW("%s:tz notify:%s", __func__, tz_data[j].label);
|
||||
sensors_set->insert(name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (thermal_update) {
|
||||
auto start_pos = uevent.find("NAME=");
|
||||
auto threshold_pos = uevent.find("THRESHOLD=");
|
||||
auto critical_pos = uevent.find("CRITICAL=");
|
||||
auto emerency_pos = uevent.find("EMERGENCY=");
|
||||
auto shutdown_pos = uevent.find("SHUTDOWN=");
|
||||
if (start_pos != std::string::npos && threshold_pos != std::string::npos) {
|
||||
start_pos += 5;
|
||||
threshold_pos += 10;
|
||||
std::string name = uevent.substr(start_pos);
|
||||
std::string threshold = uevent.substr(threshold_pos);
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
if (strncmp(name.c_str(), kMtkTempThreshold[j].name.c_str(), strlen(kMtkTempThreshold[j].name.c_str())) == 0) {
|
||||
kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::SEVERE)] = std::stoi(threshold);
|
||||
LOG(INFO) << "thermal update "
|
||||
<< " name: " << kMtkTempThreshold[j].name
|
||||
<< " hotThrottlingThresholds: " << kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::SEVERE)];
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (start_pos != std::string::npos && critical_pos != std::string::npos) {
|
||||
start_pos += 5;
|
||||
critical_pos += 9;
|
||||
std::string name = uevent.substr(start_pos);
|
||||
std::string threshold = uevent.substr(critical_pos);
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
if (strncmp(name.c_str(), kMtkTempThreshold[j].name.c_str(), strlen(kMtkTempThreshold[j].name.c_str())) == 0) {
|
||||
kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::CRITICAL)] = std::stoi(threshold);
|
||||
LOG(INFO) << "thermal update "
|
||||
<< " name: " << kMtkTempThreshold[j].name
|
||||
<< " hotThrottlingThresholds: " << kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::CRITICAL)];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (start_pos != std::string::npos && emerency_pos != std::string::npos) {
|
||||
start_pos += 5;
|
||||
emerency_pos += 10;
|
||||
std::string name = uevent.substr(start_pos);
|
||||
std::string threshold = uevent.substr(emerency_pos);
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
if (strncmp(name.c_str(), kMtkTempThreshold[j].name.c_str(), strlen(kMtkTempThreshold[j].name.c_str())) == 0) {
|
||||
kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::EMERGENCY)] = std::stoi(threshold);
|
||||
LOG(INFO) << "thermal update "
|
||||
<< " name: " << kMtkTempThreshold[j].name
|
||||
<< " hotThrottlingThresholds: " << kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::EMERGENCY)];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (start_pos != std::string::npos && shutdown_pos != std::string::npos) {
|
||||
start_pos += 5;
|
||||
shutdown_pos += 9;
|
||||
std::string name = uevent.substr(start_pos);
|
||||
std::string threshold = uevent.substr(shutdown_pos);
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
if (strncmp(name.c_str(), kMtkTempThreshold[j].name.c_str(), strlen(kMtkTempThreshold[j].name.c_str())) == 0) {
|
||||
kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::SHUTDOWN)] = std::stoi(threshold);
|
||||
LOG(INFO) << "thermal update "
|
||||
<< " name: " << kMtkTempThreshold[j].name
|
||||
<< " hotThrottlingThresholds: " << kMtkTempThreshold[j].hotThrottlingThresholds[static_cast<size_t>(ThrottlingSeverity::SHUTDOWN)];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
close(client_socket);
|
||||
}
|
||||
|
||||
}
|
||||
void ThermalWatcher::parseUevent(std::set<std::string> *sensors_set) {
|
||||
bool thermal_event = false;
|
||||
constexpr int kUeventMsgLen = 2048;
|
||||
char msg[kUeventMsgLen + 2];
|
||||
char *cp;
|
||||
|
||||
while (true) {
|
||||
int n = uevent_kernel_multicast_recv(event_fd_.get(), msg, kUeventMsgLen);
|
||||
if (n <= 0) {
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
LOG(ERROR) << "Error reading from Uevent Fd";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (n >= kUeventMsgLen) {
|
||||
LOG(ERROR) << "Uevent overflowed buffer, discarding";
|
||||
continue;
|
||||
}
|
||||
|
||||
msg[n] = '\0';
|
||||
msg[n + 1] = '\0';
|
||||
|
||||
cp = msg;
|
||||
while (*cp) {
|
||||
std::string uevent = cp;
|
||||
if (!thermal_event) {
|
||||
if (uevent.find("SUBSYSTEM=") == 0) {
|
||||
if (uevent.find("SUBSYSTEM=thermal") != std::string::npos) {
|
||||
thermal_event = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto start_pos = uevent.find("NAME=");
|
||||
if (start_pos != std::string::npos) {
|
||||
start_pos += 5;
|
||||
std::string name = uevent.substr(start_pos);
|
||||
for (int j = 0; j < TT_MAX; ++j) {
|
||||
if (strncmp(name.c_str(), tz_data[j].label, strlen(tz_data[j].label)) == 0) {
|
||||
sensors_set->insert(name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (*cp++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void ThermalWatcher::wake() {
|
||||
looper_->wake();
|
||||
}
|
||||
|
||||
bool ThermalWatcher::threadLoop() {
|
||||
// Polling interval 2s
|
||||
static constexpr int kMinPollIntervalMs = 2000;
|
||||
// Max event timeout 5mins
|
||||
static constexpr int keventPollTimeoutMs = 300000;
|
||||
int fd;
|
||||
std::set<std::string> sensors;
|
||||
|
||||
int timeout = (thermal_triggered_ || is_polling_) ? kMinPollIntervalMs : keventPollTimeoutMs;
|
||||
if (looper_->pollOnce(timeout, &fd, nullptr, nullptr) >= 0) {
|
||||
if (fd != event_fd_.get()) {
|
||||
return true;
|
||||
}
|
||||
if (tz_map_version == TZ_MAP_LEGANCY)
|
||||
parseUevent(&sensors);
|
||||
else
|
||||
parseMsg(&sensors);
|
||||
// Ignore cb_ if uevent is not from monitored sensors
|
||||
if (sensors.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
thermal_triggered_ = cb_(sensors);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
95
hidl/thermal/thermal_watcher.h
Normal file
95
hidl/thermal/thermal_watcher.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <utils/Looper.h>
|
||||
#include <utils/Thread.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using android::base::unique_fd;
|
||||
using WatcherCallback = std::function<bool(const std::set<std::string> &name)>;
|
||||
|
||||
// A helper class for monitoring thermal files changes.
|
||||
class ThermalWatcher : public ::android::Thread {
|
||||
public:
|
||||
ThermalWatcher(const WatcherCallback &cb)
|
||||
: Thread(false), cb_(cb), looper_(new Looper(true)) {}
|
||||
~ThermalWatcher() = default;
|
||||
|
||||
// Disallow copy and assign.
|
||||
ThermalWatcher(const ThermalWatcher &) = delete;
|
||||
void operator=(const ThermalWatcher &) = delete;
|
||||
|
||||
// Start the thread and return true if it succeeds.
|
||||
bool startThermalWatcher();
|
||||
// init uevent socket
|
||||
void initThermalWatcher(int tz_version);
|
||||
// Wake up the looper thus the worker thread, immediately. This can be called
|
||||
// in any thread.
|
||||
void wake();
|
||||
|
||||
private:
|
||||
// The work done by the watcher thread. This will use inotify to check for
|
||||
// modifications to the files to watch. If any modification is seen this
|
||||
// will callback the registered function with the new data read from the
|
||||
// modified file.
|
||||
bool threadLoop() override;
|
||||
|
||||
// Parse uevent message or socket message
|
||||
void parseUevent(std::set<std::string> *sensors_set);
|
||||
void parseMsg(std::set<std::string> *sensors_set);
|
||||
|
||||
// The callback function. Called whenever thermal uevent is seen.
|
||||
// The function passed in should expect a string in the form (type).
|
||||
// Where type is the name of the thermal zone that trigger a uevent notification.
|
||||
// Callback will return thermal trigger status for next polling decision.
|
||||
const WatcherCallback cb_;
|
||||
|
||||
sp<Looper> looper_;
|
||||
|
||||
// listen thermal info from theraml core via thermal hal socket
|
||||
// uevent socket registration for legancy tz map
|
||||
android::base::unique_fd event_fd_;
|
||||
// Flag to point out if any sensor across the first threshold.
|
||||
bool thermal_triggered_;
|
||||
// Flag to point out if device can support uevent notify.
|
||||
bool is_polling_;
|
||||
int tz_map_version;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
6
ossi.mk
6
ossi.mk
@@ -376,9 +376,7 @@ PRODUCT_COPY_FILES += \
|
||||
$(call inherit-product, hardware/oplus/power-libperfmgr/power-libperfmgr.mk)
|
||||
|
||||
PRODUCT_PACKAGES += \
|
||||
vendor.mediatek.hardware.mtkpower@1.2-service.stub \
|
||||
libmtkperf_client_vendor \
|
||||
libmtkperf_client
|
||||
vendor.mediatek.hardware.mtkpower@1.2-service.stub
|
||||
|
||||
PRODUCT_PACKAGES += \
|
||||
android.hardware.power@1.2.vendor \
|
||||
@@ -500,7 +498,7 @@ PRODUCT_PACKAGES += \
|
||||
|
||||
# USB
|
||||
PRODUCT_PACKAGES += \
|
||||
android.hardware.usb@1.3-service-mediatekv2
|
||||
android.hardware.usb-service.mediatek
|
||||
|
||||
# Vibrator
|
||||
PRODUCT_PACKAGES += \
|
||||
|
||||
Reference in New Issue
Block a user