diff --git a/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/include/connection/ets_agent_connection.h b/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/include/connection/ets_agent_connection.h index 931a539b13..8f0e329c39 100644 --- a/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/include/connection/ets_agent_connection.h +++ b/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/include/connection/ets_agent_connection.h @@ -76,15 +76,13 @@ int64_t InsertAgentConnection(sptr connection, const AAFwk:: void FindAgentConnection(int64_t connectId, sptr &connection); /** - * Find agent connection by want and callback. + * Find agent connection by target identity. * - * @param env The ANI environment. * @param want The want information to match. - * @param callback The callback object to match. + * @param agentId The agent ID to match. * @param connection Output parameter for the found connection. */ -void FindAgentConnection(ani_env *env, AAFwk::Want &want, ani_object callback, - sptr &connection); +void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr &connection); } class EtsAgentConnectorStubImpl; @@ -164,7 +162,7 @@ public: * * @param duplicatedCallback The callback object from ETS. */ - void AddDuplicatedPendingCallback(ani_object duplicatedCallback); + bool AddDuplicatedPendingCallback(ani_object duplicatedCallback); /** * Resolve all duplicated pending callbacks with the proxy. diff --git a/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/src/connection/ets_agent_connection.cpp b/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/src/connection/ets_agent_connection.cpp index b86b26c061..7ac9925d56 100644 --- a/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/src/connection/ets_agent_connection.cpp +++ b/agent_runtime_framework/frameworks/ets/ani/agent_extension_ability/src/connection/ets_agent_connection.cpp @@ -37,6 +37,22 @@ 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 { @@ -101,21 +117,13 @@ void FindAgentConnection(int64_t connectId, sptr &connection } } -void FindAgentConnection(ani_env *env, AAFwk::Want &want, ani_object callback, - sptr &connection) +void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr &connection) { - TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by want+callback"); + TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by target"); std::lock_guard lock(g_agentConnectsLock_); auto item = std::find_if(g_agentConnects.begin(), g_agentConnects.end(), - [&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; + [&want, &agentId](const auto &obj) { + return IsSameAgentConnection(obj.first.want, want, agentId); }); if (item == g_agentConnects.end()) { TAG_LOGD(AAFwkTag::SER_ROUTER, "Connection not found"); @@ -276,13 +284,14 @@ void EtsAgentConnection::ReleaseObjectReference(ani_ref etsObjRef) TAG_LOGE(AAFwkTag::SER_ROUTER, "etsVm_ or etsObjRef null"); return; } - 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); + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SER_ROUTER, "AttachAniEnv failed"); return; } ReleaseObjectReference(env, etsObjRef); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); } void EtsAgentConnection::CallObjectMethod(ani_env *env, const char *methodName, const char *signature, ...) @@ -371,14 +380,31 @@ void EtsAgentConnection::SetAniAsyncCallback(ani_object asyncCallback) TAG_LOGD(AAFwkTag::SER_ROUTER, "SetAniAsyncCallback success"); } -void EtsAgentConnection::AddDuplicatedPendingCallback(ani_object duplicatedCallback) +bool EtsAgentConnection::AddDuplicatedPendingCallback(ani_object duplicatedCallback) { TAG_LOGD(AAFwkTag::SER_ROUTER, "AddDuplicatedPendingCallback"); if (duplicatedCallback == nullptr) { TAG_LOGE(AAFwkTag::SER_ROUTER, "duplicatedCallback is null"); - return; + return false; } - duplicatedPendingCallbacks_.push_back(duplicatedCallback); + 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; } void EtsAgentConnection::ResolveDuplicatedPendingCallbacks(ani_env *env, ani_object proxyObj) diff --git a/agent_runtime_framework/frameworks/ets/ani/agent_manager/src/ets_agent_manager.cpp b/agent_runtime_framework/frameworks/ets/ani/agent_manager/src/ets_agent_manager.cpp index 2779e3ba60..2ff033697c 100644 --- a/agent_runtime_framework/frameworks/ets/ani/agent_manager/src/ets_agent_manager.cpp +++ b/agent_runtime_framework/frameworks/ets/ani/agent_manager/src/ets_agent_manager.cpp @@ -57,12 +57,12 @@ class EtsAgentServiceConnection; std::map> g_serviceConnections; int64_t g_serviceConnectionSerialNumber = 0; -bool CheckConnectAlreadyExist(ani_env *env, AAFwk::Want &want, - ani_object callback, ani_object asyncCallback) +bool CheckConnectAlreadyExist(ani_env *env, const AAFwk::Want &want, const std::string &agentId, + ani_object asyncCallback) { TAG_LOGD(AAFwkTag::SER_ROUTER, "CheckConnectAlreadyExist called"); sptr connection = nullptr; - AgentConnectionUtils::FindAgentConnection(env, want, callback, connection); + AgentConnectionUtils::FindAgentConnection(want, agentId, connection); if (connection == nullptr) { TAG_LOGD(AAFwkTag::SER_ROUTER, "null connection"); return false; @@ -70,7 +70,10 @@ bool CheckConnectAlreadyExist(ani_env *env, AAFwk::Want &want, ani_ref proxy = connection->GetProxyObject(); if (proxy == nullptr) { TAG_LOGW(AAFwkTag::SER_ROUTER, "null proxy"); - connection->AddDuplicatedPendingCallback(asyncCallback); + if (!connection->AddDuplicatedPendingCallback(asyncCallback)) { + AsyncCallback(env, SIGNATURE_AGENT_ASYNC_CALLBACK_WRAPPER, asyncCallback, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER), nullptr); + } } else { TAG_LOGI(AAFwkTag::SER_ROUTER, "Resolve, got proxy object"); AsyncCallback(env, SIGNATURE_AGENT_ASYNC_CALLBACK_WRAPPER, asyncCallback, @@ -531,7 +534,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, callbackObj, asyncCallback)) { + if (CheckConnectAlreadyExist(env, want, agentId, asyncCallback)) { TAG_LOGI(AAFwkTag::SER_ROUTER, "Duplicate connection found"); return; } diff --git a/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/include/connection/js_agent_connection.h b/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/include/connection/js_agent_connection.h index 7252efadc1..62bddf9799 100644 --- a/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/include/connection/js_agent_connection.h +++ b/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/include/connection/js_agent_connection.h @@ -77,15 +77,13 @@ int64_t InsertAgentConnection(sptr connection, const AAFwk::W void FindAgentConnection(int64_t connectId, sptr &connection); /** - * Find agent connection by want and callback. + * Find agent connection by target identity. * - * @param env The N-API environment. * @param want The want information to match. - * @param callback The callback object to match. + * @param agentId The agent ID to match. * @param connection Output parameter for the found connection. */ -void FindAgentConnection(napi_env env, AAFwk::Want &want, napi_value callback, - sptr &connection); +void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr &connection); } class JsAgentConnectorStubImpl; diff --git a/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/src/connection/js_agent_connection.cpp b/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/src/connection/js_agent_connection.cpp index b6eaee812d..e4b995d593 100644 --- a/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/src/connection/js_agent_connection.cpp +++ b/agent_runtime_framework/frameworks/js/napi/agent_extension_ability/src/connection/js_agent_connection.cpp @@ -33,6 +33,22 @@ constexpr int32_t ARGC_ONE = 1; static std::map, 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 { @@ -93,21 +109,13 @@ void FindAgentConnection(int64_t connectId, sptr &connection) } } -void FindAgentConnection(napi_env env, AAFwk::Want &want, napi_value callback, - sptr &connection) +void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr &connection) { - TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by want+callback"); + TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by target"); std::lock_guard lock(g_agentConnectsLock_); auto item = std::find_if(g_agentConnects.begin(), g_agentConnects.end(), - [&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 &tempCallbackPtr = obj.second->GetJsConnectionObject(); - bool callbackObjectEquals = - JSAgentConnection::IsJsCallbackObjectEquals(env, tempCallbackPtr, callback); - return wantEquals && callbackObjectEquals; + [&want, &agentId](const auto &obj) { + return IsSameAgentConnection(obj.first.want, want, agentId); }); if (item == g_agentConnects.end()) { TAG_LOGD(AAFwkTag::SER_ROUTER, "Connection not found"); diff --git a/agent_runtime_framework/frameworks/js/napi/agent_manager/src/js_agent_manager.cpp b/agent_runtime_framework/frameworks/js/napi/agent_manager/src/js_agent_manager.cpp index 9eb220ef8e..bd7ab6420f 100644 --- a/agent_runtime_framework/frameworks/js/napi/agent_manager/src/js_agent_manager.cpp +++ b/agent_runtime_framework/frameworks/js/napi/agent_manager/src/js_agent_manager.cpp @@ -54,6 +54,7 @@ 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; @@ -232,13 +233,12 @@ void RemoveServiceConnection(int64_t connectionId) } // Helper function to check for duplicate connections -bool CheckConnectAlreadyExist(napi_env env, AAFwk::Want &want, - napi_value callback, napi_value &result) +bool CheckConnectAlreadyExist(napi_env env, const AAFwk::Want &want, const std::string &agentId, napi_value &result) { TAG_LOGD(AAFwkTag::SER_ROUTER, "CheckConnectAlreadyExist called"); sptr connection = nullptr; - AgentConnectionUtils::FindAgentConnection(env, want, callback, connection); + AgentConnectionUtils::FindAgentConnection(want, agentId, connection); if (connection == nullptr) { TAG_LOGD(AAFwkTag::SER_ROUTER, "No duplicate connection found"); return false; @@ -251,13 +251,27 @@ bool CheckConnectAlreadyExist(napi_env env, AAFwk::Want &want, TAG_LOGD(AAFwkTag::SER_ROUTER, "Proxy not ready, queuing pending task"); std::unique_ptr asyncTask = CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result); + if (asyncTask == nullptr) { + TAG_LOGE(AAFwkTag::SER_ROUTER, "Create async task failed"); + ThrowError(env, static_cast(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"); - result = proxy; + std::unique_ptr asyncTask = + CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result); + if (asyncTask == nullptr) { + TAG_LOGE(AAFwkTag::SER_ROUTER, "Create async task failed"); + ThrowError(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER), INTERNAL_ERROR_MSG); + result = CreateJsUndefined(env); + return true; + } + asyncTask->ResolveWithNoError(env, proxy); return true; } @@ -566,7 +580,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, callbackObject, result); + bool duplicated = CheckConnectAlreadyExist(env, want, agentId, result); if (duplicated) { TAG_LOGI(AAFwkTag::SER_ROUTER, "Duplicated connection found"); return result; @@ -655,6 +669,11 @@ napi_value JsAgentManager::ScheduleAgentConnection(napi_env env, const AAFwk::Wa napi_value result = nullptr; std::unique_ptr asyncTask = CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result); + if (asyncTask == nullptr) { + TAG_LOGE(AAFwkTag::SER_ROUTER, "Create async task failed"); + ThrowError(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER), INTERNAL_ERROR_MSG); + return CreateJsUndefined(env); + } std::shared_ptr asyncTaskShared = std::move(asyncTask); connection->SetNapiAsyncTask(asyncTaskShared); diff --git a/agent_runtime_framework/interfaces/inner_api/include/agent_connection_manager.h b/agent_runtime_framework/interfaces/inner_api/include/agent_connection_manager.h index 2c4d2cd747..ae33c8e0c7 100644 --- a/agent_runtime_framework/interfaces/inner_api/include/agent_connection_manager.h +++ b/agent_runtime_framework/interfaces/inner_api/include/agent_connection_manager.h @@ -17,7 +17,8 @@ #define OHOS_AGENT_RUNTIME_AGENT_CONNECTION_MANAGER_H #include -#include +#include +#include #include #include @@ -39,7 +40,7 @@ class AgentConnection; * @struct AgentConnectionInfo * @brief Stores information about an agent connection. * - * The connection key consists of: agentId + agentExtProxy + connectReceiver + * The connection key consists of: agentId + connectReceiver */ struct AgentConnectionInfo { // Target agent identifier (from Want parameter AGENTID_KEY) @@ -49,8 +50,8 @@ struct AgentConnectionInfo { AAFwk::Operation connectReceiver; // The connection object sptr agentConnection; - // Agent extension proxy for bidirectional communication - // (from Want parameter AGENTEXTENSIONHOSTPROXY_KEY) + // Agent extension host proxy from Want parameter AGENTEXTENSIONHOSTPROXY_KEY. + // It is per API call and is not part of the reusable connection identity. void *agentExtProxy = nullptr; // Connection timestamp for timeout detection int64_t connectingTime = 0; @@ -83,47 +84,6 @@ struct AgentConnectionInfo { auto now = std::chrono::steady_clock::now().time_since_epoch(); connectingTime = std::chrono::duration_cast(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; - } }; /** @@ -170,7 +130,7 @@ private: * @brief Manages connections to AgentExtensionAbility instances. * * This class is similar to ConnectionManager but specifically for agent extensions. - * Connections are identified by: agentId + agentExtProxy + connectReceiver. + * Connections are identified by: agentId + connectReceiver. */ class AgentConnectionManager { public: @@ -255,16 +215,19 @@ private: */ void *GetAgentExtProxyPtr(const AAFwk::Want &want); /** - * @brief Match connection by agentId + agentExtProxy + connectReceiver. + * @brief Match connection by agentId + 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>; + using AgentConnectionRecord = std::pair; + using AgentConnectionRecords = std::list; + bool MatchConnection(const std::string &agentId, const AAFwk::Want &connectReceiver, - const std::map>>::value_type &connection); + const AgentConnectionRecord &connection); /** * @brief Create a new connection to the agent extension. * @@ -293,7 +256,7 @@ private: private: std::mutex connectionsLock_; - std::map>> agentConnections_; + AgentConnectionRecords agentConnections_; }; } // namespace AgentRuntime } // namespace OHOS diff --git a/agent_runtime_framework/interfaces/inner_api/src/agent_connection_manager.cpp b/agent_runtime_framework/interfaces/inner_api/src/agent_connection_manager.cpp index f0afcff79b..c4104f4004 100644 --- a/agent_runtime_framework/interfaces/inner_api/src/agent_connection_manager.cpp +++ b/agent_runtime_framework/interfaces/inner_api/src/agent_connection_manager.cpp @@ -242,22 +242,23 @@ void *AgentConnectionManager::GetAgentExtProxyPtr(const AAFwk::Want &want) } bool AgentConnectionManager::MatchConnection(const std::string &agentId, const AAFwk::Want &connectReceiver, - const std::map>>::value_type &connection) + const AgentConnectionRecord &connection) { // 1. Match by agentId if (agentId != connection.first.agentId) { return false; } - // 2. Match by agentExtProxy - void *agentExtProxy = GetAgentExtProxyPtr(connectReceiver); - if (agentExtProxy != connection.first.agentExtProxy) { + // 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()) { return false; } - // 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(); + const std::string &moduleName = element.GetModuleName(); + const std::string &storedModuleName = storedReceiver.GetModuleName(); + return moduleName.empty() || storedModuleName.empty() || moduleName == storedModuleName; } ErrCode AgentConnectionManager::CreateConnection(const AAFwk::Want &want, @@ -281,14 +282,19 @@ ErrCode AgentConnectionManager::CreateConnection(const AAFwk::Want &want, { std::lock_guard lock(connectionsLock_); - agentConnections_[connectionInfo] = { connectCallback }; + agentConnections_.emplace_back(connectionInfo, AgentConnectionCallbacks { connectCallback }); } ErrCode ret = AgentManagerClient::GetInstance().ConnectAgentExtensionAbility(want, agentConnection); if (ret != ERR_OK) { TAG_LOGE(AAFwkTag::SER_ROUTER, "error:%{public}d", ret); std::lock_guard lock(connectionsLock_); - agentConnections_.erase(connectionInfo); + for (auto iter = agentConnections_.begin(); iter != agentConnections_.end(); ++iter) { + if (iter->first.agentConnection == agentConnection) { + agentConnections_.erase(iter); + break; + } + } } return ret; } diff --git a/test/unittest/agent_runtime_framework/agent_connection_manager_test/agent_connection_manager_test.cpp b/test/unittest/agent_runtime_framework/agent_connection_manager_test/agent_connection_manager_test.cpp index 1706841732..dede936c0e 100644 --- a/test/unittest/agent_runtime_framework/agent_connection_manager_test/agent_connection_manager_test.cpp +++ b/test/unittest/agent_runtime_framework/agent_connection_manager_test/agent_connection_manager_test.cpp @@ -884,9 +884,9 @@ HWTEST_F(AgentConnectionManagerTest, MatchConnection_001, TestSize.Level1) } /** -* @tc.name : MatchConnection_ShouldReturnFalse_WhenAgentExtProxyDiffers +* @tc.name : MatchConnection_ShouldReturnTrue_WhenAgentExtProxyDiffers * @tc.number: MatchConnection_002 -* @tc.desc : Test MatchConnection returns false when agentExtProxy differs +* @tc.desc : Test MatchConnection returns true when only 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_FALSE(result); + EXPECT_TRUE(result); } /** @@ -959,6 +959,30 @@ 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 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 @@ -1240,6 +1264,62 @@ HWTEST_F(AgentConnectionManagerTest, ConnectAbilityInner_002, TestSize.Level1) EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.size(), static_cast(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 remoteObj1 = sptr::MakeSptr(); + want1.SetParam(AGENTEXTENSIONHOSTPROXY_KEY, remoteObj1); + + Want want2; + want2.SetParam(AGENTID_KEY, std::string("testAgent")); + want2.SetElementName("", "test.bundle", "test.ability", "test.module"); + sptr remoteObj2 = sptr::MakeSptr(); + want2.SetParam(AGENTEXTENSIONHOSTPROXY_KEY, remoteObj2); + + MyFlag::retConnectAgentExtensionAbility = ERR_OK; + sptr callback1 = new MockAbilityConnectCallback(); + auto result = AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want1, callback1); + EXPECT_EQ(result, ERR_OK); + + sptr callback2 = new MockAbilityConnectCallback(); + result = AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want2, callback2); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.size(), static_cast(1)); + EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.begin()->second.size(), static_cast(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 callback1 = new MockAbilityConnectCallback(); + EXPECT_EQ(AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want1, callback1), ERR_OK); + + sptr callback2 = new MockAbilityConnectCallback(); + EXPECT_EQ(AgentConnectionManager::GetInstance().ConnectAgentExtensionAbility(want2, callback2), ERR_OK); + + EXPECT_EQ(AgentConnectionManager::GetInstance().agentConnections_.size(), static_cast(2)); +} + /** * @tc.name : ConnectAbilityInner_ShouldRemoveConnection_WhenStateIsDisconnected (L394 coverage) * @tc.number: ConnectAbilityInner_003