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