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