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