1 /*
2 * Copyright (c) 2022 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 "resources_subscriber_mgr.h"
17 #include "efficiency_resource_log.h"
18 #include "hisysevent.h"
19
20 namespace OHOS {
21 namespace BackgroundTaskMgr {
22 namespace {
23 const int32_t RESOURCE_TYPE_SHIFTS = 16; // 能效资源类型左移位数
24 }
ResourcesSubscriberMgr()25 ResourcesSubscriberMgr::ResourcesSubscriberMgr()
26 {
27 deathRecipient_ = new (std::nothrow) ObserverDeathRecipient();
28 }
29
~ResourcesSubscriberMgr()30 ResourcesSubscriberMgr::~ResourcesSubscriberMgr() {}
31
AddSubscriber(const sptr<IBackgroundTaskSubscriber> & subscriber)32 ErrCode ResourcesSubscriberMgr::AddSubscriber(const sptr<IBackgroundTaskSubscriber>& subscriber)
33 {
34 BGTASK_LOGD("ResourcesSubscriberMgr start subscriber");
35 if (subscriber == NULL) {
36 BGTASK_LOGI("subscriber is null");
37 return ERR_BGTASK_INVALID_PARAM;
38 }
39 auto remote = subscriber->AsObject();
40 if (remote == nullptr) {
41 BGTASK_LOGE("remote in subscriber is null");
42 return ERR_BGTASK_INVALID_PARAM;
43 }
44
45 if (deathRecipient_ == nullptr) {
46 BGTASK_LOGE("create death recipient failed");
47 return ERR_BGTASK_INVALID_PARAM;
48 }
49 std::lock_guard<std::mutex> subcriberLock(subscriberLock_);
50 auto subscriberIter = std::find_if(subscriberList_.begin(), subscriberList_.end(),
51 [&remote](const auto &subscriber) { return subscriber->AsObject() == remote; });
52 if (subscriberIter != subscriberList_.end()) {
53 BGTASK_LOGE("subscriber has already exist");
54 return ERR_BGTASK_OBJECT_EXISTS;
55 }
56
57 subscriberList_.emplace_back(subscriber);
58 remote->AddDeathRecipient(deathRecipient_);
59 BGTASK_LOGD("add resources to efficiency resources mgr succeed!"\
60 " suscriber efficient resources, list.size() is %{public}d",
61 static_cast<int32_t>(subscriberList_.size()));
62 return ERR_OK;
63 }
64
RemoveSubscriber(const sptr<IBackgroundTaskSubscriber> & subscriber)65 ErrCode ResourcesSubscriberMgr::RemoveSubscriber(const sptr<IBackgroundTaskSubscriber>& subscriber)
66 {
67 if (deathRecipient_ == nullptr) {
68 BGTASK_LOGE("deathRecipient is null");
69 return ERR_BGTASK_OBJECT_EXISTS;
70 }
71 if (subscriber == nullptr) {
72 BGTASK_LOGE("subscriber is null");
73 return ERR_BGTASK_INVALID_PARAM;
74 }
75 auto remote = subscriber->AsObject();
76 if (remote == nullptr) {
77 BGTASK_LOGE("apply efficiency resources failed, remote in subscriber is null");
78 return ERR_BGTASK_INVALID_PARAM;
79 }
80 std::lock_guard<std::mutex> subcriberLock(subscriberLock_);
81 auto findSuscriber = [&remote](const auto& subscriberList) {
82 return subscriberList->AsObject() == remote;
83 };
84 auto subscriberIter = std::find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber);
85 if (subscriberIter == subscriberList_.end()) {
86 BGTASK_LOGE("request subscriber is not exists");
87 return ERR_BGTASK_OBJECT_EXISTS;
88 }
89 subscriberList_.erase(subscriberIter);
90 remote->RemoveDeathRecipient(deathRecipient_);
91 BGTASK_LOGD("remove subscriber from efficiency resources succeed");
92 return ERR_OK;
93 }
94
OnResourceChanged(const std::shared_ptr<ResourceCallbackInfo> & callbackInfo,EfficiencyResourcesEventType type)95 void ResourcesSubscriberMgr::OnResourceChanged(const std::shared_ptr<ResourceCallbackInfo> &callbackInfo,
96 EfficiencyResourcesEventType type)
97 {
98 BGTASK_LOGD("start OnResourceChanged");
99 if (callbackInfo == nullptr) {
100 BGTASK_LOGW("ResourceCallbackInfo is null");
101 return;
102 }
103 std::lock_guard<std::mutex> subcriberLock(subscriberLock_);
104 if (subscriberList_.empty()) {
105 BGTASK_LOGW("Background Task Subscriber List is empty");
106 return;
107 }
108 HiSysEventResources(callbackInfo, type);
109 switch (type) {
110 case EfficiencyResourcesEventType::APP_RESOURCE_APPLY:
111 BGTASK_LOGD("start callback function of app resources application");
112 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
113 (*iter)->OnAppEfficiencyResourcesApply(callbackInfo);
114 }
115 break;
116 case EfficiencyResourcesEventType::RESOURCE_APPLY:
117 BGTASK_LOGD("start callback function of proc resources application");
118 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
119 (*iter)->OnProcEfficiencyResourcesApply(callbackInfo);
120 }
121 break;
122 case EfficiencyResourcesEventType::APP_RESOURCE_RESET:
123 BGTASK_LOGD("start callback function of app resources reset");
124 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
125 (*iter)->OnAppEfficiencyResourcesReset(callbackInfo);
126 }
127 break;
128 case EfficiencyResourcesEventType::RESOURCE_RESET:
129 BGTASK_LOGD("start callback function of proc resources reset");
130 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
131 (*iter)->OnProcEfficiencyResourcesReset(callbackInfo);
132 }
133 break;
134 }
135 BGTASK_LOGD("efficiency resources on resources changed function succeed");
136 }
137
HiSysEventResources(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,EfficiencyResourcesEventType type)138 void ResourcesSubscriberMgr::HiSysEventResources(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,
139 EfficiencyResourcesEventType type)
140 {
141 if (callbackInfo == nullptr) {
142 BGTASK_LOGE("ResourceCallbackInfo is null");
143 return;
144 }
145 switch (type) {
146 case EfficiencyResourcesEventType::APP_RESOURCE_APPLY:
147 HiSysEventSubmit(callbackInfo, HISYSEVENT_APP_RESOURCE_APPLY, "CONTINUOUS_TASK_APPLY");
148 break;
149 case EfficiencyResourcesEventType::RESOURCE_APPLY:
150 HiSysEventSubmit(callbackInfo, HISYSEVENT_RESOURCE_APPLY, "CONTINUOUS_TASK_APPLY");
151 break;
152 case EfficiencyResourcesEventType::APP_RESOURCE_RESET:
153 HiSysEventSubmit(callbackInfo, HISYSEVENT_APP_RESOURCE_RESET, "CONTINUOUS_TASK_CANCEL");
154 break;
155 case EfficiencyResourcesEventType::RESOURCE_RESET:
156 HiSysEventSubmit(callbackInfo, HISYSEVENT_RESOURCE_RESET, "CONTINUOUS_TASK_CANCEL");
157 break;
158 }
159 }
160
HiSysEventSubmit(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,int32_t hiSysEventType,const std::string & eventType)161 void ResourcesSubscriberMgr::HiSysEventSubmit(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,
162 int32_t hiSysEventType, const std::string &eventType)
163 {
164 uint32_t resourceType = callbackInfo->GetResourceNumber() << RESOURCE_TYPE_SHIFTS;
165 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, eventType.c_str(),
166 HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", callbackInfo->GetUid(),
167 "APP_PID", callbackInfo->GetPid(), "APP_NAME", callbackInfo->GetBundleName(),
168 "BGMODE", resourceType,
169 "UIABILITY_IDENTITY", hiSysEventType);
170 }
171
HandleSubscriberDeath(const wptr<IRemoteObject> & remote)172 void ResourcesSubscriberMgr::HandleSubscriberDeath(const wptr<IRemoteObject>& remote)
173 {
174 if (remote == nullptr) {
175 BGTASK_LOGE("suscriber death, remote in suscriber is null");
176 return;
177 }
178 sptr<IRemoteObject> proxy = remote.promote();
179 if (!proxy) {
180 BGTASK_LOGE("get remote proxy failed");
181 return;
182 }
183 std::lock_guard<std::mutex> subcriberLock(subscriberLock_);
184 auto findSuscriber = [&proxy](const auto& subscriber) {
185 return subscriber->AsObject() == proxy;
186 };
187 auto subscriberIter = std::find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber);
188 if (subscriberIter == subscriberList_.end()) {
189 BGTASK_LOGI("suscriber death, remote in suscriber not found");
190 return;
191 }
192 subscriberList_.erase(subscriberIter);
193 BGTASK_LOGD("suscriber death, remove it from list");
194 }
195
196
ObserverDeathRecipient()197 ObserverDeathRecipient::ObserverDeathRecipient() {}
198
~ObserverDeathRecipient()199 ObserverDeathRecipient::~ObserverDeathRecipient() {}
200
OnRemoteDied(const wptr<IRemoteObject> & remote)201 void ObserverDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
202 {
203 DelayedSingleton<ResourcesSubscriberMgr>::GetInstance()->HandleSubscriberDeath(remote);
204 }
205 } // namespace BackgroundTaskMgr
206 } // namespace OHOS