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(std::string value)63 void ActionThermalLevel::AddActionValue(std::string value)
64 {
65 if (value.empty()) {
66 return;
67 }
68 valueList_.push_back(static_cast<uint32_t>(strtol(value.c_str(), nullptr, STRTOL_FORMART_DEC)));
69 }
70
Execute()71 void ActionThermalLevel::Execute()
72 {
73 auto tms = ThermalService::GetInstance();
74 THERMAL_RETURN_IF (tms == nullptr);
75 int32_t value = GetActionValue();
76 if (value != lastValue_) {
77 LevelRequest(value);
78 WriteActionTriggeredHiSysEvent(enableEvent_, actionName_, value);
79 tms->GetObserver()->SetDecisionValue(actionName_, std::to_string(value));
80 lastValue_ = value;
81 THERMAL_HILOGD(COMP_SVC, "action execute: {%{public}s = %{public}u}", actionName_.c_str(), lastValue_);
82 }
83 valueList_.clear();
84 }
85
GetActionValue()86 int32_t ActionThermalLevel::GetActionValue()
87 {
88 uint32_t value = MIN_THERMAL_LEVEL;
89 if (!valueList_.empty()) {
90 if (isStrict_) {
91 value = *min_element(valueList_.begin(), valueList_.end());
92 } else {
93 value = *max_element(valueList_.begin(), valueList_.end());
94 }
95 }
96 return value;
97 }
98
GetThermalLevel()99 int32_t ActionThermalLevel::GetThermalLevel()
100 {
101 return lastValue_;
102 }
103
LevelRequest(int32_t level)104 void ActionThermalLevel::LevelRequest(int32_t level)
105 {
106 if (level > MAX_THERMAL_LEVEL) {
107 level = MAX_THERMAL_LEVEL;
108 }
109 if (level < MIN_THERMAL_LEVEL) {
110 level = MIN_THERMAL_LEVEL;
111 }
112 NotifyThermalLevelChanged(level);
113 }
114
SubscribeThermalLevelCallback(const sptr<IThermalLevelCallback> & callback)115 void ActionThermalLevel::SubscribeThermalLevelCallback(const sptr<IThermalLevelCallback>& callback)
116 {
117 std::lock_guard lock(mutex_);
118 THERMAL_RETURN_IF(callback == nullptr);
119 auto object = callback->AsObject();
120 THERMAL_RETURN_IF(object == nullptr);
121 auto retIt = thermalLevelListeners_.insert(callback);
122 if (retIt.second) {
123 object->AddDeathRecipient(thermalLevelCBDeathRecipient_);
124 callback->OnThermalLevelChanged(static_cast<ThermalLevel>(lastValue_));
125 }
126 THERMAL_HILOGI(COMP_SVC, "listeners.size=%{public}zu, insertOk=%{public}d",
127 thermalLevelListeners_.size(), retIt.second);
128 }
129
UnSubscribeThermalLevelCallback(const sptr<IThermalLevelCallback> & callback)130 void ActionThermalLevel::UnSubscribeThermalLevelCallback(const sptr<IThermalLevelCallback>& callback)
131 {
132 std::lock_guard lock(mutex_);
133 THERMAL_RETURN_IF(callback == nullptr);
134 auto object = callback->AsObject();
135 THERMAL_RETURN_IF(object == nullptr);
136 size_t eraseNum = thermalLevelListeners_.erase(callback);
137 if (eraseNum != 0) {
138 object->RemoveDeathRecipient(thermalLevelCBDeathRecipient_);
139 }
140 THERMAL_HILOGI(COMP_SVC, "listeners.size=%{public}zu, eraseNum=%{public}zu",
141 thermalLevelListeners_.size(), eraseNum);
142 }
143
OnRemoteDied(const wptr<IRemoteObject> & remote)144 void ActionThermalLevel::ThermalLevelCallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
145 {
146 if (remote == nullptr || remote.promote() == nullptr) {
147 return;
148 }
149 auto tms = ThermalService::GetInstance();
150 if (tms == nullptr) {
151 return;
152 }
153 sptr<IThermalLevelCallback> callback = iface_cast<IThermalLevelCallback>(remote.promote());
154 FFRTTask task = [tms, callback] { tms->UnSubscribeThermalLevelCallback(callback); };
155 FFRTUtils::SubmitTask(task);
156 }
157
NotifyThermalLevelChanged(int32_t level)158 void ActionThermalLevel::NotifyThermalLevelChanged(int32_t level)
159 {
160 THERMAL_HILOGI(COMP_SVC, "thermal level changed, new lev: %{public}d, old lev: %{public}d", level, lastValue_);
161
162 // Send Notification event
163 PublishLevelChangedEvents(ThermalCommonEventCode::CODE_THERMAL_LEVEL_CHANGED, level);
164
165 // Call back all level listeners
166 std::lock_guard lock(mutex_);
167 for (auto& listener : thermalLevelListeners_) {
168 listener->OnThermalLevelChanged(static_cast<ThermalLevel>(level));
169 }
170
171 // Notify thermal level change event to battery statistics
172 WriteLevelChangedHiSysEvent(enableEvent_, level);
173 }
174
PublishLevelChangedEvents(ThermalCommonEventCode code,int32_t level)175 bool ActionThermalLevel::PublishLevelChangedEvents(ThermalCommonEventCode code, int32_t level)
176 {
177 Want want;
178 want.SetParam(ToString(static_cast<int32_t>(code)), level);
179 want.SetAction(CommonEventSupport::COMMON_EVENT_THERMAL_LEVEL_CHANGED);
180 CommonEventData commonData;
181 commonData.SetWant(want);
182 CommonEventPublishInfo publishInfo;
183 publishInfo.SetOrdered(false);
184 if (!CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {
185 THERMAL_HILOGE(COMP_SVC, "failed to publish thermal level change event");
186 return false;
187 }
188 return true;
189 }
190 } // namespace PowerMgr
191 } // namespace OHOS
192