mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-24 12:43:16 -04:00
bugfix: agent connection not reused -- framework
Co-Authored-By: Agent Signed-off-by: yangxuguang-huawei <yangxuguang3@huawei.com>
This commit is contained in:
+4
-6
@@ -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.
|
||||
|
||||
+45
-19
@@ -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;
|
||||
}
|
||||
|
||||
+3
-5
@@ -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;
|
||||
|
||||
+20
-12
@@ -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;
|
||||
}
|
||||
|
||||
+83
-3
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user