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 const ResourceCallbackInfo& callbackInfoRef = *callbackInfo;
110 switch (type) {
111 case EfficiencyResourcesEventType::APP_RESOURCE_APPLY:
112 BGTASK_LOGD("start callback function of app resources application");
113 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
114 (*iter)->OnAppEfficiencyResourcesApply(callbackInfoRef);
115 }
116 break;
117 case EfficiencyResourcesEventType::RESOURCE_APPLY:
118 BGTASK_LOGD("start callback function of proc resources application");
119 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
120 (*iter)->OnProcEfficiencyResourcesApply(callbackInfoRef);
121 }
122 break;
123 case EfficiencyResourcesEventType::APP_RESOURCE_RESET:
124 BGTASK_LOGD("start callback function of app resources reset");
125 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
126 (*iter)->OnAppEfficiencyResourcesReset(callbackInfoRef);
127 }
128 break;
129 case EfficiencyResourcesEventType::RESOURCE_RESET:
130 BGTASK_LOGD("start callback function of proc resources reset");
131 for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) {
132 (*iter)->OnProcEfficiencyResourcesReset(callbackInfoRef);
133 }
134 break;
135 }
136 BGTASK_LOGD("efficiency resources on resources changed function succeed");
137 }
138
HiSysEventResources(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,EfficiencyResourcesEventType type)139 void ResourcesSubscriberMgr::HiSysEventResources(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,
140 EfficiencyResourcesEventType type)
141 {
142 if (callbackInfo == nullptr) {
143 BGTASK_LOGE("ResourceCallbackInfo is null");
144 return;
145 }
146 switch (type) {
147 case EfficiencyResourcesEventType::APP_RESOURCE_APPLY:
148 HiSysEventSubmit(callbackInfo, HISYSEVENT_APP_RESOURCE_APPLY, "CONTINUOUS_TASK_APPLY");
149 break;
150 case EfficiencyResourcesEventType::RESOURCE_APPLY:
151 HiSysEventSubmit(callbackInfo, HISYSEVENT_RESOURCE_APPLY, "CONTINUOUS_TASK_APPLY");
152 break;
153 case EfficiencyResourcesEventType::APP_RESOURCE_RESET:
154 HiSysEventSubmit(callbackInfo, HISYSEVENT_APP_RESOURCE_RESET, "CONTINUOUS_TASK_CANCEL");
155 break;
156 case EfficiencyResourcesEventType::RESOURCE_RESET:
157 HiSysEventSubmit(callbackInfo, HISYSEVENT_RESOURCE_RESET, "CONTINUOUS_TASK_CANCEL");
158 break;
159 }
160 }
161
HiSysEventSubmit(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,int32_t hiSysEventType,const std::string & eventType)162 void ResourcesSubscriberMgr::HiSysEventSubmit(const std::shared_ptr<ResourceCallbackInfo> callbackInfo,
163 int32_t hiSysEventType, const std::string &eventType)
164 {
165 uint32_t resourceType = callbackInfo->GetResourceNumber() << RESOURCE_TYPE_SHIFTS;
166 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, eventType.c_str(),
167 HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", callbackInfo->GetUid(),
168 "APP_PID", callbackInfo->GetPid(), "APP_NAME", callbackInfo->GetBundleName(),
169 "BGMODE", resourceType,
170 "UIABILITY_IDENTITY", hiSysEventType);
171 }
172
HandleSubscriberDeath(const wptr<IRemoteObject> & remote)173 void ResourcesSubscriberMgr::HandleSubscriberDeath(const wptr<IRemoteObject>& remote)
174 {
175 if (remote == nullptr) {
176 BGTASK_LOGE("suscriber death, remote in suscriber is null");
177 return;
178 }
179 sptr<IRemoteObject> proxy = remote.promote();
180 if (!proxy) {
181 BGTASK_LOGE("get remote proxy failed");
182 return;
183 }
184 std::lock_guard<std::mutex> subcriberLock(subscriberLock_);
185 auto findSuscriber = [&proxy](const auto& subscriber) {
186 return subscriber->AsObject() == proxy;
187 };
188 auto subscriberIter = std::find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber);
189 if (subscriberIter == subscriberList_.end()) {
190 BGTASK_LOGI("suscriber death, remote in suscriber not found");
191 return;
192 }
193 subscriberList_.erase(subscriberIter);
194 BGTASK_LOGD("suscriber death, remove it from list");
195 }
196
197
ObserverDeathRecipient()198 ObserverDeathRecipient::ObserverDeathRecipient() {}
199
~ObserverDeathRecipient()200 ObserverDeathRecipient::~ObserverDeathRecipient() {}
201
OnRemoteDied(const wptr<IRemoteObject> & remote)202 void ObserverDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
203 {
204 DelayedSingleton<ResourcesSubscriberMgr>::GetInstance()->HandleSubscriberDeath(remote);
205 }
206 } // namespace BackgroundTaskMgr
207 } // namespace OHOS