* Copyright (c) 2026 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 "utils/agent_ability_util.h"
#include "ability_manager_errors.h"
#include "agent_extension_connection_constants.h"
#include "hilog_tag_wrapper.h"
#include "hilog_wrapper.h"
#include "long_wrapper.h"
#include "permission_verification.h"
namespace OHOS {
namespace AAFwk {
namespace {
constexpr const char* FOUNDATION_PROCESS_NAME = "foundation";
}
bool AgentAbilityUtil::IsAgentExtensionType(AppExecFwk::ExtensionAbilityType extensionType)
{
return extensionType == AppExecFwk::ExtensionAbilityType::AGENT;
}
bool AgentAbilityUtil::IsAgentExtensionAbilityInfo(const AppExecFwk::AbilityInfo &abilityInfo)
{
return abilityInfo.type == AppExecFwk::AbilityType::EXTENSION &&
IsAgentExtensionType(abilityInfo.extensionAbilityType);
}
bool AgentAbilityUtil::IsAgentExtensionInfo(const AppExecFwk::ExtensionAbilityInfo &extensionInfo)
{
return IsAgentExtensionType(extensionInfo.type);
}
bool AgentAbilityUtil::IsAtomicServiceAgentExtensionInfo(const AppExecFwk::ExtensionAbilityInfo &extensionInfo)
{
return IsAgentExtensionInfo(extensionInfo) &&
extensionInfo.applicationInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE;
}
bool AgentAbilityUtil::HasAtomicServiceAgentExtensionInfo(
const std::vector<AppExecFwk::ExtensionAbilityInfo> &extensionInfos)
{
for (const auto &extensionInfo : extensionInfos) {
if (IsAtomicServiceAgentExtensionInfo(extensionInfo)) {
return true;
}
}
return false;
}
bool AgentAbilityUtil::HasAgentOnlyParams(const Want &want)
{
return want.HasParameter(AgentRuntime::AGENTEXTENSIONHOSTPROXY_KEY) ||
want.HasParameter(AgentRuntime::AGENTID_KEY) ||
want.HasParameter(AgentRuntime::AGENT_CARD_TYPE_KEY) ||
want.HasParameter(AgentRuntime::AGENT_VERIFICATION_NONCE_KEY);
}
void AgentAbilityUtil::SetAgentVerificationNonceParam(Want &want, int64_t nonce)
{
WantParams params = want.GetParams();
params.SetParam(AgentRuntime::AGENT_VERIFICATION_NONCE_KEY, Long::Box64(nonce));
want.SetParams(params);
}
int64_t AgentAbilityUtil::GetAgentVerificationNonceParam(const Want &want)
{
auto value = want.GetParams().GetParam(AgentRuntime::AGENT_VERIFICATION_NONCE_KEY);
auto longValue = ILong::Query(value);
if (longValue == nullptr) {
return 0;
}
return Long::Unbox64(longValue);
}
int32_t AgentAbilityUtil::CheckAgentConnectEntry(const Want &want, AppExecFwk::ExtensionAbilityType extensionType)
{
if (IsAgentExtensionType(extensionType)) {
bool isFoundationCall =
PermissionVerification::GetInstance()->CheckSpecificSystemAbilityAccessPermission(FOUNDATION_PROCESS_NAME);
if (!isFoundationCall) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "AGENT connect only accepts foundation process callers");
return CHECK_PERMISSION_FAILED;
}
if (want.GetStringParam(AgentRuntime::AGENTID_KEY).empty() ||
!want.HasParameter(AgentRuntime::AGENT_CARD_TYPE_KEY) ||
GetAgentVerificationNonceParam(want) <= 0) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "invalid AGENT connect request");
return ERR_INVALID_VALUE;
}
if (want.GetRemoteObject(AgentRuntime::AGENTEXTENSIONHOSTPROXY_KEY) == nullptr) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "invalid AGENT host proxy");
return ERR_INVALID_VALUE;
}
return ERR_OK;
}
if (HasAgentOnlyParams(want)) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "non-AGENT lane carries AGENT params");
return ERR_WRONG_INTERFACE_CALL;
}
return ERR_OK;
}
int32_t AgentAbilityUtil::CheckConnectAgentResolvedTarget(
AppExecFwk::ExtensionAbilityType requestType, const AppExecFwk::AbilityInfo &abilityInfo)
{
bool targetIsAgent = IsAgentExtensionAbilityInfo(abilityInfo);
if (IsAgentExtensionType(requestType)) {
if (!targetIsAgent) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "AGENT lane resolved non-AGENT target");
return ERR_WRONG_INTERFACE_CALL;
}
return ERR_OK;
}
if (targetIsAgent) {
TAG_LOGE(AAFwkTag::SER_ROUTER, "generic connect lane resolved AGENT target");
return ERR_WRONG_INTERFACE_CALL;
}
return ERR_OK;
}
}
}