* Copyright (c) 2025 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 "sa_interceptor_manager.h"
#include <random>
#include "ability_manager_errors.h"
#include "ability_manager_service.h"
#include "hilog_tag_wrapper.h"
#include "hitrace_meter.h"
namespace OHOS {
namespace AbilityRuntime {
constexpr int32_t BASE_USER_RANGE = 200000;
SAInterceptorManager::SAInterceptorManager()
{}
SAInterceptorManager::~SAInterceptorManager()
{}
SAInterceptorManager &SAInterceptorManager::GetInstance()
{
static SAInterceptorManager manager;
return manager;
}
int32_t SAInterceptorManager::AddSAInterceptor(sptr<ISAInterceptor> interceptor)
{
if (interceptor == nullptr) {
TAG_LOGE(AAFwkTag::SA_INTERCEPTOR, "null interceptor");
return AAFwk::ERR_NULL_SA_INTERCEPTOR_EXECUTER;
}
{
std::lock_guard<std::mutex> lock(saInterceptorLock_);
for (auto it = saInterceptors_.begin(); it != saInterceptors_.end(); ++it) {
if ((*it)->AsObject() == interceptor->AsObject()) {
TAG_LOGI(AAFwkTag::ABILITYMGR, "interceptor exist");
return ERR_OK;
}
}
saInterceptors_.emplace_back(interceptor);
if (!deathRecipient_) {
deathRecipient_ = new SAInterceptorRecipient([](const wptr<IRemoteObject> &remote) {
SAInterceptorManager::GetInstance().OnObserverDied(remote);
});
}
}
auto observerObj = interceptor->AsObject();
if (!observerObj || !observerObj->AddDeathRecipient(deathRecipient_)) {
TAG_LOGE(AAFwkTag::SA_INTERCEPTOR, "AddDeathRecipient failed");
}
return ERR_OK;
}
int32_t SAInterceptorManager::RemoveSAInterceptor(sptr<IRemoteObject> interceptor)
{
if (interceptor == nullptr) {
TAG_LOGE(AAFwkTag::SA_INTERCEPTOR, "null interceptor");
return AAFwk::ERR_NULL_SA_INTERCEPTOR_EXECUTER;
}
std::lock_guard<std::mutex> lock(saInterceptorLock_);
for (auto interceptorIter = saInterceptors_.begin(); interceptorIter != saInterceptors_.end(); interceptorIter++) {
if (*interceptorIter && (*interceptorIter)->AsObject() == interceptor) {
if (interceptor && deathRecipient_) {
interceptor->RemoveDeathRecipient(deathRecipient_);
}
saInterceptors_.erase(interceptorIter);
TAG_LOGI(AAFwkTag::ABILITYMGR, "interceptor removed");
return ERR_OK;
}
}
TAG_LOGE(AAFwkTag::ABILITYMGR, "interceptor not found");
return AAFwk::ERR_SA_INTERCEPTOR_NOT_EXIST;
}
bool SAInterceptorManager::SAInterceptorListIsEmpty()
{
std::lock_guard<std::mutex> lock(saInterceptorLock_);
return saInterceptors_.empty();
}
int32_t SAInterceptorManager::ExecuteSAInterceptor(const std::string ¶ms, Rule &rule)
{
TAG_LOGI(AAFwkTag::SA_INTERCEPTOR, "call ExecuteSAInterceptor");
std::vector<sptr<ISAInterceptor>> tempSaInterceptors;
{
std::lock_guard<std::mutex> lock(saInterceptorLock_);
tempSaInterceptors = saInterceptors_;
}
for (auto &interceptor : tempSaInterceptors) {
if (interceptor == nullptr) {
continue;
}
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
auto result = interceptor->OnCheckStarting(params, rule);
if (result != ERR_OK || rule.type != RuleType::ALLOW) {
TAG_LOGW(AAFwkTag::SA_INTERCEPTOR, "OnCheckStarting error: %{public}d", result);
return result;
}
}
return ERR_OK;
}
void SAInterceptorManager::OnObserverDied(const wptr<IRemoteObject> &remote)
{
TAG_LOGI(AAFwkTag::SA_INTERCEPTOR, "call OnObserverDied");
auto remoteObj = remote.promote();
if (remoteObj == nullptr) {
TAG_LOGE(AAFwkTag::SA_INTERCEPTOR, "null remote");
return;
}
std::lock_guard<std::mutex> lock(saInterceptorLock_);
for (auto interceptorIter = saInterceptors_.begin(); interceptorIter != saInterceptors_.end(); interceptorIter++) {
if (*interceptorIter && (*interceptorIter)->AsObject() == remoteObj) {
saInterceptors_.erase(interceptorIter);
return;
}
}
}
bool SAInterceptorManager::ObserverExist(sptr<IRemoteBroker> observer)
{
if (observer == nullptr) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer");
return false;
}
std::lock_guard<std::mutex> lockRegister(saInterceptorLock_);
for (auto it = saInterceptors_.begin(); it != saInterceptors_.end(); ++it) {
if ((*it)->AsObject() == observer->AsObject()) {
return true;
}
}
return false;
}
std::string SAInterceptorManager::GenerateSAInterceptorParams(const AAFwk::Want &want, sptr<IRemoteObject> callerToken,
const AppExecFwk::AbilityInfo &abilityInfo, const std::string &dialogSessionId)
{
nlohmann::json jsonObj;
auto abilityRecord = AAFwk::Token::GetAbilityRecordByToken(callerToken);
if (abilityRecord) {
const auto &callerAbilityInfo = abilityRecord->GetAbilityInfo();
jsonObj["callerBundleName"] = callerAbilityInfo.bundleName;
jsonObj["callerModuleName"] = callerAbilityInfo.moduleName;
jsonObj["callerAbilityName"] = callerAbilityInfo.name;
} else {
jsonObj["callerBundleName"] = "";
jsonObj["callerModuleName"] = "";
jsonObj["callerAbilityName"] = "";
}
jsonObj["callerUid"] = IPCSkeleton::GetCallingUid();
jsonObj["callerAppState"] = abilityRecord ? static_cast<int32_t>(abilityRecord->GetAppState()) : 0;
jsonObj["callerUserId"] = IPCSkeleton::GetCallingUid() / BASE_USER_RANGE;
jsonObj["targetBundleName"] = abilityInfo.bundleName;
jsonObj["targetModuleName"] = abilityInfo.moduleName;
jsonObj["targetAbilityName"] = abilityInfo.name;
jsonObj["targetUid"] = abilityInfo.applicationInfo.uid;
jsonObj["targetAbilityType"] = abilityInfo.type;
jsonObj["targetAppIndex"] = abilityInfo.appIndex;
jsonObj["targetExtensionAbilityType"] = abilityInfo.extensionAbilityType;
jsonObj["linking"] = want.GetUriString();
jsonObj["dialogSessionId"] = dialogSessionId;
return jsonObj.dump();
}
SAInterceptorRecipient::SAInterceptorRecipient(RemoteDiedHandler handler) : handler_(handler)
{}
SAInterceptorRecipient::~SAInterceptorRecipient()
{}
void SAInterceptorRecipient::OnRemoteDied(const wptr<IRemoteObject> &__attribute__((unused)) remote)
{
TAG_LOGI(AAFwkTag::SA_INTERCEPTOR, "call OnRemoteDied");
if (handler_) {
handler_(remote);
}
}
}
}