1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "thermal_service_subscriber.h"
17
18 #include <functional>
19
20 #include "string_operation.h"
21 #include "thermal_service.h"
22 #include "thermal_common.h"
23 #include "constants.h"
24 namespace OHOS {
25 namespace PowerMgr {
26 namespace {
27 const int32_t SEC_MIN_NUM = 60;
28 const int32_t THERMAL_UPDATE_PERIOD = -5;
29 }
ThermalServiceSubscriber()30 ThermalServiceSubscriber::ThermalServiceSubscriber() { }
31
Init()32 bool ThermalServiceSubscriber::Init()
33 {
34 auto tms = ThermalService::GetInstance();
35 historyCount_ = tms->GetBaseinfoObj()->GetHistoryTempCount();
36 uint32_t riseRateCount = tms->GetBaseinfoObj()->GetRiseRateCount();
37 rateCount_ = riseRateCount <= 0 ? rateCount_ : riseRateCount;
38 return true;
39 }
40
OnTemperatureChanged(TypeTempMap typeTempMap)41 void ThermalServiceSubscriber::OnTemperatureChanged(TypeTempMap typeTempMap)
42 {
43 std::lock_guard<std::mutex> lock(mutex_);
44 if (typeTempMap.empty()) {
45 THERMAL_HILOGE(COMP_SVC, "failed to get sensor info: %{public}zu", typeTempMap.size());
46 return;
47 }
48
49 if (!typeTempMap_.empty()) {
50 typeTempMap_.clear();
51 }
52
53 for (auto it : typeTempMap) {
54 typeTempMap_[it.first] = it.second;
55 }
56 auto tms = ThermalService::GetInstance();
57 tms->GetSensorInfo()->SetTypeTempMap(typeTempMap_);
58 tms->GetSensorInfo()->NotifyObserver();
59
60 SetHistoryTypeTempMap(typeTempMap_);
61 return;
62 }
63
SetHistoryTypeTempMap(TypeTempMap typeTempMap)64 void ThermalServiceSubscriber::SetHistoryTypeTempMap(TypeTempMap typeTempMap)
65 {
66 THERMAL_HILOGD(COMP_SVC, "SetHistoryTypeTempMap: historyCount_=%{public}d, rateCount_=%{public}d",
67 historyCount_, rateCount_);
68 if (historyCount_ <= 1) {
69 return;
70 }
71
72 for (auto itMap : typeTempMap) {
73 auto iter = typeHistoryMap_.find(itMap.first);
74 if (iter != typeHistoryMap_.end()) {
75 if (iter->second.size() >= historyCount_) {
76 iter->second.pop_back();
77 iter->second.push_front(itMap.second);
78 } else {
79 iter->second.push_front(itMap.second);
80 }
81 } else {
82 std::deque<int32_t> historyTempList;
83 historyTempList.push_front(itMap.second);
84 typeHistoryMap_.insert(std::make_pair(itMap.first, historyTempList));
85 }
86 }
87
88 for (auto history : typeHistoryMap_) {
89 const auto& item = history.second;
90 double rate = GetThermalRiseRate(item);
91
92 auto iter = sensorsRateMap_.find(history.first);
93 if (iter != sensorsRateMap_.end()) {
94 if (iter->second.size() >= rateCount_) {
95 iter->second.pop_front();
96 iter->second.push_back(rate);
97 } else {
98 iter->second.push_back(rate);
99 }
100 } else {
101 std::deque<double> historyRateList;
102 historyRateList.push_front(rate);
103 sensorsRateMap_.insert(std::make_pair(history.first, historyRateList));
104 }
105 }
106 }
107
GetThermalRiseRate(const std::deque<int32_t> & tempQueue)108 double ThermalServiceSubscriber::GetThermalRiseRate(const std::deque<int32_t> &tempQueue)
109 {
110 if (tempQueue.size() < historyCount_) {
111 return 0;
112 }
113 int32_t tempQueueSize = static_cast<int32_t>(tempQueue.size());
114
115 // yi: tempQueue[i]
116 int32_t time = 0; // xi
117 int32_t timeSum = 0; // sum of xi
118 int32_t tempSum = 0; // sum of yi
119 int32_t timeSquaredSum = 0; // sum of xi * xi
120 int32_t timeTempMultiplySum = 0; // sum of xi * yi
121
122 for (int32_t timeIndex = 0; timeIndex < tempQueueSize; timeIndex++) {
123 time = timeIndex * THERMAL_UPDATE_PERIOD;
124 timeSum += time;
125 tempSum += tempQueue.at(timeIndex);
126 timeSquaredSum += time * time;
127 timeTempMultiplySum += time * tempQueue.at(timeIndex);
128 THERMAL_HILOGD(COMP_SVC, "GetThermalRiseRate: timeIndex=%{private}u, value=%{private}d", timeIndex,
129 tempQueue.at(timeIndex));
130 }
131 int32_t calcTime = tempQueueSize * timeSquaredSum - timeSum * timeSum; // (n * sum(xi * xi)) - (sum(xi) * sum(xi))
132 if (calcTime == 0) {
133 return 0;
134 }
135 // (n * sum(xi * yi) - (sum(xi) * sum(yi))) / (n * sum(xi * xi)) - (sum(xi) * sum(xi))
136 double slopeRate = (double)(tempQueueSize * timeTempMultiplySum - timeSum * tempSum) / calcTime;
137
138 return slopeRate * SEC_MIN_NUM;
139 }
140 } // namespace PowerMgr
141 } // namespace OHOS
142