mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-24 22:21:36 -04:00
!19629 merge revert/agent-connection into master
Revert "bugfix: agent connection not reused" Created-by: yangxuguang-huawei Commit-by: yangxuguang-huawei Merged-by: openharmony_ci Description: **IssueNo**: https://gitcode.com/openharmony/ability_ability_runtime/issues/15487 **Description**: **稳定性自检:** | 自检项 | 自检结果 | | ------------------------------------------------------------ | -------- | | 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发 | ok | | 成员变量进行赋值或创建需要排查并发 | ok| | 谨慎在lambda表达式中使用引用捕获 | ok| | 谨慎在未经拷贝的情况下使用外部传入的string、C字符串 | ok| | map\vector\list\set等stl模板类使用时需要排查并发 | ok| | 谨慎考虑加锁范围 | ok| | 在IPC通信中谨慎使用同步通信方式 | ok| | 禁止传递this指针至其他模块或线程(特别是eventhandler任务) | ok| | 禁止将外部传入的裸指针在内部直接构造智能指针 | ok| | 禁止多个独立创建的智能指针管理同一地址 | ok| | 禁止在析构函数中抛异步任务 | ok| | 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁 | ok| | 禁止在对外接口中未经判空直接使用外部传入的指针 | ok| | 禁止接口返回局部变量引用 | ok| | 禁止在信号函数中加锁 | ok| | 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作 | ok| | 禁止将同一个cpp编译在不同的so中 | ok| **安全编码自检:** | 自检项 | 自检结果 | | -------------------------------------------------------------- | -------- | | 裸指针避免通过隐式转换构造为sptr | ok| | json对象在取值之前必须先判断类型,避免类型不匹配 | ok| | 序列化时必须对传入的数组大小进行校验,避免出现超大数组 | ok | | 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型 | ok| | 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 | ok | | 指针变量、表示资源描述符的变量、bool变量必须赋初值 | ok| | readParcelable获取的对象使用前需要判空 | ok| | 分配和释放内存的函数需要成对出现 | ok| | 申请内存后异常退出前需要及时进行内存释放 | ok | | 内存申请前必须对内存大小进行合法性校验 | ok| | 内存分配后必须判断是否成功 | ok| | 禁止使用realloc、alloca函数 | ok| | 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰 | ok| | 禁止打印内存地址 | ok| | 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0 | ok| | 禁止对有符号整数进行位操作符运算 | ok| | 禁止对指针进行逻辑或位运算 | ok| | 循环次数如果收外部数据控制,需要检验其合法性 | ok| | 禁止使用内存操作类危险函数,需要使用安全函数 | ok| | 谨慎使用不可重入函数 | ok| | 必须检查安全函数的返回值,并进行正确处理 | ok| | 禁止仅通过TokenType类型判断绕过权限校验 | ok| **TDD Result**: 已验证OK **XTS Result**: 已验证OK ### 是否已执行L0用例 - [x] 已验证 - [ ] 不涉及。如不涉及,请写明理由 See merge request: openharmony/ability_ability_runtime!19629
This commit is contained in:
+6
-4
@@ -76,13 +76,15 @@ int64_t InsertAgentConnection(sptr<EtsAgentConnection> connection, const AAFwk::
|
||||
void FindAgentConnection(int64_t connectId, sptr<EtsAgentConnection> &connection);
|
||||
|
||||
/**
|
||||
* Find agent connection by target identity.
|
||||
* Find agent connection by want and callback.
|
||||
*
|
||||
* @param env The ANI environment.
|
||||
* @param want The want information to match.
|
||||
* @param agentId The agent ID to match.
|
||||
* @param callback The callback object to match.
|
||||
* @param connection Output parameter for the found connection.
|
||||
*/
|
||||
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<EtsAgentConnection> &connection);
|
||||
void FindAgentConnection(ani_env *env, AAFwk::Want &want, ani_object callback,
|
||||
sptr<EtsAgentConnection> &connection);
|
||||
}
|
||||
|
||||
class EtsAgentConnectorStubImpl;
|
||||
@@ -162,7 +164,7 @@ public:
|
||||
*
|
||||
* @param duplicatedCallback The callback object from ETS.
|
||||
*/
|
||||
bool AddDuplicatedPendingCallback(ani_object duplicatedCallback);
|
||||
void AddDuplicatedPendingCallback(ani_object duplicatedCallback);
|
||||
|
||||
/**
|
||||
* Resolve all duplicated pending callbacks with the proxy.
|
||||
|
||||
+19
-45
@@ -37,22 +37,6 @@ constexpr const char *SIGNATURE_AGENT_EXTENSION_CALLBACK =
|
||||
"application.AgentExtensionConnectCallback.AgentExtensionConnectCallback";
|
||||
constexpr const char *SIGNATURE_ON_DATA_AND_AUTH = "C{std.core.String}:";
|
||||
constexpr const char *SIGNATURE_VOID = ":";
|
||||
|
||||
bool IsSameAgentConnection(const AAFwk::Want &storedWant, const AAFwk::Want &want, const std::string &agentId)
|
||||
{
|
||||
std::string existingId = storedWant.GetStringParam(AGENTID_KEY);
|
||||
if (existingId.empty() || agentId.empty() || existingId != agentId) {
|
||||
return false;
|
||||
}
|
||||
const auto &storedElement = storedWant.GetElement();
|
||||
const auto &element = want.GetElement();
|
||||
if (storedElement.GetBundleName() != element.GetBundleName() ||
|
||||
storedElement.GetAbilityName() != element.GetAbilityName()) {
|
||||
return false;
|
||||
}
|
||||
return storedElement.GetModuleName().empty() || element.GetModuleName().empty() ||
|
||||
storedElement.GetModuleName() == element.GetModuleName();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace AgentConnectionUtils {
|
||||
@@ -117,13 +101,21 @@ void FindAgentConnection(int64_t connectId, sptr<EtsAgentConnection> &connection
|
||||
}
|
||||
}
|
||||
|
||||
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<EtsAgentConnection> &connection)
|
||||
void FindAgentConnection(ani_env *env, AAFwk::Want &want, ani_object callback,
|
||||
sptr<EtsAgentConnection> &connection)
|
||||
{
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by target");
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by want+callback");
|
||||
std::lock_guard<std::recursive_mutex> lock(g_agentConnectsLock_);
|
||||
auto item = std::find_if(g_agentConnects.begin(), g_agentConnects.end(),
|
||||
[&want, &agentId](const auto &obj) {
|
||||
return IsSameAgentConnection(obj.first.want, want, agentId);
|
||||
[&want, env, callback](const auto &obj) {
|
||||
std::string existingId = obj.first.want.GetStringParam(AGENTID_KEY);
|
||||
std::string agentId = want.GetStringParam(AGENTID_KEY);
|
||||
bool wantEquals = obj.first.want.GetElement() == want.GetElement() &&
|
||||
!existingId.empty() && !agentId.empty() && existingId == agentId;
|
||||
ani_ref tempCallbackRef = obj.second->GetEtsConnectionObject();
|
||||
bool callbackObjectEquals =
|
||||
EtsAgentConnection::IsEtsCallbackObjectEquals(env, tempCallbackRef, callback);
|
||||
return wantEquals && callbackObjectEquals;
|
||||
});
|
||||
if (item == g_agentConnects.end()) {
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "Connection not found");
|
||||
@@ -284,14 +276,13 @@ void EtsAgentConnection::ReleaseObjectReference(ani_ref etsObjRef)
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "etsVm_ or etsObjRef null");
|
||||
return;
|
||||
}
|
||||
bool isAttachThread = false;
|
||||
ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread);
|
||||
if (env == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "AttachAniEnv failed");
|
||||
ani_env *env = nullptr;
|
||||
ani_status status = ANI_ERROR;
|
||||
if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "GetEnv failed status: %{public}d", status);
|
||||
return;
|
||||
}
|
||||
ReleaseObjectReference(env, etsObjRef);
|
||||
AppExecFwk::DetachAniEnv(etsVm_, isAttachThread);
|
||||
}
|
||||
|
||||
void EtsAgentConnection::CallObjectMethod(ani_env *env, const char *methodName, const char *signature, ...)
|
||||
@@ -380,31 +371,14 @@ void EtsAgentConnection::SetAniAsyncCallback(ani_object asyncCallback)
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "SetAniAsyncCallback success");
|
||||
}
|
||||
|
||||
bool EtsAgentConnection::AddDuplicatedPendingCallback(ani_object duplicatedCallback)
|
||||
void EtsAgentConnection::AddDuplicatedPendingCallback(ani_object duplicatedCallback)
|
||||
{
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "AddDuplicatedPendingCallback");
|
||||
if (duplicatedCallback == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "duplicatedCallback is null");
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
if (etsVm_ == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "etsVm_ is null");
|
||||
return false;
|
||||
}
|
||||
ani_env *env = nullptr;
|
||||
ani_status status = ANI_ERROR;
|
||||
if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "GetEnv failed status: %{public}d", status);
|
||||
return false;
|
||||
}
|
||||
ani_ref globalRef = nullptr;
|
||||
if ((status = env->GlobalReference_Create(duplicatedCallback, &globalRef)) != ANI_OK ||
|
||||
globalRef == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "GlobalReference_Create failed status: %{public}d", status);
|
||||
return false;
|
||||
}
|
||||
duplicatedPendingCallbacks_.push_back(globalRef);
|
||||
return true;
|
||||
duplicatedPendingCallbacks_.push_back(duplicatedCallback);
|
||||
}
|
||||
|
||||
void EtsAgentConnection::ResolveDuplicatedPendingCallbacks(ani_env *env, ani_object proxyObj)
|
||||
|
||||
@@ -57,12 +57,12 @@ class EtsAgentServiceConnection;
|
||||
std::map<int64_t, sptr<EtsAgentServiceConnection>> g_serviceConnections;
|
||||
int64_t g_serviceConnectionSerialNumber = 0;
|
||||
|
||||
bool CheckConnectAlreadyExist(ani_env *env, const AAFwk::Want &want, const std::string &agentId,
|
||||
ani_object asyncCallback)
|
||||
bool CheckConnectAlreadyExist(ani_env *env, AAFwk::Want &want,
|
||||
ani_object callback, ani_object asyncCallback)
|
||||
{
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "CheckConnectAlreadyExist called");
|
||||
sptr<EtsAgentConnection> connection = nullptr;
|
||||
AgentConnectionUtils::FindAgentConnection(want, agentId, connection);
|
||||
AgentConnectionUtils::FindAgentConnection(env, want, callback, connection);
|
||||
if (connection == nullptr) {
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "null connection");
|
||||
return false;
|
||||
@@ -70,10 +70,7 @@ bool CheckConnectAlreadyExist(ani_env *env, const AAFwk::Want &want, const std::
|
||||
ani_ref proxy = connection->GetProxyObject();
|
||||
if (proxy == nullptr) {
|
||||
TAG_LOGW(AAFwkTag::SER_ROUTER, "null proxy");
|
||||
if (!connection->AddDuplicatedPendingCallback(asyncCallback)) {
|
||||
AsyncCallback(env, SIGNATURE_AGENT_ASYNC_CALLBACK_WRAPPER, asyncCallback,
|
||||
EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER), nullptr);
|
||||
}
|
||||
connection->AddDuplicatedPendingCallback(asyncCallback);
|
||||
} else {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "Resolve, got proxy object");
|
||||
AsyncCallback(env, SIGNATURE_AGENT_ASYNC_CALLBACK_WRAPPER, asyncCallback,
|
||||
@@ -534,7 +531,7 @@ void EtsAgentManager::ConnectAgentExtensionAbility(ani_env *env, ani_object aniW
|
||||
want.GetElement().GetBundleName().c_str(), want.GetElement().GetAbilityName().c_str());
|
||||
|
||||
// Check for duplicate connection
|
||||
if (CheckConnectAlreadyExist(env, want, agentId, asyncCallback)) {
|
||||
if (CheckConnectAlreadyExist(env, want, callbackObj, asyncCallback)) {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "Duplicate connection found");
|
||||
return;
|
||||
}
|
||||
|
||||
+5
-3
@@ -77,13 +77,15 @@ int64_t InsertAgentConnection(sptr<JSAgentConnection> connection, const AAFwk::W
|
||||
void FindAgentConnection(int64_t connectId, sptr<JSAgentConnection> &connection);
|
||||
|
||||
/**
|
||||
* Find agent connection by target identity.
|
||||
* Find agent connection by want and callback.
|
||||
*
|
||||
* @param env The N-API environment.
|
||||
* @param want The want information to match.
|
||||
* @param agentId The agent ID to match.
|
||||
* @param callback The callback object to match.
|
||||
* @param connection Output parameter for the found connection.
|
||||
*/
|
||||
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<JSAgentConnection> &connection);
|
||||
void FindAgentConnection(napi_env env, AAFwk::Want &want, napi_value callback,
|
||||
sptr<JSAgentConnection> &connection);
|
||||
}
|
||||
|
||||
class JsAgentConnectorStubImpl;
|
||||
|
||||
+12
-20
@@ -33,22 +33,6 @@ constexpr int32_t ARGC_ONE = 1;
|
||||
static std::map<ConnectionKey, sptr<JSAgentConnection>, KeyCompare> g_agentConnects;
|
||||
static std::recursive_mutex g_agentConnectsLock_;
|
||||
static int64_t g_agentSerialNumber = 0;
|
||||
|
||||
bool IsSameAgentConnection(const AAFwk::Want &storedWant, const AAFwk::Want &want, const std::string &agentId)
|
||||
{
|
||||
std::string existingId = storedWant.GetStringParam(AGENTID_KEY);
|
||||
if (existingId.empty() || agentId.empty() || existingId != agentId) {
|
||||
return false;
|
||||
}
|
||||
const auto &storedElement = storedWant.GetElement();
|
||||
const auto &element = want.GetElement();
|
||||
if (storedElement.GetBundleName() != element.GetBundleName() ||
|
||||
storedElement.GetAbilityName() != element.GetAbilityName()) {
|
||||
return false;
|
||||
}
|
||||
return storedElement.GetModuleName().empty() || element.GetModuleName().empty() ||
|
||||
storedElement.GetModuleName() == element.GetModuleName();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace AgentConnectionUtils {
|
||||
@@ -109,13 +93,21 @@ void FindAgentConnection(int64_t connectId, sptr<JSAgentConnection> &connection)
|
||||
}
|
||||
}
|
||||
|
||||
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<JSAgentConnection> &connection)
|
||||
void FindAgentConnection(napi_env env, AAFwk::Want &want, napi_value callback,
|
||||
sptr<JSAgentConnection> &connection)
|
||||
{
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by target");
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by want+callback");
|
||||
std::lock_guard<std::recursive_mutex> lock(g_agentConnectsLock_);
|
||||
auto item = std::find_if(g_agentConnects.begin(), g_agentConnects.end(),
|
||||
[&want, &agentId](const auto &obj) {
|
||||
return IsSameAgentConnection(obj.first.want, want, agentId);
|
||||
[&want, env, callback](const auto &obj) {
|
||||
std::string exstingId = obj.first.want.GetStringParam(AGENTID_KEY);
|
||||
std::string agentId = want.GetStringParam(AGENTID_KEY);
|
||||
bool wantEquals = obj.first.want.GetElement() == want.GetElement() &&
|
||||
!exstingId.empty() && !agentId.empty() && exstingId == agentId;
|
||||
std::unique_ptr<NativeReference> &tempCallbackPtr = obj.second->GetJsConnectionObject();
|
||||
bool callbackObjectEquals =
|
||||
JSAgentConnection::IsJsCallbackObjectEquals(env, tempCallbackPtr, callback);
|
||||
return wantEquals && callbackObjectEquals;
|
||||
});
|
||||
if (item == g_agentConnects.end()) {
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "Connection not found");
|
||||
|
||||
@@ -54,7 +54,6 @@ constexpr int32_t ARG_INDEX_0 = 0;
|
||||
constexpr int32_t ARG_INDEX_1 = 1;
|
||||
constexpr int32_t ARG_INDEX_2 = 2;
|
||||
constexpr int64_t INVALID_CONNECT_ID = -1;
|
||||
constexpr const char *INTERNAL_ERROR_MSG = "Internal error.";
|
||||
|
||||
std::mutex g_serviceConnectionsLock;
|
||||
class JSAgentServiceConnection;
|
||||
@@ -233,12 +232,13 @@ void RemoveServiceConnection(int64_t connectionId)
|
||||
}
|
||||
|
||||
// Helper function to check for duplicate connections
|
||||
bool CheckConnectAlreadyExist(napi_env env, const AAFwk::Want &want, const std::string &agentId, napi_value &result)
|
||||
bool CheckConnectAlreadyExist(napi_env env, AAFwk::Want &want,
|
||||
napi_value callback, napi_value &result)
|
||||
{
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "CheckConnectAlreadyExist called");
|
||||
|
||||
sptr<JSAgentConnection> connection = nullptr;
|
||||
AgentConnectionUtils::FindAgentConnection(want, agentId, connection);
|
||||
AgentConnectionUtils::FindAgentConnection(env, want, callback, connection);
|
||||
if (connection == nullptr) {
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "No duplicate connection found");
|
||||
return false;
|
||||
@@ -251,27 +251,13 @@ bool CheckConnectAlreadyExist(napi_env env, const AAFwk::Want &want, const std::
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "Proxy not ready, queuing pending task");
|
||||
std::unique_ptr<NapiAsyncTask> asyncTask =
|
||||
CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result);
|
||||
if (asyncTask == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Create async task failed");
|
||||
ThrowError(env, static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER), INTERNAL_ERROR_MSG);
|
||||
result = CreateJsUndefined(env);
|
||||
return true;
|
||||
}
|
||||
connection->AddDuplicatedPendingTask(asyncTask);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Connection exists and proxy is ready, resolve immediately
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "Resolving with existing proxy");
|
||||
std::unique_ptr<NapiAsyncTask> asyncTask =
|
||||
CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result);
|
||||
if (asyncTask == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Create async task failed");
|
||||
ThrowError(env, static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER), INTERNAL_ERROR_MSG);
|
||||
result = CreateJsUndefined(env);
|
||||
return true;
|
||||
}
|
||||
asyncTask->ResolveWithNoError(env, proxy);
|
||||
result = proxy;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -580,7 +566,7 @@ napi_value JsAgentManager::OnConnectAgentExtensionAbility(napi_env env, size_t a
|
||||
|
||||
// 2. Check for duplicate connection
|
||||
napi_value result = nullptr;
|
||||
bool duplicated = CheckConnectAlreadyExist(env, want, agentId, result);
|
||||
bool duplicated = CheckConnectAlreadyExist(env, want, callbackObject, result);
|
||||
if (duplicated) {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "Duplicated connection found");
|
||||
return result;
|
||||
@@ -669,11 +655,6 @@ napi_value JsAgentManager::ScheduleAgentConnection(napi_env env, const AAFwk::Wa
|
||||
napi_value result = nullptr;
|
||||
std::unique_ptr<NapiAsyncTask> asyncTask =
|
||||
CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result);
|
||||
if (asyncTask == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Create async task failed");
|
||||
ThrowError(env, static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER), INTERNAL_ERROR_MSG);
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
std::shared_ptr<NapiAsyncTask> asyncTaskShared = std::move(asyncTask);
|
||||
connection->SetNapiAsyncTask(asyncTaskShared);
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
#define OHOS_AGENT_RUNTIME_AGENT_CONNECTION_MANAGER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
@@ -40,7 +39,7 @@ class AgentConnection;
|
||||
* @struct AgentConnectionInfo
|
||||
* @brief Stores information about an agent connection.
|
||||
*
|
||||
* The connection key consists of: agentId + connectReceiver
|
||||
* The connection key consists of: agentId + agentExtProxy + connectReceiver
|
||||
*/
|
||||
struct AgentConnectionInfo {
|
||||
// Target agent identifier (from Want parameter AGENTID_KEY)
|
||||
@@ -50,8 +49,8 @@ struct AgentConnectionInfo {
|
||||
AAFwk::Operation connectReceiver;
|
||||
// The connection object
|
||||
sptr<AgentConnection> agentConnection;
|
||||
// Agent extension host proxy from Want parameter AGENTEXTENSIONHOSTPROXY_KEY.
|
||||
// It is per API call and is not part of the reusable connection identity.
|
||||
// Agent extension proxy for bidirectional communication
|
||||
// (from Want parameter AGENTEXTENSIONHOSTPROXY_KEY)
|
||||
void *agentExtProxy = nullptr;
|
||||
// Connection timestamp for timeout detection
|
||||
int64_t connectingTime = 0;
|
||||
@@ -84,6 +83,47 @@ struct AgentConnectionInfo {
|
||||
auto now = std::chrono::steady_clock::now().time_since_epoch();
|
||||
connectingTime = std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Comparison operator for map key ordering.
|
||||
*
|
||||
* Compares by: agentId -> agentExtProxy -> connectingTime -> connectReceiver
|
||||
* (bundleName -> moduleName -> abilityName)
|
||||
*
|
||||
* @param that The other AgentConnectionInfo to compare with.
|
||||
* @return Returns true if this is less than that.
|
||||
*/
|
||||
inline bool operator<(const AgentConnectionInfo &that) const
|
||||
{
|
||||
if (agentId < that.agentId) {
|
||||
return true;
|
||||
}
|
||||
if (agentExtProxy < that.agentExtProxy) {
|
||||
return true;
|
||||
}
|
||||
if (connectingTime < that.connectingTime) {
|
||||
return true;
|
||||
}
|
||||
if (connectReceiver.GetBundleName() < that.connectReceiver.GetBundleName()) {
|
||||
return true;
|
||||
}
|
||||
if (connectReceiver.GetBundleName() == that.connectReceiver.GetBundleName() &&
|
||||
connectReceiver.GetModuleName() < that.connectReceiver.GetModuleName()) {
|
||||
return true;
|
||||
}
|
||||
if (connectReceiver.GetBundleName() == that.connectReceiver.GetBundleName() &&
|
||||
connectReceiver.GetModuleName() == that.connectReceiver.GetModuleName() &&
|
||||
connectReceiver.GetAbilityName() < that.connectReceiver.GetAbilityName()) {
|
||||
return true;
|
||||
}
|
||||
if (connectReceiver.GetBundleName() == that.connectReceiver.GetBundleName() &&
|
||||
connectReceiver.GetModuleName() == that.connectReceiver.GetModuleName() &&
|
||||
connectReceiver.GetAbilityName() == that.connectReceiver.GetAbilityName() &&
|
||||
!(connectReceiver == that.connectReceiver)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -130,7 +170,7 @@ private:
|
||||
* @brief Manages connections to AgentExtensionAbility instances.
|
||||
*
|
||||
* This class is similar to ConnectionManager but specifically for agent extensions.
|
||||
* Connections are identified by: agentId + connectReceiver.
|
||||
* Connections are identified by: agentId + agentExtProxy + connectReceiver.
|
||||
*/
|
||||
class AgentConnectionManager {
|
||||
public:
|
||||
@@ -215,19 +255,16 @@ private:
|
||||
*/
|
||||
void *GetAgentExtProxyPtr(const AAFwk::Want &want);
|
||||
/**
|
||||
* @brief Match connection by agentId + connectReceiver.
|
||||
* @brief Match connection by agentId + agentExtProxy + connectReceiver.
|
||||
*
|
||||
* @param agentId The agent ID to match.
|
||||
* @param connectReceiver The connect receiver (Want) to match.
|
||||
* @param connection The existing connection entry.
|
||||
* @return Returns true if matches, false otherwise.
|
||||
*/
|
||||
using AgentConnectionCallbacks = std::vector<sptr<AbilityRuntime::AbilityConnectCallback>>;
|
||||
using AgentConnectionRecord = std::pair<AgentConnectionInfo, AgentConnectionCallbacks>;
|
||||
using AgentConnectionRecords = std::list<AgentConnectionRecord>;
|
||||
|
||||
bool MatchConnection(const std::string &agentId, const AAFwk::Want &connectReceiver,
|
||||
const AgentConnectionRecord &connection);
|
||||
const std::map<AgentConnectionInfo,
|
||||
std::vector<sptr<AbilityRuntime::AbilityConnectCallback>>>::value_type &connection);
|
||||
/**
|
||||
* @brief Create a new connection to the agent extension.
|
||||
*
|
||||
@@ -256,7 +293,7 @@ private:
|
||||
|
||||
private:
|
||||
std::mutex connectionsLock_;
|
||||
AgentConnectionRecords agentConnections_;
|
||||
std::map<AgentConnectionInfo, std::vector<sptr<AbilityRuntime::AbilityConnectCallback>>> agentConnections_;
|
||||
};
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -242,23 +242,22 @@ void *AgentConnectionManager::GetAgentExtProxyPtr(const AAFwk::Want &want)
|
||||
}
|
||||
|
||||
bool AgentConnectionManager::MatchConnection(const std::string &agentId, const AAFwk::Want &connectReceiver,
|
||||
const AgentConnectionRecord &connection)
|
||||
const std::map<AgentConnectionInfo, std::vector<sptr<AbilityConnectCallback>>>::value_type &connection)
|
||||
{
|
||||
// 1. Match by agentId
|
||||
if (agentId != connection.first.agentId) {
|
||||
return false;
|
||||
}
|
||||
// 2. Match by connectReceiver (bundleName, moduleName, abilityName).
|
||||
// AGENTEXTENSIONHOSTPROXY_KEY is per connect call, so it must not split reusable connections.
|
||||
const AAFwk::Operation &storedReceiver = connection.first.connectReceiver;
|
||||
const AppExecFwk::ElementName &element = connectReceiver.GetElement();
|
||||
if (element.GetBundleName() != storedReceiver.GetBundleName() ||
|
||||
element.GetAbilityName() != storedReceiver.GetAbilityName()) {
|
||||
// 2. Match by agentExtProxy
|
||||
void *agentExtProxy = GetAgentExtProxyPtr(connectReceiver);
|
||||
if (agentExtProxy != connection.first.agentExtProxy) {
|
||||
return false;
|
||||
}
|
||||
const std::string &moduleName = element.GetModuleName();
|
||||
const std::string &storedModuleName = storedReceiver.GetModuleName();
|
||||
return moduleName.empty() || storedModuleName.empty() || moduleName == storedModuleName;
|
||||
// 3. Match by connectReceiver (bundleName, moduleName, abilityName)
|
||||
const AAFwk::Operation &storedReceiver = connection.first.connectReceiver;
|
||||
return connectReceiver.GetElement().GetBundleName() == storedReceiver.GetBundleName() &&
|
||||
connectReceiver.GetElement().GetModuleName() == storedReceiver.GetModuleName() &&
|
||||
connectReceiver.GetElement().GetAbilityName() == storedReceiver.GetAbilityName();
|
||||
}
|
||||
|
||||
ErrCode AgentConnectionManager::CreateConnection(const AAFwk::Want &want,
|
||||
@@ -282,19 +281,14 @@ ErrCode AgentConnectionManager::CreateConnection(const AAFwk::Want &want,
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(connectionsLock_);
|
||||
agentConnections_.emplace_back(connectionInfo, AgentConnectionCallbacks { connectCallback });
|
||||
agentConnections_[connectionInfo] = { connectCallback };
|
||||
}
|
||||
|
||||
ErrCode ret = AgentManagerClient::GetInstance().ConnectAgentExtensionAbility(want, agentConnection);
|
||||
if (ret != ERR_OK) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "error:%{public}d", ret);
|
||||
std::lock_guard<std::mutex> lock(connectionsLock_);
|
||||
for (auto iter = agentConnections_.begin(); iter != agentConnections_.end(); ++iter) {
|
||||
if (iter->first.agentConnection == agentConnection) {
|
||||
agentConnections_.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
agentConnections_.erase(connectionInfo);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#ifndef OHOS_AGENT_RUNTIME_FRAMEWORK_AGENT_MANAGER_SERVICE_H
|
||||
#define OHOS_AGENT_RUNTIME_FRAMEWORK_AGENT_MANAGER_SERVICE_H
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
@@ -32,7 +31,6 @@
|
||||
#include "task_handler_wrap.h"
|
||||
#include "agent_host_connection.h"
|
||||
#include "agent_host_connection_types.h"
|
||||
#include "element_name.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AgentRuntime {
|
||||
@@ -85,41 +83,6 @@ public:
|
||||
private:
|
||||
friend class AgentServiceConnection;
|
||||
friend class AgentHostConnection;
|
||||
|
||||
/**
|
||||
* @struct StandardAgentKey
|
||||
* @brief Identity key for deduplicating non-low-code agent connections: callerUid + agentId + target.
|
||||
*/
|
||||
struct StandardAgentKey {
|
||||
int32_t callerUid = 0;
|
||||
std::string agentId;
|
||||
std::string bundleName;
|
||||
std::string moduleName;
|
||||
std::string abilityName;
|
||||
};
|
||||
|
||||
enum class StandardAgentState : int32_t {
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct StandardAgentSession
|
||||
* @brief Collapsed session for standard agent connections sharing the same (callerUid, agentId, target).
|
||||
*/
|
||||
struct StandardAgentSession {
|
||||
StandardAgentKey key;
|
||||
StandardAgentState state = StandardAgentState::CONNECTING;
|
||||
sptr<AAFwk::IAbilityConnection> serviceConnection = nullptr;
|
||||
std::vector<sptr<AAFwk::IAbilityConnection>> pendingCallbacks;
|
||||
std::vector<sptr<AAFwk::IAbilityConnection>> connectedCallbacks;
|
||||
std::vector<sptr<IRemoteObject>> callerRemotes;
|
||||
AppExecFwk::ElementName cachedElement;
|
||||
sptr<IRemoteObject> cachedRemoteObject = nullptr;
|
||||
int32_t cachedResultCode = ERR_OK;
|
||||
bool isDisconnecting = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct TrackedConnectionRecord
|
||||
* @brief Stores one caller-visible connection together with the service-side wrapper used to talk to AMS.
|
||||
@@ -133,21 +96,6 @@ private:
|
||||
bool isLowCode = false;
|
||||
bool countTowardsCallerLimit = true;
|
||||
bool isDisconnecting = false;
|
||||
StandardAgentKey standardKey;
|
||||
};
|
||||
|
||||
using TrackedConnectionIter = std::map<sptr<IRemoteObject>, TrackedConnectionRecord>::iterator;
|
||||
using StandardSessionIter = std::list<std::shared_ptr<StandardAgentSession>>::iterator;
|
||||
|
||||
struct AgentDisconnectPlan {
|
||||
sptr<AAFwk::IAbilityConnection> serviceConnection = nullptr;
|
||||
sptr<AgentHostConnection> hostConnection = nullptr;
|
||||
sptr<IRemoteObject> callerRemote = nullptr;
|
||||
AgentHostKey hostKey;
|
||||
bool hasHostKey = false;
|
||||
bool isStandard = false;
|
||||
int32_t standardCallerUid = 0;
|
||||
StandardAgentKey standardKey;
|
||||
};
|
||||
|
||||
AgentManagerService();
|
||||
@@ -195,13 +143,8 @@ private:
|
||||
/**
|
||||
* @brief Finds the tracked record that matches the caller callback object or the fallback caller uid path.
|
||||
*/
|
||||
TrackedConnectionIter FindTrackedConnectionLocked(const sptr<AAFwk::IAbilityConnection> &connection,
|
||||
int32_t callerUid);
|
||||
int32_t PrepareAgentDisconnectLocked(const sptr<AAFwk::IAbilityConnection> &connection,
|
||||
AgentDisconnectPlan &plan);
|
||||
int32_t PrepareLowCodeDisconnectLocked(TrackedConnectionIter it, AgentDisconnectPlan &plan);
|
||||
int32_t PrepareStandardDisconnectLocked(TrackedConnectionIter it, AgentDisconnectPlan &plan);
|
||||
void RollbackAgentDisconnectLocked(const AgentDisconnectPlan &plan);
|
||||
std::map<sptr<IRemoteObject>, TrackedConnectionRecord>::iterator FindTrackedConnectionLocked(
|
||||
const sptr<AAFwk::IAbilityConnection> &connection, int32_t callerUid);
|
||||
void ReleaseCallerConnectionCountByUidLocked(int32_t callerUid);
|
||||
/**
|
||||
* @brief Forwards connect/disconnect completion from the service-side wrapper back to the original caller.
|
||||
@@ -214,12 +157,6 @@ private:
|
||||
const sptr<IRemoteObject> &callerRemote);
|
||||
void HandleCallerConnectionDied(const wptr<IRemoteObject> &remote);
|
||||
void HandleCallerConnectionDied(const sptr<IRemoteObject> &remote);
|
||||
void CleanupDeadStandardConnectionLocked(TrackedConnectionIter it, const sptr<IRemoteObject> &remote,
|
||||
sptr<AAFwk::IAbilityConnection> &serviceConnection);
|
||||
void CleanupDeadLowCodeConnectionLocked(TrackedConnectionIter it, const sptr<IRemoteObject> &remote,
|
||||
sptr<AgentHostConnection> &hostConnection);
|
||||
void DisconnectDeadServiceConnection(const sptr<AAFwk::IAbilityConnection> &serviceConnection);
|
||||
void DisconnectDeadHostConnection(const sptr<AgentHostConnection> &hostConnection);
|
||||
/**
|
||||
* @brief Connect path for LOW_CODE agents, which reuse one shared host session per target host.
|
||||
*/
|
||||
@@ -249,38 +186,6 @@ private:
|
||||
* @brief Extracts the host-session identity from the target element and caller user context.
|
||||
*/
|
||||
AgentHostKey BuildAgentHostKey(const AAFwk::Want &want, int32_t callingUid) const;
|
||||
/**
|
||||
* @brief Builds the identity key for standard agent session deduplication.
|
||||
*/
|
||||
StandardAgentKey BuildStandardAgentKey(int32_t callerUid, const std::string &agentId,
|
||||
const AAFwk::Want &want) const;
|
||||
bool IsStandardAgentKeyEqual(const StandardAgentKey &left, const StandardAgentKey &right) const;
|
||||
bool IsStandardAgentKeyMatched(const StandardAgentKey &storedKey, const StandardAgentKey &incomingKey) const;
|
||||
/**
|
||||
* @brief Finds an existing standard session matching the given key.
|
||||
*/
|
||||
std::shared_ptr<StandardAgentSession> FindStandardSessionLocked(const StandardAgentKey &key) const;
|
||||
StandardSessionIter FindStandardSessionByServiceRemoteLocked(const sptr<IRemoteObject> &serviceRemote);
|
||||
/**
|
||||
* @brief Registers a caller callback against an existing standard session without consuming another quota slot.
|
||||
*/
|
||||
int32_t RegisterStandardSessionCallerLocked(const std::shared_ptr<StandardAgentSession> &session,
|
||||
const sptr<AAFwk::IAbilityConnection> &connection, bool countTowardsCallerLimit);
|
||||
/**
|
||||
* @brief Creates a new collapsed standard session, registers one quota, and issues the real AMS connect.
|
||||
*/
|
||||
int32_t CreateStandardAgentSession(const AAFwk::Want &connectWant, const std::string &agentId,
|
||||
const StandardAgentKey &key, const sptr<AAFwk::IAbilityConnection> &connection);
|
||||
/**
|
||||
* @brief Handles AMS connect completion for a standard collapsed session.
|
||||
*/
|
||||
void HandleStandardAgentConnectDone(const sptr<IRemoteObject> &serviceRemote,
|
||||
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int32_t resultCode);
|
||||
/**
|
||||
* @brief Handles AMS disconnect completion for a standard collapsed session.
|
||||
*/
|
||||
void HandleStandardAgentDisconnectDone(const sptr<IRemoteObject> &serviceRemote,
|
||||
const AppExecFwk::ElementName &element, int32_t resultCode);
|
||||
/**
|
||||
* @brief Marks the target low-code agent as invoked so future callers can detect duplicate activation.
|
||||
*/
|
||||
@@ -318,7 +223,6 @@ private:
|
||||
std::mutex agentHostMutex_;
|
||||
std::map<AgentHostKey, std::shared_ptr<AgentHostSession>> agentHostSessions_;
|
||||
std::map<AgentOwnerKey, std::shared_ptr<AgentHostSession>> agentOwners_;
|
||||
std::list<std::shared_ptr<StandardAgentSession>> standardSessions_;
|
||||
};
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -25,14 +25,12 @@ public:
|
||||
explicit AgentServiceConnection(const sptr<AAFwk::IAbilityConnection> &connection);
|
||||
~AgentServiceConnection() override = default;
|
||||
|
||||
void SetStandardSessionMode();
|
||||
void OnAbilityConnectDone(
|
||||
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode) override;
|
||||
void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
|
||||
|
||||
private:
|
||||
sptr<AAFwk::IAbilityConnection> callerConnection_;
|
||||
bool isStandardSession_ = false;
|
||||
};
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -81,19 +81,6 @@ bool IsMatchedAgentCardTarget(const AAFwk::Want &want, const AgentCard &card)
|
||||
return element.GetModuleName().empty() || card.appInfo->moduleName.empty() ||
|
||||
element.GetModuleName() == card.appInfo->moduleName;
|
||||
}
|
||||
|
||||
void NormalizeConnectAgentTarget(AAFwk::Want &want, const AgentCard &card)
|
||||
{
|
||||
if (card.appInfo == nullptr || card.appInfo->moduleName.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto &element = want.GetElement();
|
||||
if (!element.GetModuleName().empty()) {
|
||||
return;
|
||||
}
|
||||
want.SetElementName(element.GetBundleName(), element.GetAbilityName());
|
||||
want.SetModuleName(card.appInfo->moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
sptr<AgentManagerService> AgentManagerService::GetInstance()
|
||||
@@ -139,7 +126,6 @@ void AgentManagerService::OnStop() noexcept
|
||||
std::lock_guard<std::mutex> lock(connectionLock_);
|
||||
trackedConnections_.clear();
|
||||
callerConnectionCounts_.clear();
|
||||
standardSessions_.clear();
|
||||
}
|
||||
std::lock_guard<std::mutex> hostLock(agentHostMutex_);
|
||||
agentHostSessions_.clear();
|
||||
@@ -359,40 +345,23 @@ int32_t AgentManagerService::ConnectAgentExtensionAbility(const AAFwk::Want &wan
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "connecting %{public}s-%{public}s",
|
||||
connectWant.GetBundle().c_str(), agentId.c_str());
|
||||
|
||||
// Step 5: deduplicate standard agent connections at the service side.
|
||||
StandardAgentKey key = BuildStandardAgentKey(callerUid, agentId, connectWant);
|
||||
AppExecFwk::ElementName cachedElement;
|
||||
sptr<IRemoteObject> cachedRemoteObject = nullptr;
|
||||
int32_t cachedResultCode = ERR_OK;
|
||||
bool notifyCached = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(connectionLock_);
|
||||
auto existing = FindStandardSessionLocked(key);
|
||||
if (existing != nullptr) {
|
||||
ret = RegisterStandardSessionCallerLocked(existing, connection, false);
|
||||
if (ret != ERR_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (existing->state == StandardAgentState::CONNECTING) {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "standard session connecting, append caller");
|
||||
return ERR_OK;
|
||||
}
|
||||
if (existing->state == StandardAgentState::CONNECTED) {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "standard session connected, return cached proxy");
|
||||
cachedElement = existing->cachedElement;
|
||||
cachedRemoteObject = existing->cachedRemoteObject;
|
||||
cachedResultCode = existing->cachedResultCode;
|
||||
notifyCached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notifyCached) {
|
||||
connection->OnAbilityConnectDone(cachedElement, cachedRemoteObject, cachedResultCode);
|
||||
return ERR_OK;
|
||||
// Step 5: create the tracked wrapper connection before talking to AMS.
|
||||
sptr<AAFwk::IAbilityConnection> serviceConnection;
|
||||
ret = RegisterTrackedConnectionAndGetServiceConnection(connection, callerUid, true, serviceConnection);
|
||||
if (ret != ERR_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Step 6: no existing session — create one and issue the real AMS connect.
|
||||
return CreateStandardAgentSession(connectWant, agentId, key, connection);
|
||||
// Step 6: issue the actual extension connect request through AMS.
|
||||
ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbilityWithExtensionType(
|
||||
connectWant, serviceConnection, nullptr, AAFwk::DEFAULT_INVAL_VALUE, AppExecFwk::ExtensionAbilityType::AGENT);
|
||||
if (ret != ERR_OK) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "ConnectAbilityWithExtensionType failed: %{public}d", ret);
|
||||
ReleaseTrackedConnection(connection);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AgentManagerService::ConnectServiceExtensionAbility(const sptr<IRemoteObject> &callerToken,
|
||||
@@ -488,7 +457,6 @@ int32_t AgentManagerService::ResolveConnectAgentTarget(const AAFwk::Want &want,
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "low-code target mismatch");
|
||||
return AAFwk::INVALID_PARAMETERS_ERR;
|
||||
}
|
||||
NormalizeConnectAgentTarget(connectWant, card);
|
||||
|
||||
// Capture the caller UID once the target metadata is known-good.
|
||||
callingUid = IPCSkeleton::GetCallingUid();
|
||||
@@ -610,27 +578,73 @@ int32_t AgentManagerService::DisconnectAgentExtensionAbility(const sptr<AAFwk::I
|
||||
return AAFwk::INVALID_PARAMETERS_ERR;
|
||||
}
|
||||
|
||||
AgentDisconnectPlan plan;
|
||||
sptr<AAFwk::IAbilityConnection> serviceConnection = nullptr;
|
||||
sptr<AgentHostConnection> hostConnection = nullptr;
|
||||
sptr<IRemoteObject> callerRemote = nullptr;
|
||||
AgentHostKey hostKey;
|
||||
bool hasHostKey = false;
|
||||
{
|
||||
std::scoped_lock lock(connectionLock_, agentHostMutex_);
|
||||
auto ret = PrepareAgentDisconnectLocked(connection, plan);
|
||||
if (ret != ERR_OK) {
|
||||
return ret;
|
||||
auto it = FindTrackedConnectionLocked(connection, IPCSkeleton::GetCallingUid());
|
||||
if (it == trackedConnections_.end()) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Connection not tracked");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
callerRemote = it->first;
|
||||
if (it->second.isDisconnecting) {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "Connection is already disconnecting");
|
||||
return ERR_OK;
|
||||
}
|
||||
if (it->second.isLowCode) {
|
||||
auto sessionIter = agentHostSessions_.find(it->second.hostKey);
|
||||
if (sessionIter == agentHostSessions_.end() || sessionIter->second == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Low-code host session missing");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
auto session = sessionIter->second;
|
||||
if (session->isDisconnecting) {
|
||||
return ERR_OK;
|
||||
}
|
||||
session->isDisconnecting = true;
|
||||
it->second.isDisconnecting = true;
|
||||
hostKey = it->second.hostKey;
|
||||
hasHostKey = true;
|
||||
if (!ReleaseCallerConnectionCountLocked(callerRemote)) {
|
||||
session->isDisconnecting = false;
|
||||
it->second.isDisconnecting = false;
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Release caller connection count failed");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
hostConnection = session->hostConnection;
|
||||
} else {
|
||||
it->second.isDisconnecting = true;
|
||||
if (!ReleaseCallerConnectionCountLocked(callerRemote)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Release caller connection count failed");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
serviceConnection = it->second.serviceConnection;
|
||||
}
|
||||
}
|
||||
if (plan.serviceConnection == nullptr && plan.hostConnection == nullptr) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
sptr<AAFwk::IAbilityConnection> disconnectConnection = plan.serviceConnection;
|
||||
if (plan.hostConnection != nullptr) {
|
||||
disconnectConnection = plan.hostConnection;
|
||||
sptr<AAFwk::IAbilityConnection> disconnectConnection = serviceConnection;
|
||||
if (hostConnection != nullptr) {
|
||||
disconnectConnection = hostConnection;
|
||||
}
|
||||
auto ret = IN_PROCESS_CALL(AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(disconnectConnection));
|
||||
if (ret != ERR_OK) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "DisconnectAbility failed: %{public}d", ret);
|
||||
std::scoped_lock lock(connectionLock_, agentHostMutex_);
|
||||
RollbackAgentDisconnectLocked(plan);
|
||||
auto it = trackedConnections_.find(callerRemote);
|
||||
if (hasHostKey) {
|
||||
auto sessionIter = agentHostSessions_.find(hostKey);
|
||||
if (sessionIter != agentHostSessions_.end() && sessionIter->second != nullptr) {
|
||||
sessionIter->second->isDisconnecting = false;
|
||||
}
|
||||
}
|
||||
if (it != trackedConnections_.end() && it->second.isDisconnecting) {
|
||||
it->second.isDisconnecting = false;
|
||||
callerConnectionCounts_[it->second.callerUid]++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -664,7 +678,8 @@ sptr<IRemoteObject> AgentManagerService::GetConnectionIdentityRemote(
|
||||
return connection->AsObject();
|
||||
}
|
||||
|
||||
AgentManagerService::TrackedConnectionIter AgentManagerService::FindTrackedConnectionLocked(
|
||||
std::map<sptr<IRemoteObject>, AgentManagerService::TrackedConnectionRecord>::iterator
|
||||
AgentManagerService::FindTrackedConnectionLocked(
|
||||
const sptr<AAFwk::IAbilityConnection> &connection, int32_t callerUid)
|
||||
{
|
||||
auto end = trackedConnections_.end();
|
||||
@@ -705,115 +720,6 @@ AgentManagerService::TrackedConnectionIter AgentManagerService::FindTrackedConne
|
||||
return matched;
|
||||
}
|
||||
|
||||
int32_t AgentManagerService::PrepareAgentDisconnectLocked(const sptr<AAFwk::IAbilityConnection> &connection,
|
||||
AgentDisconnectPlan &plan)
|
||||
{
|
||||
auto it = FindTrackedConnectionLocked(connection, IPCSkeleton::GetCallingUid());
|
||||
if (it == trackedConnections_.end()) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Connection not tracked");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
plan.callerRemote = it->first;
|
||||
if (it->second.isDisconnecting) {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "Connection is already disconnecting");
|
||||
return ERR_OK;
|
||||
}
|
||||
if (it->second.isLowCode) {
|
||||
return PrepareLowCodeDisconnectLocked(it, plan);
|
||||
}
|
||||
return PrepareStandardDisconnectLocked(it, plan);
|
||||
}
|
||||
|
||||
int32_t AgentManagerService::PrepareLowCodeDisconnectLocked(TrackedConnectionIter it, AgentDisconnectPlan &plan)
|
||||
{
|
||||
auto sessionIter = agentHostSessions_.find(it->second.hostKey);
|
||||
if (sessionIter == agentHostSessions_.end() || sessionIter->second == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Low-code host session missing");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
auto session = sessionIter->second;
|
||||
if (session->isDisconnecting) {
|
||||
return ERR_OK;
|
||||
}
|
||||
session->isDisconnecting = true;
|
||||
it->second.isDisconnecting = true;
|
||||
plan.hostKey = it->second.hostKey;
|
||||
plan.hasHostKey = true;
|
||||
if (!ReleaseCallerConnectionCountLocked(plan.callerRemote)) {
|
||||
session->isDisconnecting = false;
|
||||
it->second.isDisconnecting = false;
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Release caller connection count failed");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
plan.hostConnection = session->hostConnection;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AgentManagerService::PrepareStandardDisconnectLocked(TrackedConnectionIter it, AgentDisconnectPlan &plan)
|
||||
{
|
||||
const auto &stdKey = it->second.standardKey;
|
||||
if (stdKey.callerUid != 0 && !stdKey.agentId.empty()) {
|
||||
auto sessionIt = std::find_if(standardSessions_.begin(), standardSessions_.end(),
|
||||
[this, &stdKey](const auto &item) {
|
||||
return item != nullptr && IsStandardAgentKeyEqual(item->key, stdKey);
|
||||
});
|
||||
if (sessionIt != standardSessions_.end() && *sessionIt != nullptr) {
|
||||
auto &session = *sessionIt;
|
||||
if (session->isDisconnecting) {
|
||||
TAG_LOGI(AAFwkTag::SER_ROUTER, "standard session already disconnecting");
|
||||
return ERR_OK;
|
||||
}
|
||||
session->isDisconnecting = true;
|
||||
it->second.isDisconnecting = true;
|
||||
plan.serviceConnection = session->serviceConnection;
|
||||
plan.isStandard = true;
|
||||
plan.standardCallerUid = session->key.callerUid;
|
||||
plan.standardKey = session->key;
|
||||
ReleaseCallerConnectionCountByUidLocked(plan.standardCallerUid);
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
it->second.isDisconnecting = true;
|
||||
if (!ReleaseCallerConnectionCountLocked(plan.callerRemote)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Release caller connection count failed");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
plan.serviceConnection = it->second.serviceConnection;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void AgentManagerService::RollbackAgentDisconnectLocked(const AgentDisconnectPlan &plan)
|
||||
{
|
||||
auto it = trackedConnections_.find(plan.callerRemote);
|
||||
if (plan.hasHostKey) {
|
||||
auto sessionIter = agentHostSessions_.find(plan.hostKey);
|
||||
if (sessionIter != agentHostSessions_.end() && sessionIter->second != nullptr) {
|
||||
sessionIter->second->isDisconnecting = false;
|
||||
}
|
||||
}
|
||||
if (plan.isStandard) {
|
||||
auto sessionIt = std::find_if(standardSessions_.begin(), standardSessions_.end(),
|
||||
[this, &plan](const auto &item) {
|
||||
return item != nullptr && IsStandardAgentKeyEqual(item->key, plan.standardKey);
|
||||
});
|
||||
if (sessionIt != standardSessions_.end() && *sessionIt != nullptr) {
|
||||
(*sessionIt)->isDisconnecting = false;
|
||||
}
|
||||
if (plan.standardCallerUid != 0) {
|
||||
callerConnectionCounts_[plan.standardCallerUid]++;
|
||||
}
|
||||
}
|
||||
if (it != trackedConnections_.end() && it->second.isDisconnecting) {
|
||||
it->second.isDisconnecting = false;
|
||||
if (!plan.isStandard) {
|
||||
callerConnectionCounts_[it->second.callerUid]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t AgentManagerService::DisconnectServiceExtensionAbility(const sptr<IRemoteObject> &callerToken,
|
||||
const sptr<AAFwk::IAbilityConnection> &connection)
|
||||
{
|
||||
@@ -1067,66 +973,53 @@ void AgentManagerService::TransferLowCodeCallerLimitLocked(const std::shared_ptr
|
||||
}
|
||||
}
|
||||
|
||||
void AgentManagerService::CleanupDeadStandardConnectionLocked(TrackedConnectionIter it,
|
||||
const sptr<IRemoteObject> &remote, sptr<AAFwk::IAbilityConnection> &serviceConnection)
|
||||
void AgentManagerService::HandleCallerConnectionDied(const sptr<IRemoteObject> &remote)
|
||||
{
|
||||
serviceConnection = it->second.serviceConnection;
|
||||
auto &stdKey = it->second.standardKey;
|
||||
if (stdKey.callerUid != 0 && !stdKey.agentId.empty()) {
|
||||
auto sessionIt = std::find_if(standardSessions_.begin(), standardSessions_.end(),
|
||||
[this, &stdKey](const auto &item) {
|
||||
return item != nullptr && IsStandardAgentKeyEqual(item->key, stdKey);
|
||||
});
|
||||
if (sessionIt != standardSessions_.end() && *sessionIt != nullptr) {
|
||||
serviceConnection = (*sessionIt)->serviceConnection;
|
||||
for (const auto &callerRemote : (*sessionIt)->callerRemotes) {
|
||||
if (callerRemote != remote) {
|
||||
ReleaseTrackedConnectionByRemoteLocked(callerRemote);
|
||||
sptr<AAFwk::IAbilityConnection> serviceConnection = nullptr;
|
||||
sptr<AgentHostConnection> hostConnection = nullptr;
|
||||
{
|
||||
std::scoped_lock lock(connectionLock_, agentHostMutex_);
|
||||
if (remote == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto it = trackedConnections_.find(remote);
|
||||
if (it == trackedConnections_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!it->second.isLowCode) {
|
||||
serviceConnection = it->second.serviceConnection;
|
||||
ReleaseTrackedConnectionByRemoteLocked(remote);
|
||||
} else {
|
||||
auto sessionIter = agentHostSessions_.find(it->second.hostKey);
|
||||
if (sessionIter != agentHostSessions_.end() && sessionIter->second != nullptr) {
|
||||
auto session = sessionIter->second;
|
||||
session->callerConnections.erase(remote);
|
||||
for (auto agentIter = session->agents.begin(); agentIter != session->agents.end();) {
|
||||
if (agentIter->second.callerRemote == remote) {
|
||||
agentOwners_.erase(AgentOwnerKey { session->hostUid, agentIter->first });
|
||||
agentIter = session->agents.erase(agentIter);
|
||||
continue;
|
||||
}
|
||||
++agentIter;
|
||||
}
|
||||
if (!session->isDisconnecting && session->agents.empty()) {
|
||||
session->isDisconnecting = true;
|
||||
hostConnection = session->hostConnection;
|
||||
} else {
|
||||
TransferLowCodeCallerLimitLocked(session, remote);
|
||||
}
|
||||
}
|
||||
standardSessions_.erase(sessionIt);
|
||||
ReleaseTrackedConnectionByRemoteLocked(remote);
|
||||
}
|
||||
}
|
||||
ReleaseTrackedConnectionByRemoteLocked(remote);
|
||||
}
|
||||
|
||||
void AgentManagerService::CleanupDeadLowCodeConnectionLocked(TrackedConnectionIter it,
|
||||
const sptr<IRemoteObject> &remote, sptr<AgentHostConnection> &hostConnection)
|
||||
{
|
||||
auto sessionIter = agentHostSessions_.find(it->second.hostKey);
|
||||
if (sessionIter != agentHostSessions_.end() && sessionIter->second != nullptr) {
|
||||
auto session = sessionIter->second;
|
||||
session->callerConnections.erase(remote);
|
||||
for (auto agentIter = session->agents.begin(); agentIter != session->agents.end();) {
|
||||
if (agentIter->second.callerRemote == remote) {
|
||||
agentOwners_.erase(AgentOwnerKey { session->hostUid, agentIter->first });
|
||||
agentIter = session->agents.erase(agentIter);
|
||||
continue;
|
||||
}
|
||||
++agentIter;
|
||||
}
|
||||
if (!session->isDisconnecting && session->agents.empty()) {
|
||||
session->isDisconnecting = true;
|
||||
hostConnection = session->hostConnection;
|
||||
} else {
|
||||
TransferLowCodeCallerLimitLocked(session, remote);
|
||||
}
|
||||
}
|
||||
ReleaseTrackedConnectionByRemoteLocked(remote);
|
||||
}
|
||||
|
||||
void AgentManagerService::DisconnectDeadServiceConnection(const sptr<AAFwk::IAbilityConnection> &serviceConnection)
|
||||
{
|
||||
if (serviceConnection != nullptr) {
|
||||
auto ret = IN_PROCESS_CALL(AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(serviceConnection));
|
||||
if (ret != ERR_OK) {
|
||||
TAG_LOGW(AAFwkTag::SER_ROUTER, "DisconnectAbility after caller death failed: %{public}d", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AgentManagerService::DisconnectDeadHostConnection(const sptr<AgentHostConnection> &hostConnection)
|
||||
{
|
||||
if (hostConnection != nullptr) {
|
||||
auto ret = IN_PROCESS_CALL(AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(hostConnection));
|
||||
if (ret != ERR_OK) {
|
||||
@@ -1143,30 +1036,6 @@ void AgentManagerService::DisconnectDeadHostConnection(const sptr<AgentHostConne
|
||||
}
|
||||
}
|
||||
|
||||
void AgentManagerService::HandleCallerConnectionDied(const sptr<IRemoteObject> &remote)
|
||||
{
|
||||
sptr<AAFwk::IAbilityConnection> serviceConnection = nullptr;
|
||||
sptr<AgentHostConnection> hostConnection = nullptr;
|
||||
{
|
||||
std::scoped_lock lock(connectionLock_, agentHostMutex_);
|
||||
if (remote == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto it = trackedConnections_.find(remote);
|
||||
if (it == trackedConnections_.end()) {
|
||||
return;
|
||||
}
|
||||
if (it->second.isLowCode) {
|
||||
CleanupDeadLowCodeConnectionLocked(it, remote, hostConnection);
|
||||
} else {
|
||||
CleanupDeadStandardConnectionLocked(it, remote, serviceConnection);
|
||||
}
|
||||
}
|
||||
|
||||
DisconnectDeadServiceConnection(serviceConnection);
|
||||
DisconnectDeadHostConnection(hostConnection);
|
||||
}
|
||||
|
||||
void AgentManagerService::HandleCallerConnectionDied(const wptr<IRemoteObject> &remote)
|
||||
{
|
||||
auto remoteObject = remote.promote();
|
||||
@@ -1519,207 +1388,5 @@ void AgentManagerService::ClearAgentHostSessionLocked(const AgentHostKey &key)
|
||||
}
|
||||
agentHostSessions_.erase(sessionIter);
|
||||
}
|
||||
|
||||
AgentManagerService::StandardAgentKey AgentManagerService::BuildStandardAgentKey(
|
||||
int32_t callerUid, const std::string &agentId, const AAFwk::Want &want) const
|
||||
{
|
||||
StandardAgentKey key;
|
||||
key.callerUid = callerUid;
|
||||
key.agentId = agentId;
|
||||
const auto &element = want.GetElement();
|
||||
key.bundleName = element.GetBundleName();
|
||||
key.moduleName = element.GetModuleName();
|
||||
key.abilityName = element.GetAbilityName();
|
||||
return key;
|
||||
}
|
||||
|
||||
bool AgentManagerService::IsStandardAgentKeyEqual(const StandardAgentKey &left, const StandardAgentKey &right) const
|
||||
{
|
||||
return left.callerUid == right.callerUid && left.agentId == right.agentId &&
|
||||
left.bundleName == right.bundleName && left.moduleName == right.moduleName &&
|
||||
left.abilityName == right.abilityName;
|
||||
}
|
||||
|
||||
bool AgentManagerService::IsStandardAgentKeyMatched(
|
||||
const StandardAgentKey &storedKey, const StandardAgentKey &incomingKey) const
|
||||
{
|
||||
return storedKey.callerUid == incomingKey.callerUid && storedKey.agentId == incomingKey.agentId &&
|
||||
storedKey.bundleName == incomingKey.bundleName && storedKey.abilityName == incomingKey.abilityName &&
|
||||
(storedKey.moduleName.empty() || incomingKey.moduleName.empty() ||
|
||||
storedKey.moduleName == incomingKey.moduleName);
|
||||
}
|
||||
|
||||
std::shared_ptr<AgentManagerService::StandardAgentSession> AgentManagerService::FindStandardSessionLocked(
|
||||
const StandardAgentKey &key) const
|
||||
{
|
||||
for (const auto &entry : standardSessions_) {
|
||||
if (entry != nullptr && IsStandardAgentKeyMatched(entry->key, key)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AgentManagerService::StandardSessionIter AgentManagerService::FindStandardSessionByServiceRemoteLocked(
|
||||
const sptr<IRemoteObject> &serviceRemote)
|
||||
{
|
||||
return std::find_if(standardSessions_.begin(), standardSessions_.end(),
|
||||
[&serviceRemote](const auto &item) {
|
||||
return item != nullptr && item->serviceConnection != nullptr &&
|
||||
item->serviceConnection->AsObject() == serviceRemote;
|
||||
});
|
||||
}
|
||||
|
||||
int32_t AgentManagerService::RegisterStandardSessionCallerLocked(
|
||||
const std::shared_ptr<StandardAgentSession> &session,
|
||||
const sptr<AAFwk::IAbilityConnection> &connection, bool countTowardsCallerLimit)
|
||||
{
|
||||
if (session == nullptr || connection == nullptr || session->serviceConnection == nullptr) {
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
auto callerRemote = GetConnectionIdentityRemote(connection);
|
||||
if (callerRemote == nullptr) {
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
auto trackedIt = trackedConnections_.find(callerRemote);
|
||||
if (trackedIt == trackedConnections_.end()) {
|
||||
auto ret = TryRegisterConnectionLocked(connection, session->key.callerUid,
|
||||
session->serviceConnection, nullptr, countTowardsCallerLimit);
|
||||
if (ret != ERR_OK) {
|
||||
return ret;
|
||||
}
|
||||
trackedIt = trackedConnections_.find(callerRemote);
|
||||
} else if (trackedIt->second.standardKey.callerUid != 0 &&
|
||||
!IsStandardAgentKeyEqual(trackedIt->second.standardKey, session->key)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "Connection already belongs to another standard session");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (trackedIt != trackedConnections_.end()) {
|
||||
trackedIt->second.standardKey = session->key;
|
||||
}
|
||||
if (std::find(session->callerRemotes.begin(), session->callerRemotes.end(), callerRemote) ==
|
||||
session->callerRemotes.end()) {
|
||||
session->callerRemotes.push_back(callerRemote);
|
||||
}
|
||||
auto &callbacks = session->state == StandardAgentState::CONNECTED ?
|
||||
session->connectedCallbacks : session->pendingCallbacks;
|
||||
if (std::find(callbacks.begin(), callbacks.end(), connection) == callbacks.end()) {
|
||||
callbacks.push_back(connection);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AgentManagerService::CreateStandardAgentSession(const AAFwk::Want &connectWant,
|
||||
const std::string &agentId, const StandardAgentKey &key,
|
||||
const sptr<AAFwk::IAbilityConnection> &connection)
|
||||
{
|
||||
auto serviceConnection = sptr<AgentServiceConnection>::MakeSptr(connection);
|
||||
if (serviceConnection == nullptr) {
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
serviceConnection->SetStandardSessionMode();
|
||||
|
||||
auto session = std::make_shared<StandardAgentSession>();
|
||||
session->key = key;
|
||||
session->state = StandardAgentState::CONNECTING;
|
||||
session->serviceConnection = serviceConnection;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(connectionLock_);
|
||||
auto ret = RegisterStandardSessionCallerLocked(session, connection, true);
|
||||
if (ret != ERR_OK) {
|
||||
return ret;
|
||||
}
|
||||
standardSessions_.emplace_back(session);
|
||||
}
|
||||
|
||||
auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbilityWithExtensionType(
|
||||
connectWant, serviceConnection, nullptr, AAFwk::DEFAULT_INVAL_VALUE, AppExecFwk::ExtensionAbilityType::AGENT);
|
||||
if (ret != ERR_OK) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "ConnectAbilityWithExtensionType failed: %{public}d", ret);
|
||||
ReleaseTrackedConnection(connection);
|
||||
std::lock_guard<std::mutex> lock(connectionLock_);
|
||||
auto sessionIt = FindStandardSessionByServiceRemoteLocked(serviceConnection->AsObject());
|
||||
if (sessionIt != standardSessions_.end()) {
|
||||
standardSessions_.erase(sessionIt);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void AgentManagerService::HandleStandardAgentConnectDone(
|
||||
const sptr<IRemoteObject> &serviceRemote,
|
||||
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
|
||||
{
|
||||
std::vector<sptr<AAFwk::IAbilityConnection>> callbacks;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(connectionLock_);
|
||||
auto sessionIt = FindStandardSessionByServiceRemoteLocked(serviceRemote);
|
||||
if (sessionIt == standardSessions_.end() || *sessionIt == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto &session = *sessionIt;
|
||||
session->cachedElement = element;
|
||||
session->cachedRemoteObject = remoteObject;
|
||||
session->cachedResultCode = resultCode;
|
||||
|
||||
if (resultCode == ERR_OK && remoteObject != nullptr) {
|
||||
session->state = StandardAgentState::CONNECTED;
|
||||
callbacks = session->pendingCallbacks;
|
||||
session->pendingCallbacks.clear();
|
||||
// Move all pending callers to connectedCallbacks for disconnect notification
|
||||
session->connectedCallbacks.insert(session->connectedCallbacks.end(),
|
||||
callbacks.begin(), callbacks.end());
|
||||
} else {
|
||||
// Connect failed: clean up the entire collapsed session
|
||||
callbacks = session->pendingCallbacks;
|
||||
session->pendingCallbacks.clear();
|
||||
standardSessions_.erase(sessionIt);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &cb : callbacks) {
|
||||
if (cb != nullptr) {
|
||||
cb->OnAbilityConnectDone(element, remoteObject, resultCode);
|
||||
}
|
||||
if (resultCode != ERR_OK) {
|
||||
ReleaseTrackedConnection(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AgentManagerService::HandleStandardAgentDisconnectDone(
|
||||
const sptr<IRemoteObject> &serviceRemote,
|
||||
const AppExecFwk::ElementName &element, int32_t resultCode)
|
||||
{
|
||||
std::vector<sptr<AAFwk::IAbilityConnection>> callbacks;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(connectionLock_);
|
||||
auto sessionIt = FindStandardSessionByServiceRemoteLocked(serviceRemote);
|
||||
if (sessionIt == standardSessions_.end() || *sessionIt == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto &session = *sessionIt;
|
||||
// Collect all callers: pending + connected
|
||||
callbacks = session->pendingCallbacks;
|
||||
session->pendingCallbacks.clear();
|
||||
callbacks.insert(callbacks.end(),
|
||||
session->connectedCallbacks.begin(), session->connectedCallbacks.end());
|
||||
session->connectedCallbacks.clear();
|
||||
// Erase session bookkeeping
|
||||
standardSessions_.erase(sessionIt);
|
||||
}
|
||||
|
||||
for (const auto &cb : callbacks) {
|
||||
if (cb != nullptr) {
|
||||
cb->OnAbilityDisconnectDone(element, resultCode);
|
||||
HandleConnectionDone(cb, resultCode, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -23,21 +23,9 @@ AgentServiceConnection::AgentServiceConnection(const sptr<AAFwk::IAbilityConnect
|
||||
: callerConnection_(connection)
|
||||
{}
|
||||
|
||||
void AgentServiceConnection::SetStandardSessionMode()
|
||||
{
|
||||
isStandardSession_ = true;
|
||||
}
|
||||
|
||||
void AgentServiceConnection::OnAbilityConnectDone(
|
||||
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
|
||||
{
|
||||
if (isStandardSession_) {
|
||||
auto service = AgentManagerService::GetInstance();
|
||||
if (service != nullptr) {
|
||||
service->HandleStandardAgentConnectDone(AsObject(), element, remoteObject, resultCode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (callerConnection_ != nullptr) {
|
||||
callerConnection_->OnAbilityConnectDone(element, remoteObject, resultCode);
|
||||
}
|
||||
@@ -49,13 +37,6 @@ void AgentServiceConnection::OnAbilityConnectDone(
|
||||
|
||||
void AgentServiceConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
|
||||
{
|
||||
if (isStandardSession_) {
|
||||
auto service = AgentManagerService::GetInstance();
|
||||
if (service != nullptr) {
|
||||
service->HandleStandardAgentDisconnectDone(AsObject(), element, resultCode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (callerConnection_ != nullptr) {
|
||||
callerConnection_->OnAbilityDisconnectDone(element, resultCode);
|
||||
}
|
||||
|
||||
+3
-83
@@ -884,9 +884,9 @@ HWTEST_F(AgentConnectionManagerTest, MatchConnection_001, TestSize.Level1)
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : MatchConnection_ShouldReturnTrue_WhenAgentExtProxyDiffers
|
||||
* @tc.name : MatchConnection_ShouldReturnFalse_WhenAgentExtProxyDiffers
|
||||
* @tc.number: MatchConnection_002
|
||||
* @tc.desc : Test MatchConnection returns true when only agentExtProxy differs
|
||||
* @tc.desc : Test MatchConnection returns false when agentExtProxy differs
|
||||
*/
|
||||
HWTEST_F(AgentConnectionManagerTest, MatchConnection_002, TestSize.Level1)
|
||||
{
|
||||
@@ -908,7 +908,7 @@ HWTEST_F(AgentConnectionManagerTest, MatchConnection_002, TestSize.Level1)
|
||||
|
||||
auto &connectionEntry = *AgentConnectionManager::GetInstance().agentConnections_.begin();
|
||||
auto result = AgentConnectionManager::GetInstance().MatchConnection("testAgent", want, connectionEntry);
|
||||
EXPECT_TRUE(result);
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -959,30 +959,6 @@ HWTEST_F(AgentConnectionManagerTest, MatchConnection_004, TestSize.Level1)
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : MatchConnection_ShouldReturnTrue_WhenModuleNameIsEmpty
|
||||
* @tc.number: MatchConnection_007
|
||||
* @tc.desc : Test MatchConnection returns true when the user-passed Want does not specify moduleName
|
||||
*/
|
||||
HWTEST_F(AgentConnectionManagerTest, MatchConnection_007, TestSize.Level1)
|
||||
{
|
||||
Want want;
|
||||
want.SetParam(AGENTID_KEY, std::string("testAgent"));
|
||||
want.SetElementName("", "test.bundle", "test.ability");
|
||||
|
||||
Want want2;
|
||||
want2.SetParam(AGENTID_KEY, std::string("testAgent"));
|
||||
want2.SetElementName("", "test.bundle", "test.ability", "test.module");
|
||||
|
||||
MyFlag::retConnectAgentExtensionAbility = ERR_OK;
|
||||
sptr<MockAbilityConnectCallback> callback = new MockAbilityConnectCallback();
|
||||
AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want2, callback);
|
||||
|
||||
auto &connectionEntry = *AgentConnectionManager::GetInstance().agentConnections_.begin();
|
||||
auto result = AgentConnectionManager::GetInstance().MatchConnection("testAgent", want, connectionEntry);
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : MatchConnection_ShouldReturnFalse_WhenAbilityNameDiffers
|
||||
* @tc.number: MatchConnection_005
|
||||
@@ -1264,62 +1240,6 @@ HWTEST_F(AgentConnectionManagerTest, ConnectAbilityInner_002, TestSize.Level1)
|
||||
EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.size(), static_cast<size_t>(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : ConnectAbilityInner_ShouldReuseConnection_WhenHostProxyDiffers
|
||||
* @tc.number: ConnectAbilityInner_004
|
||||
* @tc.desc : Test ConnectAbilityInner reuses connection for same agent and target with different host proxies
|
||||
*/
|
||||
HWTEST_F(AgentConnectionManagerTest, ConnectAbilityInner_004, TestSize.Level1)
|
||||
{
|
||||
Want want1;
|
||||
want1.SetParam(AGENTID_KEY, std::string("testAgent"));
|
||||
want1.SetElementName("", "test.bundle", "test.ability", "test.module");
|
||||
sptr<IRemoteObject> remoteObj1 = sptr<MockIRemoteObject>::MakeSptr();
|
||||
want1.SetParam(AGENTEXTENSIONHOSTPROXY_KEY, remoteObj1);
|
||||
|
||||
Want want2;
|
||||
want2.SetParam(AGENTID_KEY, std::string("testAgent"));
|
||||
want2.SetElementName("", "test.bundle", "test.ability", "test.module");
|
||||
sptr<IRemoteObject> remoteObj2 = sptr<MockIRemoteObject>::MakeSptr();
|
||||
want2.SetParam(AGENTEXTENSIONHOSTPROXY_KEY, remoteObj2);
|
||||
|
||||
MyFlag::retConnectAgentExtensionAbility = ERR_OK;
|
||||
sptr<MockAbilityConnectCallback> callback1 = new MockAbilityConnectCallback();
|
||||
auto result = AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want1, callback1);
|
||||
EXPECT_EQ(result, ERR_OK);
|
||||
|
||||
sptr<MockAbilityConnectCallback> callback2 = new MockAbilityConnectCallback();
|
||||
result = AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want2, callback2);
|
||||
EXPECT_EQ(result, ERR_OK);
|
||||
EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.size(), static_cast<size_t>(1));
|
||||
EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.begin()->second.size(), static_cast<size_t>(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : ConnectAbilityInner_ShouldCreateNewConnection_WhenExplicitModuleNameDiffers
|
||||
* @tc.number: ConnectAbilityInner_005
|
||||
* @tc.desc : Test ConnectAbilityInner keeps same abilityName in different explicit modules separate
|
||||
*/
|
||||
HWTEST_F(AgentConnectionManagerTest, ConnectAbilityInner_005, TestSize.Level1)
|
||||
{
|
||||
Want want1;
|
||||
want1.SetParam(AGENTID_KEY, std::string("testAgent"));
|
||||
want1.SetElementName("", "test.bundle", "test.ability", "moduleA");
|
||||
|
||||
Want want2;
|
||||
want2.SetParam(AGENTID_KEY, std::string("testAgent"));
|
||||
want2.SetElementName("", "test.bundle", "test.ability", "moduleB");
|
||||
|
||||
MyFlag::retConnectAgentExtensionAbility = ERR_OK;
|
||||
sptr<MockAbilityConnectCallback> callback1 = new MockAbilityConnectCallback();
|
||||
EXPECT_EQ(AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want1, callback1), ERR_OK);
|
||||
|
||||
sptr<MockAbilityConnectCallback> callback2 = new MockAbilityConnectCallback();
|
||||
EXPECT_EQ(AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want2, callback2), ERR_OK);
|
||||
|
||||
EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.size(), static_cast<size_t>(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : ConnectAbilityInner_ShouldRemoveConnection_WhenStateIsDisconnected (L394 coverage)
|
||||
* @tc.number: ConnectAbilityInner_003
|
||||
|
||||
+2
-1155
File diff suppressed because it is too large
Load Diff
-197
@@ -71,7 +71,6 @@ public:
|
||||
auto service = AgentManagerService::GetInstance();
|
||||
service->trackedConnections_.clear();
|
||||
service->callerConnectionCounts_.clear();
|
||||
service->standardSessions_.clear();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -148,201 +147,5 @@ HWTEST_F(AgentServiceConnectionTest, OnAbilityDisconnectDone_001, TestSize.Level
|
||||
EXPECT_TRUE(service->trackedConnections_.empty());
|
||||
EXPECT_TRUE(service->callerConnectionCounts_.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : SetStandardSessionMode_001
|
||||
* @tc.number: SetStandardSessionMode_001
|
||||
* @tc.desc : Test SetStandardSessionMode sets the internal flag
|
||||
*/
|
||||
HWTEST_F(AgentServiceConnectionTest, SetStandardSessionMode_001, TestSize.Level1)
|
||||
{
|
||||
auto callerConnection = sptr<TrackingAbilityConnection>::MakeSptr();
|
||||
auto agentConnection = sptr<AgentServiceConnection>::MakeSptr(callerConnection);
|
||||
|
||||
EXPECT_FALSE(agentConnection->isStandardSession_);
|
||||
agentConnection->SetStandardSessionMode();
|
||||
EXPECT_TRUE(agentConnection->isStandardSession_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : OnAbilityConnectDone_003
|
||||
* @tc.number: OnAbilityConnectDone_003
|
||||
* @tc.desc : Test standard session mode connect done routes to HandleStandardAgentConnectDone and notifies all
|
||||
* pending callers
|
||||
*/
|
||||
HWTEST_F(AgentServiceConnectionTest, OnAbilityConnectDone_003, TestSize.Level1)
|
||||
{
|
||||
auto service = AgentManagerService::GetInstance();
|
||||
|
||||
// Build a standard session with two pending callers
|
||||
auto caller1 = sptr<TrackingAbilityConnection>::MakeSptr();
|
||||
auto caller2 = sptr<TrackingAbilityConnection>::MakeSptr();
|
||||
|
||||
AgentManagerService::StandardAgentKey key;
|
||||
key.callerUid = 100;
|
||||
key.agentId = "testAgent";
|
||||
key.bundleName = "test.bundle";
|
||||
key.abilityName = "TestAbility";
|
||||
|
||||
auto session = std::make_shared<AgentManagerService::StandardAgentSession>();
|
||||
session->key = key;
|
||||
session->state = AgentManagerService::StandardAgentState::CONNECTING;
|
||||
session->pendingCallbacks.push_back(caller1);
|
||||
session->pendingCallbacks.push_back(caller2);
|
||||
|
||||
auto agentConnection = sptr<AgentServiceConnection>::MakeSptr(nullptr);
|
||||
agentConnection->SetStandardSessionMode();
|
||||
session->serviceConnection = agentConnection;
|
||||
|
||||
// Register the session so HandleStandardAgentConnectDone can find it
|
||||
service->standardSessions_.emplace_back(session);
|
||||
|
||||
// Simulate AMS connect done
|
||||
AppExecFwk::ElementName element("", "test.bundle", "TestAbility");
|
||||
sptr<IRemoteObject> remoteObject = new (std::nothrow) IPCObjectStub(u"test.remote");
|
||||
agentConnection->OnAbilityConnectDone(element, remoteObject, ERR_OK);
|
||||
|
||||
// Both pending callers should be notified
|
||||
EXPECT_EQ(caller1->connectDoneCount, 1);
|
||||
EXPECT_EQ(caller1->lastResultCode, ERR_OK);
|
||||
EXPECT_EQ(caller1->lastRemoteObject, remoteObject);
|
||||
EXPECT_EQ(caller2->connectDoneCount, 1);
|
||||
EXPECT_EQ(caller2->lastResultCode, ERR_OK);
|
||||
EXPECT_EQ(caller2->lastRemoteObject, remoteObject);
|
||||
|
||||
// Session should be CONNECTED and pendingCallbacks should be empty
|
||||
EXPECT_EQ(session->state, AgentManagerService::StandardAgentState::CONNECTED);
|
||||
EXPECT_TRUE(session->pendingCallbacks.empty());
|
||||
// Both should be in connectedCallbacks now
|
||||
EXPECT_EQ(session->connectedCallbacks.size(), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : OnAbilityConnectDone_004
|
||||
* @tc.number: OnAbilityConnectDone_004
|
||||
* @tc.desc : Test standard session mode connect failure cleans up session and notifies pending callers
|
||||
*/
|
||||
HWTEST_F(AgentServiceConnectionTest, OnAbilityConnectDone_004, TestSize.Level1)
|
||||
{
|
||||
auto service = AgentManagerService::GetInstance();
|
||||
|
||||
auto caller1 = sptr<TrackingAbilityConnection>::MakeSptr();
|
||||
|
||||
AgentManagerService::StandardAgentKey key;
|
||||
key.callerUid = 100;
|
||||
key.agentId = "testAgent";
|
||||
key.bundleName = "test.bundle";
|
||||
key.abilityName = "TestAbility";
|
||||
|
||||
auto session = std::make_shared<AgentManagerService::StandardAgentSession>();
|
||||
session->key = key;
|
||||
session->state = AgentManagerService::StandardAgentState::CONNECTING;
|
||||
session->pendingCallbacks.push_back(caller1);
|
||||
|
||||
auto agentConnection = sptr<AgentServiceConnection>::MakeSptr(nullptr);
|
||||
agentConnection->SetStandardSessionMode();
|
||||
session->serviceConnection = agentConnection;
|
||||
|
||||
service->standardSessions_.emplace_back(session);
|
||||
|
||||
// Simulate AMS connect failure
|
||||
AppExecFwk::ElementName element("", "test.bundle", "TestAbility");
|
||||
agentConnection->OnAbilityConnectDone(element, nullptr, ERR_INVALID_VALUE);
|
||||
|
||||
// Caller should be notified of failure
|
||||
EXPECT_EQ(caller1->connectDoneCount, 1);
|
||||
EXPECT_EQ(caller1->lastResultCode, ERR_INVALID_VALUE);
|
||||
|
||||
// Session should be cleaned up
|
||||
EXPECT_TRUE(service->standardSessions_.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : OnAbilityDisconnectDone_002
|
||||
* @tc.number: OnAbilityDisconnectDone_002
|
||||
* @tc.desc : Test standard session mode disconnect done notifies all callers and cleans up session
|
||||
*/
|
||||
HWTEST_F(AgentServiceConnectionTest, OnAbilityDisconnectDone_002, TestSize.Level1)
|
||||
{
|
||||
auto service = AgentManagerService::GetInstance();
|
||||
|
||||
auto caller1 = sptr<TrackingAbilityConnection>::MakeSptr();
|
||||
auto caller2 = sptr<TrackingAbilityConnection>::MakeSptr();
|
||||
|
||||
AgentManagerService::StandardAgentKey key;
|
||||
key.callerUid = 100;
|
||||
key.agentId = "testAgent";
|
||||
key.bundleName = "test.bundle";
|
||||
key.abilityName = "TestAbility";
|
||||
|
||||
auto session = std::make_shared<AgentManagerService::StandardAgentSession>();
|
||||
session->key = key;
|
||||
session->state = AgentManagerService::StandardAgentState::CONNECTED;
|
||||
session->connectedCallbacks.push_back(caller1);
|
||||
session->connectedCallbacks.push_back(caller2);
|
||||
|
||||
auto agentConnection = sptr<AgentServiceConnection>::MakeSptr(nullptr);
|
||||
agentConnection->SetStandardSessionMode();
|
||||
session->serviceConnection = agentConnection;
|
||||
|
||||
// Also set up a tracked connection for the first caller so HandleConnectionDone can clean up
|
||||
AgentManagerService::TrackedConnectionRecord record;
|
||||
record.callerUid = 100;
|
||||
record.isDisconnecting = true;
|
||||
service->trackedConnections_.emplace(caller1->AsObject(), record);
|
||||
|
||||
service->standardSessions_.emplace_back(session);
|
||||
|
||||
// Simulate AMS disconnect done
|
||||
AppExecFwk::ElementName element("", "test.bundle", "TestAbility");
|
||||
agentConnection->OnAbilityDisconnectDone(element, ERR_OK);
|
||||
|
||||
// Both callers should be notified
|
||||
EXPECT_EQ(caller1->disconnectDoneCount, 1);
|
||||
EXPECT_EQ(caller1->lastResultCode, ERR_OK);
|
||||
EXPECT_EQ(caller2->disconnectDoneCount, 1);
|
||||
EXPECT_EQ(caller2->lastResultCode, ERR_OK);
|
||||
|
||||
// Session should be cleaned up
|
||||
EXPECT_TRUE(service->standardSessions_.empty());
|
||||
EXPECT_TRUE(service->trackedConnections_.empty());
|
||||
EXPECT_TRUE(service->callerConnectionCounts_.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name : OnAbilityConnectDone_005
|
||||
* @tc.number: OnAbilityConnectDone_005
|
||||
* @tc.desc : Test standard session mode does not forward to callerConnection (which is null)
|
||||
*/
|
||||
HWTEST_F(AgentServiceConnectionTest, OnAbilityConnectDone_005, TestSize.Level1)
|
||||
{
|
||||
auto service = AgentManagerService::GetInstance();
|
||||
|
||||
AgentManagerService::StandardAgentKey key;
|
||||
key.callerUid = 100;
|
||||
key.agentId = "testAgent";
|
||||
key.bundleName = "test.bundle";
|
||||
key.abilityName = "TestAbility";
|
||||
|
||||
auto session = std::make_shared<AgentManagerService::StandardAgentSession>();
|
||||
session->key = key;
|
||||
session->state = AgentManagerService::StandardAgentState::CONNECTING;
|
||||
// No pending callbacks — session mode should still work without crash
|
||||
|
||||
auto agentConnection = sptr<AgentServiceConnection>::MakeSptr(nullptr);
|
||||
agentConnection->SetStandardSessionMode();
|
||||
session->serviceConnection = agentConnection;
|
||||
|
||||
service->standardSessions_.emplace_back(session);
|
||||
|
||||
AppExecFwk::ElementName element("", "test.bundle", "TestAbility");
|
||||
sptr<IRemoteObject> remoteObject = new (std::nothrow) IPCObjectStub(u"test.remote");
|
||||
// Should not crash even with no pending callbacks
|
||||
agentConnection->OnAbilityConnectDone(element, remoteObject, ERR_OK);
|
||||
|
||||
EXPECT_EQ(session->state, AgentManagerService::StandardAgentState::CONNECTED);
|
||||
EXPECT_TRUE(session->pendingCallbacks.empty());
|
||||
EXPECT_TRUE(session->connectedCallbacks.empty());
|
||||
}
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
|
||||
Reference in New Issue
Block a user