1 /*
2 * Copyright (c) 2021-2023 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 "action_thermal_level.h"
17
18 #include <common_event_data.h>
19 #include <common_event_manager.h>
20 #include <common_event_support.h>
21 #include <map>
22
23 #include "constants.h"
24 #include "thermal_hisysevent.h"
25 #include "thermal_service.h"
26 #include "thermal_common.h"
27 #include "ffrt_utils.h"
28
29 using namespace OHOS::AAFwk;
30 using namespace OHOS::EventFwk;
31 using namespace OHOS::HiviewDFX;
32
33 namespace OHOS {
34 namespace PowerMgr {
35 namespace {
36 constexpr int32_t MIN_THERMAL_LEVEL = static_cast<int32_t>(ThermalLevel::COOL);
37 constexpr int32_t MAX_THERMAL_LEVEL = static_cast<int32_t>(ThermalLevel::ESCAPE);
38 }
39 int32_t ActionThermalLevel::lastValue_ = INT_MIN;
40
ActionThermalLevel(const std::string & actionName)41 ActionThermalLevel::ActionThermalLevel(const std::string& actionName)
42 {
43 actionName_ = actionName;
44 }
45
InitParams(const std::string & params)46 void ActionThermalLevel::InitParams(const std::string& params)
47 {
48 if (thermalLevelCBDeathRecipient_ == nullptr) {
49 thermalLevelCBDeathRecipient_ = new ThermalLevelCallbackDeathRecipient();
50 }
51 }
52
SetStrict(bool enable)53 void ActionThermalLevel::SetStrict(bool enable)
54 {
55 isStrict_ = enable;
56 }
57
SetEnableEvent(bool enable)58 void ActionThermalLevel::SetEnableEvent(bool enable)
59 {
60 enableEvent_ = enable;
61 }
62
AddActionValue(uint32_t actionId,std::string value)63 void ActionThermalLevel::AddActionValue(uint32_t actionId, std::string value)
64 {
65 if (value.empty()) {
66 return;
67 }
68 if (actionId > 0) {
69 auto iter = policyActionMap_.find(actionId);
70 if (iter != policyActionMap_.end()) {
71 iter->second.uintDelayValue = static_cast<uint32_t>(static_cast<uint32_t>(strtol(value.c_str(),
72 nullptr, STRTOL_FORMART_DEC)));
73 }
74 } else {
75 valueList_.push_back(static_cast<uint32_t>(strtol(value.c_str(), nullptr, STRTOL_FORMART_DEC)));
76 }
77 }
78
ExecuteInner()79 void ActionThermalLevel::ExecuteInner()
80 {
81 auto tms = ThermalService::GetInstance();
82 THERMAL_RETURN_IF (tms == nullptr);
83 for (auto &policyAction : policyActionMap_) {
84 if (policyAction.second.isCompleted) {
85 valueList_.push_back(policyAction.second.uintDelayValue);
86 }
87 }
88
89 int32_t value = GetActionValue();
90 if (value != lastValue_) {
91 THERMAL_HILOGI(COMP_SVC, "thermal level changed, new lev: %{public}d, old lev: %{public}d", value, lastValue_);
92 lastValue_ = value;
93 LevelRequest(value);
94 WriteActionTriggeredHiSysEvent(enableEvent_, actionName_, value);
95 tms->GetObserver()->SetDecisionValue(actionName_, std::to_string(value));
96 THERMAL_HILOGD(COMP_SVC, "action execute: {%{public}s = %{public}u}", actionName_.c_str(), lastValue_);
97 }
98 valueList_.clear();
99 }
100
ResetActionValue()101 void ActionThermalLevel::ResetActionValue()
102 {
103 lastValue_ = INT_MIN;
104 }
105
GetActionValue()106 int32_t ActionThermalLevel::GetActionValue()
107 {
108 uint32_t value = MIN_THERMAL_LEVEL;
109 if (!valueList_.empty()) {
110 if (isStrict_) {
111 value = *min_element(valueList_.begin(), valueList_.end());
112 } else {
113 value = *max_element(valueList_.begin(), valueList_.end());
114 }
115 }
116 return value;
117 }
118
GetThermalLevel()119 int32_t ActionThermalLevel::GetThermalLevel()
120 {
121 return lastValue_;
122 }
123
LevelRequest(int32_t level)124 void ActionThermalLevel::LevelRequest(int32_t level)
125 {
126 if (level > MAX_THERMAL_LEVEL) {
127 level = MAX_THERMAL_LEVEL;
128 }
129 if (level < MIN_THERMAL_LEVEL) {
130 level = MIN_THERMAL_LEVEL;
131 }
132 NotifyThermalLevelChanged(level);
133 }
134
SubscribeThermalLevelCallback(const sptr<IThermalLevelCallback> & callback)135 void ActionThermalLevel::SubscribeThermalLevelCallback(const sptr<IThermalLevelCallback>& callback)
136 {
137 std::lock_guard lock(mutex_);
138 THERMAL_RETURN_IF(callback == nullptr);
139 auto object = callback->AsObject();
140 THERMAL_RETURN_IF(object == nullptr);
141 auto retIt = thermalLevelListeners_.insert(callback);
142 if (retIt.second) {
143 object->AddDeathRecipient(thermalLevelCBDeathRecipient_);
144 callback->OnThermalLevelChanged(static_cast<ThermalLevel>(lastValue_));
145 }
146 THERMAL_HILOGI(COMP_SVC, "listeners.size=%{public}zu, insertOk=%{public}d",
147 thermalLevelListeners_.size(), retIt.second);
148 }
149
UnSubscribeThermalLevelCallback(const sptr<IThermalLevelCallback> & callback)150 void ActionThermalLevel::UnSubscribeThermalLevelCallback(const sptr<IThermalLevelCallback>& callback)
151 {
152 std::lock_guard lock(mutex_);
153 THERMAL_RETURN_IF(callback == nullptr);
154 auto object = callback->AsObject();
155 THERMAL_RETURN_IF(object == nullptr);
156 size_t eraseNum = thermalLevelListeners_.erase(callback);
157 if (eraseNum != 0) {
158 object->RemoveDeathRecipient(thermalLevelCBDeathRecipient_);
159 }
160 THERMAL_HILOGI(COMP_SVC, "listeners.size=%{public}zu, eraseNum=%{public}zu",
161 thermalLevelListeners_.size(), eraseNum);
162 }
163
OnRemoteDied(const wptr<IRemoteObject> & remote)164 void ActionThermalLevel::ThermalLevelCallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
165 {
166 if (remote == nullptr || remote.promote() == nullptr) {
167 return;
168 }
169 auto tms = ThermalService::GetInstance();
170 if (tms == nullptr) {
171 return;
172 }
173 sptr<IThermalLevelCallback> callback = iface_cast<IThermalLevelCallback>(remote.promote());
174 FFRTTask task = [tms, callback] { tms->UnSubscribeThermalLevelCallback(callback); };
175 FFRTUtils::SubmitTask(task);
176 }
177
NotifyThermalLevelChanged(int32_t level)178 void ActionThermalLevel::NotifyThermalLevelChanged(int32_t level)
179 {
180 // Send Notification event
181 PublishLevelChangedEvents(ThermalCommonEventCode::CODE_THERMAL_LEVEL_CHANGED, level);
182
183 // Call back all level listeners
184 std::lock_guard lock(mutex_);
185 for (auto& listener : thermalLevelListeners_) {
186 listener->OnThermalLevelChanged(static_cast<ThermalLevel>(level));
187 }
188
189 // Notify thermal level change event to battery statistics
190 WriteLevelChangedHiSysEvent(enableEvent_, level);
191 }
192
PublishLevelChangedEvents(ThermalCommonEventCode code,int32_t level)193 bool ActionThermalLevel::PublishLevelChangedEvents(ThermalCommonEventCode code, int32_t level)
194 {
195 Want want;
196 want.SetParam(ToString(static_cast<int32_t>(code)), level);
197 want.SetAction(CommonEventSupport::COMMON_EVENT_THERMAL_LEVEL_CHANGED);
198 CommonEventData commonData;
199 commonData.SetWant(want);
200 CommonEventPublishInfo publishInfo;
201 publishInfo.SetOrdered(false);
202 if (!CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {
203 THERMAL_HILOGE(COMP_SVC, "failed to publish thermal level change event");
204 return false;
205 }
206 return true;
207 }
208 } // namespace PowerMgr
209 } // namespace OHOS
210