* Copyright (c) 2023-2024 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 "app_running_status_module.h"
#include <algorithm>
#include "app_running_status_proxy.h"
#include "cpp/mutex.h"
#include "hilog_tag_wrapper.h"
namespace OHOS {
namespace AbilityRuntime {
int32_t AppRunningStatusModule::RegisterListener(const sptr<AppRunningStatusListenerInterface> &listener)
{
TAG_LOGD(AAFwkTag::APPMGR, "called");
if (listener == nullptr || listener->AsObject() == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "null listener");
return ERR_INVALID_OPERATION;
}
std::lock_guard<std::mutex> lock(listenerMutex_);
auto findTask =
[listener](
const std::pair<sptr<AppRunningStatusListenerInterface>, sptr<IRemoteObject::DeathRecipient>> &item) {
return listener->AsObject() == item.first->AsObject();
};
auto itemFind = std::find_if(listeners_.begin(), listeners_.end(), findTask);
if (itemFind != listeners_.end()) {
TAG_LOGD(AAFwkTag::APPMGR, "Listener is already exist.");
return ERR_OK;
}
sptr<ClientDeathRecipient> deathRecipient = new (std::nothrow) ClientDeathRecipient(shared_from_this());
if (deathRecipient == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "null deathRecipient");
return ERR_NO_MEMORY;
}
listener->AsObject()->AddDeathRecipient(deathRecipient);
listeners_.emplace(listener, deathRecipient);
return ERR_OK;
}
int32_t AppRunningStatusModule::UnregisterListener(const sptr<AppRunningStatusListenerInterface> &listener)
{
TAG_LOGD(AAFwkTag::APPMGR, "called");
if (listener == nullptr || listener->AsObject() == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "input invalid");
return ERR_INVALID_VALUE;
}
return RemoveListenerAndDeathRecipient(listener->AsObject());
}
void AppRunningStatusModule::NotifyAppRunningStatusEvent(
const std::string &bundle, int32_t uid, RunningStatus runningStatus)
{
TAG_LOGD(AAFwkTag::APPMGR, "called");
std::lock_guard<std::mutex> lock(listenerMutex_);
for (const auto &item : listeners_) {
if (item.first == nullptr) {
TAG_LOGW(AAFwkTag::APPMGR, "invalid listener");
continue;
}
item.first->NotifyAppRunningStatus(bundle, uid, runningStatus);
}
}
AppRunningStatusModule::ClientDeathRecipient::ClientDeathRecipient(const std::weak_ptr<AppRunningStatusModule> &weakPtr)
{
weakPtr_ = weakPtr;
}
void AppRunningStatusModule::ClientDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
{
TAG_LOGD(AAFwkTag::APPMGR, "called");
auto appRunningStatus = weakPtr_.lock();
if (appRunningStatus == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "null appRunningStatus");
return;
}
appRunningStatus->RemoveListenerAndDeathRecipient(remote);
}
int32_t AppRunningStatusModule::RemoveListenerAndDeathRecipient(const wptr<IRemoteObject> &remote)
{
TAG_LOGD(AAFwkTag::APPMGR, "called");
auto listener = remote.promote();
if (listener == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "null listener");
return ERR_INVALID_VALUE;
}
std::lock_guard<std::mutex> lock(listenerMutex_);
auto findTask =
[listener](
const std::pair<sptr<AppRunningStatusListenerInterface>, sptr<IRemoteObject::DeathRecipient>> &item) {
return listener == item.first->AsObject();
};
auto itemFind = std::find_if(listeners_.begin(), listeners_.end(), findTask);
if (itemFind == listeners_.end()) {
TAG_LOGE(AAFwkTag::APPMGR, "listener is not exist");
return ERR_INVALID_OPERATION;
}
auto storedListener = itemFind->first;
auto deathRecipient = itemFind->second;
listeners_.erase(itemFind);
if (storedListener == nullptr || storedListener->AsObject() == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "invalid listener");
return ERR_INVALID_OPERATION;
}
storedListener->AsObject()->RemoveDeathRecipient(deathRecipient);
return ERR_OK;
}
}
}