/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "resources_subscriber_mgr.h" #include "efficiency_resource_log.h" #include "hisysevent.h" namespace OHOS { namespace BackgroundTaskMgr { namespace { const int32_t RESOURCE_TYPE_SHIFTS = 16; // 能效资源类型左移位数 } ResourcesSubscriberMgr::ResourcesSubscriberMgr() { deathRecipient_ = new (std::nothrow) ObserverDeathRecipient(); } ResourcesSubscriberMgr::~ResourcesSubscriberMgr() {} ErrCode ResourcesSubscriberMgr::AddSubscriber(const sptr& subscriber) { BGTASK_LOGD("ResourcesSubscriberMgr start subscriber"); if (subscriber == NULL) { BGTASK_LOGI("subscriber is null"); return ERR_BGTASK_INVALID_PARAM; } auto remote = subscriber->AsObject(); if (remote == nullptr) { BGTASK_LOGE("remote in subscriber is null"); return ERR_BGTASK_INVALID_PARAM; } if (deathRecipient_ == nullptr) { BGTASK_LOGE("create death recipient failed"); return ERR_BGTASK_INVALID_PARAM; } std::lock_guard subcriberLock(subscriberLock_); auto subscriberIter = std::find_if(subscriberList_.begin(), subscriberList_.end(), [&remote](const auto &subscriber) { return subscriber->AsObject() == remote; }); if (subscriberIter != subscriberList_.end()) { BGTASK_LOGE("subscriber has already exist"); return ERR_BGTASK_OBJECT_EXISTS; } subscriberList_.emplace_back(subscriber); remote->AddDeathRecipient(deathRecipient_); BGTASK_LOGD("add resources to efficiency resources mgr succeed!"\ " suscriber efficient resources, list.size() is %{public}d", static_cast(subscriberList_.size())); return ERR_OK; } ErrCode ResourcesSubscriberMgr::RemoveSubscriber(const sptr& subscriber) { if (deathRecipient_ == nullptr) { BGTASK_LOGE("deathRecipient is null"); return ERR_BGTASK_OBJECT_EXISTS; } if (subscriber == nullptr) { BGTASK_LOGE("subscriber is null"); return ERR_BGTASK_INVALID_PARAM; } auto remote = subscriber->AsObject(); if (remote == nullptr) { BGTASK_LOGE("apply efficiency resources failed, remote in subscriber is null"); return ERR_BGTASK_INVALID_PARAM; } std::lock_guard subcriberLock(subscriberLock_); auto findSuscriber = [&remote](const auto& subscriberList) { return subscriberList->AsObject() == remote; }; auto subscriberIter = std::find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber); if (subscriberIter == subscriberList_.end()) { BGTASK_LOGE("request subscriber is not exists"); return ERR_BGTASK_OBJECT_EXISTS; } subscriberList_.erase(subscriberIter); remote->RemoveDeathRecipient(deathRecipient_); BGTASK_LOGD("remove subscriber from efficiency resources succeed"); return ERR_OK; } void ResourcesSubscriberMgr::OnResourceChanged(const std::shared_ptr &callbackInfo, EfficiencyResourcesEventType type) { BGTASK_LOGD("start OnResourceChanged"); if (callbackInfo == nullptr) { BGTASK_LOGW("ResourceCallbackInfo is null"); return; } std::lock_guard subcriberLock(subscriberLock_); if (subscriberList_.empty()) { BGTASK_LOGW("Background Task Subscriber List is empty"); return; } HiSysEventResources(callbackInfo, type); switch (type) { case EfficiencyResourcesEventType::APP_RESOURCE_APPLY: BGTASK_LOGD("start callback function of app resources application"); for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) { (*iter)->OnAppEfficiencyResourcesApply(callbackInfo); } break; case EfficiencyResourcesEventType::RESOURCE_APPLY: BGTASK_LOGD("start callback function of proc resources application"); for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) { (*iter)->OnProcEfficiencyResourcesApply(callbackInfo); } break; case EfficiencyResourcesEventType::APP_RESOURCE_RESET: BGTASK_LOGD("start callback function of app resources reset"); for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) { (*iter)->OnAppEfficiencyResourcesReset(callbackInfo); } break; case EfficiencyResourcesEventType::RESOURCE_RESET: BGTASK_LOGD("start callback function of proc resources reset"); for (auto iter = subscriberList_.begin(); iter != subscriberList_.end(); ++iter) { (*iter)->OnProcEfficiencyResourcesReset(callbackInfo); } break; } BGTASK_LOGD("efficiency resources on resources changed function succeed"); } void ResourcesSubscriberMgr::HiSysEventResources(const std::shared_ptr callbackInfo, EfficiencyResourcesEventType type) { if (callbackInfo == nullptr) { BGTASK_LOGE("ResourceCallbackInfo is null"); return; } switch (type) { case EfficiencyResourcesEventType::APP_RESOURCE_APPLY: HiSysEventSubmit(callbackInfo, HISYSEVENT_APP_RESOURCE_APPLY, "CONTINUOUS_TASK_APPLY"); break; case EfficiencyResourcesEventType::RESOURCE_APPLY: HiSysEventSubmit(callbackInfo, HISYSEVENT_RESOURCE_APPLY, "CONTINUOUS_TASK_APPLY"); break; case EfficiencyResourcesEventType::APP_RESOURCE_RESET: HiSysEventSubmit(callbackInfo, HISYSEVENT_APP_RESOURCE_RESET, "CONTINUOUS_TASK_CANCEL"); break; case EfficiencyResourcesEventType::RESOURCE_RESET: HiSysEventSubmit(callbackInfo, HISYSEVENT_RESOURCE_RESET, "CONTINUOUS_TASK_CANCEL"); break; } } void ResourcesSubscriberMgr::HiSysEventSubmit(const std::shared_ptr callbackInfo, int32_t hiSysEventType, const std::string &eventType) { uint32_t resourceType = callbackInfo->GetResourceNumber() << RESOURCE_TYPE_SHIFTS; HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::BACKGROUND_TASK, eventType.c_str(), HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_UID", callbackInfo->GetUid(), "APP_PID", callbackInfo->GetPid(), "APP_NAME", callbackInfo->GetBundleName(), "BGMODE", resourceType, "UIABILITY_IDENTITY", hiSysEventType); } void ResourcesSubscriberMgr::HandleSubscriberDeath(const wptr& remote) { if (remote == nullptr) { BGTASK_LOGE("suscriber death, remote in suscriber is null"); return; } sptr proxy = remote.promote(); if (!proxy) { BGTASK_LOGE("get remote proxy failed"); return; } std::lock_guard subcriberLock(subscriberLock_); auto findSuscriber = [&proxy](const auto& subscriber) { return subscriber->AsObject() == proxy; }; auto subscriberIter = std::find_if(subscriberList_.begin(), subscriberList_.end(), findSuscriber); if (subscriberIter == subscriberList_.end()) { BGTASK_LOGI("suscriber death, remote in suscriber not found"); return; } subscriberList_.erase(subscriberIter); BGTASK_LOGD("suscriber death, remove it from list"); } ObserverDeathRecipient::ObserverDeathRecipient() {} ObserverDeathRecipient::~ObserverDeathRecipient() {} void ObserverDeathRecipient::OnRemoteDied(const wptr& remote) { DelayedSingleton::GetInstance()->HandleSubscriberDeath(remote); } } // namespace BackgroundTaskMgr } // namespace OHOS