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 tms->GetObserver()->SetDecisionValue(actionName_, std::to_string(value));
95 THERMAL_HILOGD(COMP_SVC, "action execute: {%{public}s = %{public}u}", actionName_.c_str(), lastValue_);
96 }
97 valueList_.clear();
98 }
99
ResetActionValue()100 void ActionThermalLevel::ResetActionValue()
101 {
102 lastValue_ = INT_MIN;
103 }
104
GetActionValue()105 int32_t ActionThermalLevel::GetActionValue()
106 {
107 uint32_t value = MIN_THERMAL_LEVEL;
108 if (!valueList_.empty()) {
109 if (isStrict_) {
110 value = *min_element(valueList_.begin(), valueList_.end());
111 } else {
112 value = *max_element(valueList_.begin(), valueList_.end());
113 }
114 }
115 return value;
116 }
117
GetThermalLevel()118 int32_t ActionThermalLevel::GetThermalLevel()
119 {
120 return lastValue_;
121 }
122
LevelRequest(int32_t level)123 void ActionThermalLevel::LevelRequest(int32_t level)
124 {
125 if (level > MAX_THERMAL_LEVEL) {
126 level = MAX_THERMAL_LEVEL;
127 }
128 if (level < MIN_THERMAL_LEVEL) {
129 level = MIN_THERMAL_LEVEL;
130 }
131 NotifyThermalLevelChanged(level);
132 }
133
SubscribeThermalLevelCallback(const sptr<IThermalLevelCallback> & callback)134 void ActionThermalLevel::SubscribeThermalLevelCallback(const sptr<IThermalLevelCallback>& callback)
135 {
136 std::lock_guard lock(mutex_);
137 THERMAL_RETURN_IF(callback == nullptr);
138 auto object = callback->AsObject();
139 THERMAL_RETURN_IF(object == nullptr);
140 auto retIt = thermalLevelListeners_.insert(callback);
141 if (retIt.second) {
142 object->AddDeathRecipient(thermalLevelCBDeathRecipient_);
143 callback->OnThermalLevelChanged(static_cast<ThermalLevel>(lastValue_));
144 }
145 THERMAL_HILOGI(COMP_SVC, "listeners.size=%{public}zu, insertOk=%{public}d",
146 thermalLevelListeners_.size(), retIt.second);
147 }
148
UnSubscribeThermalLevelCallback(const sptr<IThermalLevelCallback> & callback)149 void ActionThermalLevel::UnSubscribeThermalLevelCallback(const sptr<IThermalLevelCallback>& callback)
150 {
151 std::lock_guard lock(mutex_);
152 THERMAL_RETURN_IF(callback == nullptr);
153 auto object = callback->AsObject();
154 THERMAL_RETURN_IF(object == nullptr);
155 size_t eraseNum = thermalLevelListeners_.erase(callback);
156 if (eraseNum != 0) {
157 object->RemoveDeathRecipient(thermalLevelCBDeathRecipient_);
158 }
159 THERMAL_HILOGI(COMP_SVC, "listeners.size=%{public}zu, eraseNum=%{public}zu",
160 thermalLevelListeners_.size(), eraseNum);
161 }
162
OnRemoteDied(const wptr<IRemoteObject> & remote)163 void ActionThermalLevel::ThermalLevelCallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
164 {
165 if (remote == nullptr || remote.promote() == nullptr) {
166 return;
167 }
168 auto tms = ThermalService::GetInstance();
169 if (tms == nullptr) {
170 return;
171 }
172 sptr<IThermalLevelCallback> callback = iface_cast<IThermalLevelCallback>(remote.promote());
173 FFRTTask task = [tms, callback] { tms->UnSubscribeThermalLevelCallback(callback); };
174 FFRTUtils::SubmitTask(task);
175 }
176
NotifyThermalLevelChanged(int32_t level)177 void ActionThermalLevel::NotifyThermalLevelChanged(int32_t level)
178 {
179 // Send Notification event
180 PublishLevelChangedEvents(ThermalCommonEventCode::CODE_THERMAL_LEVEL_CHANGED, level);
181
182 // Call back all level listeners
183 std::lock_guard lock(mutex_);
184 for (auto& listener : thermalLevelListeners_) {
185 listener->OnThermalLevelChanged(static_cast<ThermalLevel>(level));
186 }
187 }
188
PublishLevelChangedEvents(ThermalCommonEventCode code,int32_t level)189 bool ActionThermalLevel::PublishLevelChangedEvents(ThermalCommonEventCode code, int32_t level)
190 {
191 Want want;
192 want.SetParam(ToString(static_cast<int32_t>(code)), level);
193 want.SetAction(CommonEventSupport::COMMON_EVENT_THERMAL_LEVEL_CHANGED);
194 CommonEventData commonData;
195 commonData.SetWant(want);
196 CommonEventPublishInfo publishInfo;
197 publishInfo.SetOrdered(false);
198 if (!CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {
199 THERMAL_HILOGE(COMP_SVC, "failed to publish thermal level change event");
200 return false;
201 }
202 return true;
203 }
204 } // namespace PowerMgr
205 } // namespace OHOS
206