description:修复ActsServiceAbilityClientTest用例失败问题

Signed-off-by: 孙旭辉 <sunxuhui7@huawei.com>
This commit is contained in:
孙旭辉
2024-06-22 12:29:29 +08:00
parent 0c21188852
commit e7dc2a01ac
4 changed files with 448 additions and 445 deletions
@@ -24,11 +24,16 @@
#include "napi_common_ability_wrap_utils.h"
#include "napi_common_util.h"
#include "napi_context.h"
#include "napi_remote_object.h"
using namespace OHOS::AbilityRuntime;
namespace OHOS {
namespace AppExecFwk {
static std::map<ConnectionKey, sptr<NAPIAbilityConnection>, key_compare> connects_;
static std::mutex g_connectionsLock_;
static int64_t serialNumber_ = 0;
JsNapiCommon::JsNapiCommon() : ability_(nullptr)
{}
@@ -1430,5 +1435,348 @@ void JsNapiCommon::AddFreeInstallObserver(napi_env env, const AAFwk::Want &want,
freeInstallObserver_->AddJsObserverObject(bundleName, abilityName, startTime, callback, result);
}
}
void ClearCallbackWork(uv_work_t* req, int)
{
std::unique_ptr<uv_work_t> work(req);
if (!req) {
TAG_LOGE(AAFwkTag::JSNAPI, "work null");
return;
}
std::unique_ptr<ConnectionCallback> callback(reinterpret_cast<ConnectionCallback*>(req->data));
if (!callback) {
TAG_LOGE(AAFwkTag::JSNAPI, "data null");
return;
}
callback->Reset();
}
void ConnectionCallback::Reset()
{
auto engine = reinterpret_cast<NativeEngine*>(env);
if (engine == nullptr) {
removeKey = nullptr;
return;
}
if (pthread_self() == engine->GetTid()) {
TAG_LOGD(AAFwkTag::JSNAPI, "in-js-thread");
if (connectCallbackRef) {
napi_delete_reference(env, connectCallbackRef);
connectCallbackRef = nullptr;
}
if (disconnectCallbackRef) {
napi_delete_reference(env, disconnectCallbackRef);
disconnectCallbackRef = nullptr;
}
if (failedCallbackRef) {
napi_delete_reference(env, failedCallbackRef);
failedCallbackRef = nullptr;
}
env = nullptr;
removeKey = nullptr;
return;
}
TAG_LOGI(AAFwkTag::JSNAPI, "not in-js-thread");
auto loop = engine->GetUVLoop();
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, loop == nullptr.", __func__);
env = nullptr;
removeKey = nullptr;
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "work == nullptr.");
return;
}
ConnectionCallback *data = new(std::nothrow) ConnectionCallback(std::move(*this));
work->data = data;
auto ret = uv_queue_work(loop, work, [](uv_work_t*) {}, ClearCallbackWork);
if (ret != 0) {
TAG_LOGE(AAFwkTag::JSNAPI, "uv_queue_work failed: %{public}d", ret);
data->env = nullptr;
data->removeKey = nullptr;
delete data;
delete work;
}
}
void NAPIAbilityConnection::AddConnectionCallback(std::shared_ptr<ConnectionCallback> callback)
{
std::lock_guard<std::mutex> guard(lock_);
callbacks_.emplace_back(callback);
}
int NAPIAbilityConnection::GetConnectionState() const
{
std::lock_guard<std::mutex> guard(lock_);
return connectionState_;
}
void NAPIAbilityConnection::SetConnectionState(int connectionState)
{
std::lock_guard<std::mutex> guard(lock_);
connectionState_ = connectionState;
}
size_t NAPIAbilityConnection::GetCallbackSize()
{
std::lock_guard<std::mutex> guard(lock_);
return callbacks_.size();
}
size_t NAPIAbilityConnection::RemoveAllCallbacks(ConnectRemoveKeyType key)
{
size_t result = 0;
std::lock_guard<std::mutex> guard(lock_);
for (auto it = callbacks_.begin(); it != callbacks_.end();) {
auto callback = *it;
if (callback && callback->removeKey == key) {
it = callbacks_.erase(it);
result++;
} else {
++it;
}
}
TAG_LOGI(AAFwkTag::JSNAPI, "RemoveAllCallbacks removed size:%{public}zu, left size:%{public}zu", result,
callbacks_.size());
return result;
}
void UvWorkOnAbilityConnectDone(uv_work_t *work, int status)
{
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, uv_queue_work");
std::unique_ptr<uv_work_t> managedWork(work);
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, work is null");
return;
}
// JS Thread
std::unique_ptr<ConnectAbilityCB> connectAbilityCB(static_cast<ConnectAbilityCB *>(work->data));
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, connectAbilityCB is null");
return;
}
CallbackInfo &cbInfo = connectAbilityCB->cbBase.cbInfo;
napi_handle_scope scope = nullptr;
napi_open_handle_scope(cbInfo.env, &scope);
if (scope == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "napi_open_handle_scope failed");
return;
}
napi_value globalValue;
napi_get_global(cbInfo.env, &globalValue);
napi_value func;
napi_get_named_property(cbInfo.env, globalValue, "requireNapi", &func);
napi_value rpcInfo;
napi_create_string_utf8(cbInfo.env, "rpc", NAPI_AUTO_LENGTH, &rpcInfo);
napi_value funcArgv[1] = { rpcInfo };
napi_value returnValue;
napi_call_function(cbInfo.env, globalValue, func, 1, funcArgv, &returnValue);
napi_value result[ARGS_TWO] = {nullptr};
result[PARAM0] =
WrapElementName(cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName);
napi_value jsRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(
cbInfo.env, connectAbilityCB->abilityConnectionCB.connection);
result[PARAM1] = jsRemoteObject;
napi_value callback = nullptr;
napi_value undefined = nullptr;
napi_get_undefined(cbInfo.env, &undefined);
napi_value callResult = nullptr;
napi_get_reference_value(cbInfo.env, cbInfo.callback, &callback);
napi_call_function(
cbInfo.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
if (cbInfo.callback != nullptr) {
napi_delete_reference(cbInfo.env, cbInfo.callback);
}
napi_close_handle_scope(cbInfo.env, scope);
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, uv_queue_work end");
}
void NAPIAbilityConnection::HandleOnAbilityConnectDone(ConnectionCallback &callback, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s called.", __func__);
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(callback.env, &loop);
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, loop == null.", __func__);
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, work == null.", __func__);
return;
}
ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB;
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, connectAbilityCB == null.", __func__);
if (work != nullptr) {
delete work;
work = nullptr;
}
return;
}
connectAbilityCB->cbBase.cbInfo.env = callback.env;
connectAbilityCB->cbBase.cbInfo.callback = callback.connectCallbackRef;
callback.connectCallbackRef = nullptr;
connectAbilityCB->abilityConnectionCB.elementName = element_;
connectAbilityCB->abilityConnectionCB.resultCode = resultCode;
connectAbilityCB->abilityConnectionCB.connection = serviceRemoteObject_;
work->data = static_cast<void *>(connectAbilityCB);
int rev = uv_queue_work_with_qos(
loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityConnectDone, uv_qos_user_initiated);
if (rev != 0) {
if (connectAbilityCB != nullptr) {
delete connectAbilityCB;
connectAbilityCB = nullptr;
}
if (work != nullptr) {
delete work;
work = nullptr;
}
}
}
void NAPIAbilityConnection::OnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s bundleName:%{public}s abilityName:%{public}s, resultCode:%{public}d",
__func__, element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
if (remoteObject == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, remoteObject == nullptr.", __func__);
return;
}
std::lock_guard<std::mutex> guard(lock_);
element_ = element;
serviceRemoteObject_ = remoteObject;
for (const auto &callback : callbacks_) {
HandleOnAbilityConnectDone(*callback, resultCode);
}
connectionState_ = CONNECTION_STATE_CONNECTED;
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s, end.", __func__);
}
void UvWorkOnAbilityDisconnectDone(uv_work_t *work, int status)
{
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, uv_queue_work");
std::unique_ptr<uv_work_t> managedWork(work);
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, work is null");
return;
}
// JS Thread
std::unique_ptr<ConnectAbilityCB> connectAbilityCB(static_cast<ConnectAbilityCB *>(work->data));
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, connectAbilityCB is null");
return;
}
CallbackInfo &cbInfo = connectAbilityCB->cbBase.cbInfo;
napi_handle_scope scope = nullptr;
napi_open_handle_scope(cbInfo.env, &scope);
if (scope == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "napi_open_handle_scope failed");
return;
}
napi_value result = WrapElementName(cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName);
if (cbInfo.callback != nullptr) {
napi_value callback = nullptr;
napi_value callResult = nullptr;
napi_value undefined = nullptr;
napi_get_undefined(cbInfo.env, &undefined);
napi_get_reference_value(cbInfo.env, cbInfo.callback, &callback);
napi_call_function(cbInfo.env, undefined, callback, ARGS_ONE, &result, &callResult);
napi_delete_reference(cbInfo.env, cbInfo.callback);
cbInfo.callback = nullptr;
}
napi_close_handle_scope(cbInfo.env, scope);
// release connect
std::lock_guard<std::mutex> lock(g_connectionsLock_);
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone connects_.size:%{public}zu", connects_.size());
std::string deviceId = connectAbilityCB->abilityConnectionCB.elementName.GetDeviceID();
std::string bundleName = connectAbilityCB->abilityConnectionCB.elementName.GetBundleName();
std::string abilityName = connectAbilityCB->abilityConnectionCB.elementName.GetAbilityName();
auto item = std::find_if(connects_.begin(), connects_.end(),
[deviceId, bundleName, abilityName](const std::map<ConnectionKey,
sptr<NAPIAbilityConnection>>::value_type &obj) {
return (deviceId == obj.first.want.GetDeviceId()) &&
(bundleName == obj.first.want.GetBundle()) &&
(abilityName == obj.first.want.GetElement().GetAbilityName());
});
if (item != connects_.end()) {
// match deviceid & bundlename && abilityname
connects_.erase(item);
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone erase connects_.size:%{public}zu", connects_.size());
}
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, uv_queue_work end");
}
void NAPIAbilityConnection::HandleOnAbilityDisconnectDone(ConnectionCallback &callback, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s called.", __func__);
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(callback.env, &loop);
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, loop == nullptr.", __func__);
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "work == nullptr.");
return;
}
ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB;
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, connectAbilityCB == nullptr.", __func__);
if (work != nullptr) {
delete work;
work = nullptr;
}
return;
}
connectAbilityCB->cbBase.cbInfo.env = callback.env;
connectAbilityCB->cbBase.cbInfo.callback = callback.disconnectCallbackRef;
callback.disconnectCallbackRef = nullptr;
connectAbilityCB->abilityConnectionCB.elementName = element_;
connectAbilityCB->abilityConnectionCB.resultCode = resultCode;
work->data = static_cast<void *>(connectAbilityCB);
int rev = uv_queue_work(
loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityDisconnectDone);
if (rev != 0) {
if (connectAbilityCB != nullptr) {
delete connectAbilityCB;
connectAbilityCB = nullptr;
}
if (work != nullptr) {
delete work;
work = nullptr;
}
}
}
void NAPIAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s bundleName:%{public}s abilityName:%{public}s, resultCode:%{public}d",
__func__, element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
std::lock_guard<std::mutex> guard(lock_);
element_ = element;
for (const auto &callback : callbacks_) {
HandleOnAbilityDisconnectDone(*callback, resultCode);
}
connectionState_ = CONNECTION_STATE_DISCONNECTED;
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s, end.", __func__);
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -15,6 +15,8 @@
#ifndef OHOS_ABILITY_RUNTIME_JS_NAPI_COMMON_ABILITY_H
#define OHOS_ABILITY_RUNTIME_JS_NAPI_COMMON_ABILITY_H
#include "ability_connect_callback_stub.h"
#include "ability_info.h"
#include "ability_manager_errors.h"
#include "application_info.h"
@@ -143,6 +145,104 @@ public:
Ability *ability_;
sptr<AbilityRuntime::JsFreeInstallObserver> freeInstallObserver_ = nullptr;
};
enum {
CONNECTION_STATE_DISCONNECTED = -1,
CONNECTION_STATE_CONNECTED = 0,
CONNECTION_STATE_CONNECTING = 1
};
using ConnectRemoveKeyType = JsNapiCommon*;
struct ConnectionCallback {
ConnectionCallback(napi_env env, napi_value cbInfo, ConnectRemoveKeyType key)
{
this->env = env;
napi_value jsMethod = nullptr;
napi_get_named_property(env, cbInfo, "onConnect", &jsMethod);
napi_create_reference(env, jsMethod, 1, &connectCallbackRef);
napi_get_named_property(env, cbInfo, "onDisconnect", &jsMethod);
napi_create_reference(env, jsMethod, 1, &disconnectCallbackRef);
napi_get_named_property(env, cbInfo, "onFailed", &jsMethod);
napi_create_reference(env, jsMethod, 1, &failedCallbackRef);
removeKey = key;
}
ConnectionCallback(ConnectionCallback &) = delete;
ConnectionCallback(ConnectionCallback &&other)
: env(other.env), connectCallbackRef(other.connectCallbackRef),
disconnectCallbackRef(other.disconnectCallbackRef), failedCallbackRef(other.failedCallbackRef),
removeKey(other.removeKey)
{
other.env = nullptr;
other.connectCallbackRef = nullptr;
other.disconnectCallbackRef = nullptr;
other.failedCallbackRef = nullptr;
other.removeKey = nullptr;
}
const ConnectionCallback &operator=(ConnectionCallback &) = delete;
const ConnectionCallback &operator=(ConnectionCallback &&other)
{
Reset();
env = other.env;
connectCallbackRef = other.connectCallbackRef;
disconnectCallbackRef = other.disconnectCallbackRef;
failedCallbackRef = other.failedCallbackRef;
other.env = nullptr;
other.connectCallbackRef = nullptr;
other.disconnectCallbackRef = nullptr;
other.failedCallbackRef = nullptr;
other.removeKey = nullptr;
return *this;
}
~ConnectionCallback()
{
Reset();
}
void Reset();
napi_env env = nullptr;
napi_ref connectCallbackRef = nullptr;
napi_ref disconnectCallbackRef = nullptr;
napi_ref failedCallbackRef = nullptr;
ConnectRemoveKeyType removeKey = nullptr;
};
class NAPIAbilityConnection : public AAFwk::AbilityConnectionStub {
public:
void OnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode) override;
void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
void AddConnectionCallback(std::shared_ptr<ConnectionCallback> callback);
void HandleOnAbilityConnectDone(ConnectionCallback &callback, int resultCode);
void HandleOnAbilityDisconnectDone(ConnectionCallback &callback, int resultCode);
int GetConnectionState() const;
void SetConnectionState(int connectionState);
size_t GetCallbackSize();
size_t RemoveAllCallbacks(ConnectRemoveKeyType key);
private:
std::list<std::shared_ptr<ConnectionCallback>> callbacks_;
AppExecFwk::ElementName element_;
sptr<IRemoteObject> serviceRemoteObject_ = nullptr;
int connectionState_ = CONNECTION_STATE_DISCONNECTED;
mutable std::mutex lock_;
};
struct ConnectionKey {
Want want;
int64_t id;
};
struct key_compare {
bool operator()(const ConnectionKey &key1, const ConnectionKey &key2) const
{
if (key1.id < key2.id) {
return true;
}
return false;
}
};
} // namespace AppExecFwk
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_JS_NAPI_COMMON_ABILITY_H
@@ -1016,349 +1016,6 @@ napi_value NAPI_StopAbilityCommon(napi_env env, napi_callback_info info, Ability
return ret;
}
void ClearCallbackWork(uv_work_t* req, int)
{
std::unique_ptr<uv_work_t> work(req);
if (!req) {
TAG_LOGE(AAFwkTag::JSNAPI, "work null");
return;
}
std::unique_ptr<ConnectionCallback> callback(reinterpret_cast<ConnectionCallback*>(req->data));
if (!callback) {
TAG_LOGE(AAFwkTag::JSNAPI, "data null");
return;
}
callback->Reset();
}
void ConnectionCallback::Reset()
{
auto engine = reinterpret_cast<NativeEngine*>(env);
if (engine == nullptr) {
removeKey = nullptr;
return;
}
if (pthread_self() == engine->GetTid()) {
TAG_LOGD(AAFwkTag::JSNAPI, "in-js-thread");
if (connectCallbackRef) {
napi_delete_reference(env, connectCallbackRef);
connectCallbackRef = nullptr;
}
if (disconnectCallbackRef) {
napi_delete_reference(env, disconnectCallbackRef);
disconnectCallbackRef = nullptr;
}
if (failedCallbackRef) {
napi_delete_reference(env, failedCallbackRef);
failedCallbackRef = nullptr;
}
env = nullptr;
removeKey = nullptr;
return;
}
TAG_LOGI(AAFwkTag::JSNAPI, "not in-js-thread");
auto loop = engine->GetUVLoop();
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, loop == nullptr.", __func__);
env = nullptr;
removeKey = nullptr;
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "work == nullptr.");
return;
}
ConnectionCallback *data = new(std::nothrow) ConnectionCallback(std::move(*this));
work->data = data;
auto ret = uv_queue_work(loop, work, [](uv_work_t*) {}, ClearCallbackWork);
if (ret != 0) {
TAG_LOGE(AAFwkTag::JSNAPI, "uv_queue_work failed: %{public}d", ret);
data->env = nullptr;
data->removeKey = nullptr;
delete data;
delete work;
}
}
void NAPIAbilityConnection::AddConnectionCallback(std::shared_ptr<ConnectionCallback> callback)
{
std::lock_guard<std::mutex> guard(lock_);
callbacks_.emplace_back(callback);
}
int NAPIAbilityConnection::GetConnectionState() const
{
std::lock_guard<std::mutex> guard(lock_);
return connectionState_;
}
void NAPIAbilityConnection::SetConnectionState(int connectionState)
{
std::lock_guard<std::mutex> guard(lock_);
connectionState_ = connectionState;
}
size_t NAPIAbilityConnection::GetCallbackSize()
{
std::lock_guard<std::mutex> guard(lock_);
return callbacks_.size();
}
size_t NAPIAbilityConnection::RemoveAllCallbacks(ConnectRemoveKeyType key)
{
size_t result = 0;
std::lock_guard<std::mutex> guard(lock_);
for (auto it = callbacks_.begin(); it != callbacks_.end();) {
auto callback = *it;
if (callback && callback->removeKey == key) {
it = callbacks_.erase(it);
result++;
} else {
++it;
}
}
TAG_LOGI(AAFwkTag::JSNAPI, "RemoveAllCallbacks removed size:%{public}zu, left size:%{public}zu", result,
callbacks_.size());
return result;
}
void UvWorkOnAbilityConnectDone(uv_work_t *work, int status)
{
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, uv_queue_work");
std::unique_ptr<uv_work_t> managedWork(work);
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, work is null");
return;
}
// JS Thread
std::unique_ptr<ConnectAbilityCB> connectAbilityCB(static_cast<ConnectAbilityCB *>(work->data));
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, connectAbilityCB is null");
return;
}
CallbackInfo &cbInfo = connectAbilityCB->cbBase.cbInfo;
napi_handle_scope scope = nullptr;
napi_open_handle_scope(cbInfo.env, &scope);
if (scope == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "napi_open_handle_scope failed");
return;
}
napi_value globalValue;
napi_get_global(cbInfo.env, &globalValue);
napi_value func;
napi_get_named_property(cbInfo.env, globalValue, "requireNapi", &func);
napi_value rpcInfo;
napi_create_string_utf8(cbInfo.env, "rpc", NAPI_AUTO_LENGTH, &rpcInfo);
napi_value funcArgv[1] = { rpcInfo };
napi_value returnValue;
napi_call_function(cbInfo.env, globalValue, func, 1, funcArgv, &returnValue);
napi_value result[ARGS_TWO] = {nullptr};
result[PARAM0] =
WrapElementName(cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName);
napi_value jsRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(
cbInfo.env, connectAbilityCB->abilityConnectionCB.connection);
result[PARAM1] = jsRemoteObject;
napi_value callback = nullptr;
napi_value undefined = nullptr;
napi_get_undefined(cbInfo.env, &undefined);
napi_value callResult = nullptr;
napi_get_reference_value(cbInfo.env, cbInfo.callback, &callback);
napi_call_function(
cbInfo.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
if (cbInfo.callback != nullptr) {
napi_delete_reference(cbInfo.env, cbInfo.callback);
}
napi_close_handle_scope(cbInfo.env, scope);
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityConnectDone, uv_queue_work end");
}
void NAPIAbilityConnection::HandleOnAbilityConnectDone(ConnectionCallback &callback, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s called.", __func__);
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(callback.env, &loop);
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, loop == null.", __func__);
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, work == null.", __func__);
return;
}
ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB;
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, connectAbilityCB == null.", __func__);
if (work != nullptr) {
delete work;
work = nullptr;
}
return;
}
connectAbilityCB->cbBase.cbInfo.env = callback.env;
connectAbilityCB->cbBase.cbInfo.callback = callback.connectCallbackRef;
callback.connectCallbackRef = nullptr;
connectAbilityCB->abilityConnectionCB.elementName = element_;
connectAbilityCB->abilityConnectionCB.resultCode = resultCode;
connectAbilityCB->abilityConnectionCB.connection = serviceRemoteObject_;
work->data = static_cast<void *>(connectAbilityCB);
int rev = uv_queue_work_with_qos(
loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityConnectDone, uv_qos_user_initiated);
if (rev != 0) {
if (connectAbilityCB != nullptr) {
delete connectAbilityCB;
connectAbilityCB = nullptr;
}
if (work != nullptr) {
delete work;
work = nullptr;
}
}
}
void NAPIAbilityConnection::OnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s bundleName:%{public}s abilityName:%{public}s, resultCode:%{public}d",
__func__, element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
if (remoteObject == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, remoteObject == nullptr.", __func__);
return;
}
std::lock_guard<std::mutex> guard(lock_);
element_ = element;
serviceRemoteObject_ = remoteObject;
for (const auto &callback : callbacks_) {
HandleOnAbilityConnectDone(*callback, resultCode);
}
connectionState_ = CONNECTION_STATE_CONNECTED;
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s, end.", __func__);
}
void UvWorkOnAbilityDisconnectDone(uv_work_t *work, int status)
{
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, uv_queue_work");
std::unique_ptr<uv_work_t> managedWork(work);
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, work is null");
return;
}
// JS Thread
std::unique_ptr<ConnectAbilityCB> connectAbilityCB(static_cast<ConnectAbilityCB *>(work->data));
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, connectAbilityCB is null");
return;
}
CallbackInfo &cbInfo = connectAbilityCB->cbBase.cbInfo;
napi_handle_scope scope = nullptr;
napi_open_handle_scope(cbInfo.env, &scope);
if (scope == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "napi_open_handle_scope failed");
return;
}
napi_value result = WrapElementName(cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName);
if (cbInfo.callback != nullptr) {
napi_value callback = nullptr;
napi_value callResult = nullptr;
napi_value undefined = nullptr;
napi_get_undefined(cbInfo.env, &undefined);
napi_get_reference_value(cbInfo.env, cbInfo.callback, &callback);
napi_call_function(cbInfo.env, undefined, callback, ARGS_ONE, &result, &callResult);
napi_delete_reference(cbInfo.env, cbInfo.callback);
cbInfo.callback = nullptr;
}
napi_close_handle_scope(cbInfo.env, scope);
// release connect
std::lock_guard<std::mutex> lock(g_connectionsLock_);
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone connects_.size:%{public}zu", connects_.size());
std::string deviceId = connectAbilityCB->abilityConnectionCB.elementName.GetDeviceID();
std::string bundleName = connectAbilityCB->abilityConnectionCB.elementName.GetBundleName();
std::string abilityName = connectAbilityCB->abilityConnectionCB.elementName.GetAbilityName();
auto item = std::find_if(connects_.begin(), connects_.end(),
[deviceId, bundleName, abilityName](const std::map<ConnectionKey,
sptr<NAPIAbilityConnection>>::value_type &obj) {
return (deviceId == obj.first.want.GetDeviceId()) &&
(bundleName == obj.first.want.GetBundle()) &&
(abilityName == obj.first.want.GetElement().GetAbilityName());
});
if (item != connects_.end()) {
// match deviceid & bundlename && abilityname
connects_.erase(item);
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone erase connects_.size:%{public}zu", connects_.size());
}
TAG_LOGI(AAFwkTag::JSNAPI, "UvWorkOnAbilityDisconnectDone, uv_queue_work end");
}
void NAPIAbilityConnection::HandleOnAbilityDisconnectDone(ConnectionCallback &callback, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s called.", __func__);
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(callback.env, &loop);
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, loop == nullptr.", __func__);
return;
}
uv_work_t *work = new(std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "work == nullptr.");
return;
}
ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB;
if (connectAbilityCB == nullptr) {
TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, connectAbilityCB == nullptr.", __func__);
if (work != nullptr) {
delete work;
work = nullptr;
}
return;
}
connectAbilityCB->cbBase.cbInfo.env = callback.env;
connectAbilityCB->cbBase.cbInfo.callback = callback.disconnectCallbackRef;
callback.disconnectCallbackRef = nullptr;
connectAbilityCB->abilityConnectionCB.elementName = element_;
connectAbilityCB->abilityConnectionCB.resultCode = resultCode;
work->data = static_cast<void *>(connectAbilityCB);
int rev = uv_queue_work(
loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityDisconnectDone);
if (rev != 0) {
if (connectAbilityCB != nullptr) {
delete connectAbilityCB;
connectAbilityCB = nullptr;
}
if (work != nullptr) {
delete work;
work = nullptr;
}
}
}
void NAPIAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
{
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s bundleName:%{public}s abilityName:%{public}s, resultCode:%{public}d",
__func__, element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
std::lock_guard<std::mutex> guard(lock_);
element_ = element;
for (const auto &callback : callbacks_) {
HandleOnAbilityDisconnectDone(*callback, resultCode);
}
connectionState_ = CONNECTION_STATE_DISCONNECTED;
TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s, end.", __func__);
}
/**
* @brief AcquireDataAbilityHelper.
*
@@ -20,7 +20,6 @@
#include <mutex>
#include <list>
#include "ability_connect_callback_stub.h"
#include "ability_info.h"
#include "ability_manager_errors.h"
#include "application_info.h"
@@ -167,90 +166,6 @@ napi_value NAPI_GetAbilityNameCommon(napi_env env, napi_callback_info info, Abil
*/
napi_value NAPI_StopAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType);
enum {
CONNECTION_STATE_DISCONNECTED = -1,
CONNECTION_STATE_CONNECTED = 0,
CONNECTION_STATE_CONNECTING = 1
};
class JsNapiCommon;
using ConnectRemoveKeyType = JsNapiCommon*;
struct ConnectionCallback {
ConnectionCallback(napi_env env, napi_value cbInfo, ConnectRemoveKeyType key)
{
this->env = env;
napi_value jsMethod = nullptr;
napi_get_named_property(env, cbInfo, "onConnect", &jsMethod);
napi_create_reference(env, jsMethod, 1, &connectCallbackRef);
napi_get_named_property(env, cbInfo, "onDisconnect", &jsMethod);
napi_create_reference(env, jsMethod, 1, &disconnectCallbackRef);
napi_get_named_property(env, cbInfo, "onFailed", &jsMethod);
napi_create_reference(env, jsMethod, 1, &failedCallbackRef);
removeKey = key;
}
ConnectionCallback(ConnectionCallback &) = delete;
ConnectionCallback(ConnectionCallback &&other)
: env(other.env), connectCallbackRef(other.connectCallbackRef),
disconnectCallbackRef(other.disconnectCallbackRef), failedCallbackRef(other.failedCallbackRef),
removeKey(other.removeKey)
{
other.env = nullptr;
other.connectCallbackRef = nullptr;
other.disconnectCallbackRef = nullptr;
other.failedCallbackRef = nullptr;
other.removeKey = nullptr;
}
const ConnectionCallback &operator=(ConnectionCallback &) = delete;
const ConnectionCallback &operator=(ConnectionCallback &&other)
{
Reset();
env = other.env;
connectCallbackRef = other.connectCallbackRef;
disconnectCallbackRef = other.disconnectCallbackRef;
failedCallbackRef = other.failedCallbackRef;
other.env = nullptr;
other.connectCallbackRef = nullptr;
other.disconnectCallbackRef = nullptr;
other.failedCallbackRef = nullptr;
other.removeKey = nullptr;
return *this;
}
~ConnectionCallback()
{
Reset();
}
void Reset();
napi_env env = nullptr;
napi_ref connectCallbackRef = nullptr;
napi_ref disconnectCallbackRef = nullptr;
napi_ref failedCallbackRef = nullptr;
ConnectRemoveKeyType removeKey = nullptr;
};
class NAPIAbilityConnection : public AAFwk::AbilityConnectionStub {
public:
void OnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode) override;
void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
void AddConnectionCallback(std::shared_ptr<ConnectionCallback> callback);
void HandleOnAbilityConnectDone(ConnectionCallback &callback, int resultCode);
void HandleOnAbilityDisconnectDone(ConnectionCallback &callback, int resultCode);
int GetConnectionState() const;
void SetConnectionState(int connectionState);
size_t GetCallbackSize();
size_t RemoveAllCallbacks(ConnectRemoveKeyType key);
private:
std::list<std::shared_ptr<ConnectionCallback>> callbacks_;
AppExecFwk::ElementName element_;
sptr<IRemoteObject> serviceRemoteObject_ = nullptr;
int connectionState_ = CONNECTION_STATE_DISCONNECTED;
mutable std::mutex lock_;
};
/**
* @brief acquireDataAbilityHelper processing function.
*
@@ -294,23 +209,6 @@ napi_value NAPI_StartBackgroundRunningCommon(napi_env env, napi_callback_info in
*/
napi_value NAPI_CancelBackgroundRunningCommon(napi_env env, napi_callback_info info);
struct ConnectionKey {
Want want;
int64_t id;
};
struct key_compare {
bool operator()(const ConnectionKey &key1, const ConnectionKey &key2) const
{
if (key1.id < key2.id) {
return true;
}
return false;
}
};
static std::map<ConnectionKey, sptr<NAPIAbilityConnection>, key_compare> connects_;
static std::mutex g_connectionsLock_;
static int64_t serialNumber_ = 0;
enum ErrorCode {
NO_ERROR = 0,
INVALID_PARAMETER = -1,