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