bugfix: agent connection not reused -- framework

Co-Authored-By: Agent

Signed-off-by: yangxuguang-huawei <yangxuguang3@huawei.com>
This commit is contained in:
yangxuguang-huawei
2026-06-08 15:27:05 +08:00
parent 05f4c691be
commit fe825a1c7a
9 changed files with 217 additions and 116 deletions
@@ -76,15 +76,13 @@ int64_t InsertAgentConnection(sptr<EtsAgentConnection> connection, const AAFwk::
void FindAgentConnection(int64_t connectId, sptr<EtsAgentConnection> &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<EtsAgentConnection> &connection);
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<EtsAgentConnection> &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.
@@ -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<EtsAgentConnection> &connection
}
}
void FindAgentConnection(ani_env *env, AAFwk::Want &want, ani_object callback,
sptr<EtsAgentConnection> &connection)
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<EtsAgentConnection> &connection)
{
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by want+callback");
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by target");
std::lock_guard<std::recursive_mutex> 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)
@@ -57,12 +57,12 @@ class EtsAgentServiceConnection;
std::map<int64_t, sptr<EtsAgentServiceConnection>> 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<EtsAgentConnection> 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;
}
@@ -77,15 +77,13 @@ int64_t InsertAgentConnection(sptr<JSAgentConnection> connection, const AAFwk::W
void FindAgentConnection(int64_t connectId, sptr<JSAgentConnection> &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<JSAgentConnection> &connection);
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<JSAgentConnection> &connection);
}
class JsAgentConnectorStubImpl;
@@ -33,6 +33,22 @@ 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 {
@@ -93,21 +109,13 @@ void FindAgentConnection(int64_t connectId, sptr<JSAgentConnection> &connection)
}
}
void FindAgentConnection(napi_env env, AAFwk::Want &want, napi_value callback,
sptr<JSAgentConnection> &connection)
void FindAgentConnection(const AAFwk::Want &want, const std::string &agentId, sptr<JSAgentConnection> &connection)
{
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by want+callback");
TAG_LOGD(AAFwkTag::SER_ROUTER, "FindAgentConnection by target");
std::lock_guard<std::recursive_mutex> 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<NativeReference> &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");
@@ -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<JSAgentConnection> 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<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");
result = 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);
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<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,7 +17,8 @@
#define OHOS_AGENT_RUNTIME_AGENT_CONNECTION_MANAGER_H
#include <chrono>
#include <map>
#include <functional>
#include <list>
#include <mutex>
#include <vector>
@@ -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> 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<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;
}
};
/**
@@ -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<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 std::map<AgentConnectionInfo,
std::vector<sptr<AbilityRuntime::AbilityConnectCallback>>>::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<AgentConnectionInfo, std::vector<sptr<AbilityRuntime::AbilityConnectCallback>>> agentConnections_;
AgentConnectionRecords agentConnections_;
};
} // namespace AgentRuntime
} // namespace OHOS
@@ -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<AgentConnectionInfo, std::vector<sptr<AbilityConnectCallback>>>::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<std::mutex> 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<std::mutex> 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;
}
@@ -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<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
@@ -1240,6 +1264,62 @@ 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