From 12bfdcdd956b420a8e177a593abc9a3867d1aa24 Mon Sep 17 00:00:00 2001 From: ql Date: Fri, 7 Jan 2022 17:43:43 +0800 Subject: [PATCH] napi distributed mission manager Change-Id: I3e24cb11cb32b6860fa5fdb0ac97c3d21e4ba7a4 Signed-off-by: ql --- interfaces/kits/napi/BUILD.gn | 1 + .../mission_callback_interface.h | 45 + .../mission_manager/mission_callback_stub.cpp | 91 ++ .../mission_manager/mission_callback_stub.h | 39 + .../napi_mission_registration.cpp | 1452 +++++++++++++++++ .../napi_mission_registration.h | 140 ++ 6 files changed, 1768 insertions(+) create mode 100644 interfaces/kits/napi/aafwk/mission_manager/mission_callback_interface.h create mode 100644 interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.cpp create mode 100644 interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.h create mode 100644 interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.cpp create mode 100644 interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.h diff --git a/interfaces/kits/napi/BUILD.gn b/interfaces/kits/napi/BUILD.gn index af650893059..ebe5c180096 100644 --- a/interfaces/kits/napi/BUILD.gn +++ b/interfaces/kits/napi/BUILD.gn @@ -27,6 +27,7 @@ group("napi_packages") { "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/form_extension_context:formextensioncontext_napi", "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common:napi_common", "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/mission_manager:missionmanager_napi", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/mission_manager:missionregistration_napi", "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/particleAbility:particleability", "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/service_extension_context:serviceextensioncontext_napi", "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/serviceextension:serviceextension_napi", diff --git a/interfaces/kits/napi/aafwk/mission_manager/mission_callback_interface.h b/interfaces/kits/napi/aafwk/mission_manager/mission_callback_interface.h new file mode 100644 index 00000000000..bb55dc3f73c --- /dev/null +++ b/interfaces/kits/napi/aafwk/mission_manager/mission_callback_interface.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MISSION_CALLBACK_INTERFACE_H +#define OHOS_MISSION_CALLBACK_INTERFACE_H + +#include "element_name.h" +#include "iremote_broker.h" + +namespace OHOS { +namespace DistributedSchedule { +class IMissionCallback : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.DistributedSchedule.IMissionCallback"); + + virtual void NotifyMissionsChanged(const std::u16string deviceId) = 0; + virtual void NotifySnapshot(const std::u16string deviceId, int32_t taskId) = 0; + virtual void NotifyNetDisconnect(const std::u16string deviceId, int32_t state) = 0; + virtual void OnContinueDone(int32_t result) = 0; + + enum RequestCode { + NOTIFY_MISSIONS_CHANGED = 1, + + NOTIFY_SNAP_SHOT = 2, + + NOTIFY_NET_DISCONNECT = 3, + + NOTIFY_CONTINUATION_RESULT = 4, + }; +}; +} // namespace DistributedSchedule +} // namespace OHOS +#endif // OHOS_MISSION_CALLBACK_INTERFACE_H diff --git a/interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.cpp b/interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.cpp new file mode 100644 index 00000000000..c8bc8d2ab02 --- /dev/null +++ b/interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_callback_stub.h" + +#include "dtbschedmgr_log.h" +#include "ipc_types.h" +#include "message_parcel.h" +#include "want.h" + +namespace OHOS { +namespace DistributedSchedule { +namespace { + const std::string TAG = "MissionCallbackStub"; + const std::u16string MISSION_CALLBACK_STUB_TOKEN = u"ohos.DistributedSchedule.IMissionCallback"; +} + +MissionCallbackStub::MissionCallbackStub() +{} + +MissionCallbackStub::~MissionCallbackStub() +{} + +int32_t MissionCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) +{ + if (data.ReadInterfaceToken() != MISSION_CALLBACK_STUB_TOKEN) { + HILOGE("Local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + switch (code) { + case IMissionCallback::NOTIFY_MISSIONS_CHANGED: { + auto deviceId = data.ReadString16(); + HILOGI("NOTIFY_MISSIONS_CHANGED deviceId is %{public}s", Str16ToStr8(deviceId).c_str()); + if (deviceId.empty()) { + HILOGE("callback stub receive deviceId is empty"); + return ERR_INVALID_VALUE; + } + NotifyMissionsChanged(deviceId); + return NO_ERROR; + } + case IMissionCallback::NOTIFY_SNAP_SHOT: { + auto deviceId = data.ReadString16(); + if (deviceId.empty()) { + HILOGE("callback stub receive deviceId is empty"); + return ERR_INVALID_VALUE; + } + int32_t missionId = data.ReadInt32(); + HILOGI("NOTIFY_SNAP_SHOT deviceId: %{public}s, missionId: %{public}d", + Str16ToStr8(deviceId).c_str(), missionId); + NotifySnapshot(deviceId, missionId); + return NO_ERROR; + } + case IMissionCallback::NOTIFY_NET_DISCONNECT: { + auto deviceId = data.ReadString16(); + if (deviceId.empty()) { + HILOGE("callback stub receive deviceId is empty"); + return ERR_INVALID_VALUE; + } + int32_t state = data.ReadInt32(); + HILOGI("NOTIFY_NET_DISCONNECT deviceId: %{public}s, state: %{public}d", + Str16ToStr8(deviceId).c_str(), state); + NotifyNetDisconnect(deviceId, state); + return NO_ERROR; + } + case IMissionCallback::NOTIFY_CONTINUATION_RESULT: { + int32_t result = data.ReadInt32(); + HILOGI("NOTIFY_CONTINUATION_RESULT result: %{public}d", result); + OnContinueDone(result); + return NO_ERROR; + } + default: { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } +} +} // namespace DistributedSchedule +} // namespace OHOS diff --git a/interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.h b/interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.h new file mode 100644 index 00000000000..fdcc0829d5c --- /dev/null +++ b/interfaces/kits/napi/aafwk/mission_manager/mission_callback_stub.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MISSION_CALLBACK_STUB_H +#define OHOS_MISSION_CALLBACK_STUB_H + +#include +#include + +#include "mission_callback_interface.h" +#include "nocopyable.h" + +namespace OHOS { +namespace DistributedSchedule { +class MissionCallbackStub : public IRemoteStub { +public: + MissionCallbackStub(); + virtual ~MissionCallbackStub(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +private: + DISALLOW_COPY_AND_MOVE(MissionCallbackStub); +}; +} // namespace DistributedSchedule +} // namespace OHOS +#endif // OHOS_MISSION_CALLBACK_STUB_H \ No newline at end of file diff --git a/interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.cpp b/interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.cpp new file mode 100644 index 00000000000..1dd25543a6c --- /dev/null +++ b/interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.cpp @@ -0,0 +1,1452 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ability_manager_client.h" +#include "dtbschedmgr_log.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "napi_common_data.h" +#include "napi_common_util.h" +#include "napi_common_want.h" +#include "napi_mission_registration.h" +#include "napi_remote_object.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace DistributedSchedule { +using AbilityManagerClient = AAFwk::AbilityManagerClient; +const std::string TAG = "NAPIMissionRegistration"; +constexpr size_t VALUE_BUFFER_SIZE = 128; + +bool SetStartSyncMissionsContext(const napi_env &env, const napi_value &value, + SyncRemoteMissionsContext* context) +{ + HILOGI("%{public}s call.", __func__); + bool isFixConflict = false; + napi_has_named_property(env, value, "fixConflict", &isFixConflict); + if (!isFixConflict) { + HILOGE("%{public}s, Wrong argument name for fixConflict.", __func__); + return false; + } + napi_value fixConflictValue = nullptr; + napi_get_named_property(env, value, "fixConflict", &fixConflictValue); + if (fixConflictValue == nullptr) { + HILOGE("%{public}s, not find fixConflict.", __func__); + return false; + } + napi_valuetype valueType = napi_undefined; + napi_typeof(env, fixConflictValue, &valueType); + if (valueType != napi_boolean) { + HILOGE("%{public}s, fixConflict error type.", __func__); + return false; + } + bool isTag = false; + napi_has_named_property(env, value, "tag", &isTag); + if (!isTag) { + HILOGE("%{public}s, Wrong argument name for tag.", __func__); + return false; + } + napi_value tagValue = nullptr; + napi_get_named_property(env, value, "tag", &tagValue); + if (tagValue == nullptr) { + HILOGE("%{public}s, not find tag.", __func__); + return false; + } + napi_typeof(env, tagValue, &valueType); + if (valueType != napi_number) { + HILOGE("%{public}s, tag error type.", __func__); + return false; + } + napi_get_value_int64(env, tagValue, &context->tag); + HILOGI("%{public}s end.", __func__); + return true; +} + +bool SetSyncRemoteMissionsContext(const napi_env &env, const napi_value &value, + bool isStart, SyncRemoteMissionsContext* context) +{ + HILOGI("%{public}s call.", __func__); + napi_valuetype valueType = napi_undefined; + napi_typeof(env, value, &valueType); + if (valueType != napi_object) { + HILOGE("%{public}s, Wrong argument type.", __func__); + return false; + } + napi_value deviceIdValue = nullptr; + bool isDeviceId = false; + napi_has_named_property(env, value, "deviceId", &isDeviceId); + if (!isDeviceId) { + HILOGE("%{public}s, Wrong argument name for deviceId.", __func__); + return false; + } + napi_get_named_property(env, value, "deviceId", &deviceIdValue); + if (deviceIdValue == nullptr) { + HILOGE("%{public}s, not find deviceId.", __func__); + return false; + } + napi_typeof(env, deviceIdValue, &valueType); + if (valueType != napi_string) { + HILOGE("%{public}s, deviceId error type.", __func__); + return false; + } + napi_get_value_string_utf16(env, deviceIdValue, context->deviceId, VALUE_BUFFER_SIZE, &context->valueLen); + if (isStart && !SetStartSyncMissionsContext (env, value, context)) { + HILOGE("%{public}s, Wrong argument for start sync.", __func__); + return false; + } + HILOGI("%{public}s end.", __func__); + return true; +} + +bool ProcessSyncInput(napi_env env, napi_callback_info info, bool isStart, + SyncRemoteMissionsContext* syncContext) +{ + HILOGI("%{public}s,called.", __func__); + size_t argc = 2; + napi_value argv[2] = { 0 }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != ARGS_ONE && argc != ARGS_TWO) { + HILOGE("%{public}s, argument size error.", __func__); + return false; + } + syncContext->env = env; + if (!SetSyncRemoteMissionsContext(env, argv[0], isStart, syncContext)) { + HILOGE("%{public}s, Wrong argument.", __func__); + return false; + } + if (argc == ARGS_TWO) { + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[1], &valueType); + if (valueType != napi_function) { + HILOGE("%{public}s, callback error type.", __func__); + return false; + } + napi_create_reference(env, argv[1], 1, &syncContext->callbackRef); + } + HILOGI("%{public}s, end.", __func__); + return true; +} + +void StartSyncRemoteMissionsAsyncWork(napi_env env, const napi_value resourceName, + SyncRemoteMissionsContext* syncContext) +{ + HILOGI("%{public}s, called.", __func__); + napi_create_async_work(env, nullptr, resourceName, + [](napi_env env, void* data) { + SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data; + // syncContext->result = AbilityManagerClient::GetInstance()-> + // StartSyncRemoteMissions(Str16ToStr8(syncContext->deviceId), + // syncContext->fixConflict, syncContext->tag); + syncContext->result = -1; + }, + [](napi_env env, napi_status status, void* data) { + SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data; + // set result + napi_value result[2] = { 0 }; + napi_get_undefined(env, &result[1]); + if (syncContext->result == 0) { + napi_get_undefined(env, &result[0]); + } else { + napi_value message = nullptr; + napi_create_string_utf8(env, ("StartSyncRemoteMissions failed, error : " + + std::to_string(syncContext->result)).c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(env, nullptr, message, &result[0]); + } + + if (syncContext->callbackRef == nullptr) { // promise + if (syncContext->result == 0) { + napi_resolve_deferred(env, syncContext->deferred, result[1]); + } else { + napi_reject_deferred(env, syncContext->deferred, result[0]); + } + } else { // AsyncCallback + napi_value callback = nullptr; + napi_get_reference_value(env, syncContext->callbackRef, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult); + napi_delete_reference(env, syncContext->callbackRef); + } + napi_delete_async_work(env, syncContext->work); + delete syncContext; + syncContext = nullptr; + }, + (void *)syncContext, + &syncContext->work); + napi_queue_async_work(env, syncContext->work); + HILOGI("%{public}s, end.", __func__); +} + +napi_value NAPI_StartSyncRemoteMissions(napi_env env, napi_callback_info info) +{ + HILOGI("%{public}s, called.", __func__); + auto syncContext = new SyncRemoteMissionsContext(); + if (!ProcessSyncInput(env, info, true, syncContext)) { + delete syncContext; + syncContext = nullptr; + HILOGE("%{public}s, Wrong argument.", __func__); + NAPI_ASSERT(env, false, "Wrong argument"); + } + napi_value result = nullptr; + if (syncContext->callbackRef == nullptr) { + napi_create_promise(env, &syncContext->deferred, &result); + } else { + napi_get_undefined(env, &result); + } + + napi_value resourceName = nullptr; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + StartSyncRemoteMissionsAsyncWork(env, resourceName, syncContext); + HILOGI("%{public}s, end.", __func__); + return result; +} + +void StopSyncRemoteMissionsAsyncWork(napi_env env, napi_value resourceName, + SyncRemoteMissionsContext* syncContext) +{ + HILOGI("%{public}s, called.", __func__); + napi_create_async_work(env, nullptr, resourceName, + [](napi_env env, void* data) { + SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data; + // syncContext->result = AbilityManagerClient::GetInstance()-> + // StopSyncRemoteMissions(Str16ToStr8(syncContext->deviceId)); + syncContext->result = -1; + }, + [](napi_env env, napi_status status, void* data) { + SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data; + // set result + napi_value result[2] = { 0 }; + napi_get_undefined(env, &result[1]); + if (syncContext->result == 0) { + napi_get_undefined(env, &result[0]); + } else { + napi_value message = nullptr; + napi_create_string_utf8(env, ("StopSyncRemoteMissions failed, error : " + + std::to_string(syncContext->result)).c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(env, nullptr, message, &result[0]); + } + + if (syncContext->callbackRef == nullptr) { // promise + if (syncContext->result == 0) { + napi_resolve_deferred(env, syncContext->deferred, result[1]); + } else { + napi_reject_deferred(env, syncContext->deferred, result[0]); + } + } else { // AsyncCallback + napi_value callback = nullptr; + napi_get_reference_value(env, syncContext->callbackRef, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult); + napi_delete_reference(env, syncContext->callbackRef); + } + napi_delete_async_work(env, syncContext->work); + delete syncContext; + syncContext = nullptr; + }, + (void *)syncContext, + &syncContext->work); + napi_queue_async_work(env, syncContext->work); + HILOGI("%{public}s, end.", __func__); +} + +napi_value NAPI_StopSyncRemoteMissions(napi_env env, napi_callback_info info) +{ + HILOGI("%{public}s, called.", __func__); + auto syncContext = new SyncRemoteMissionsContext(); + if (!ProcessSyncInput(env, info, false, syncContext)) { + delete syncContext; + syncContext = nullptr; + HILOGE("%{public}s, Wrong argument.", __func__); + NAPI_ASSERT(env, false, "Wrong argument"); + } + napi_value result = nullptr; + if (syncContext->callbackRef == nullptr) { + napi_create_promise(env, &syncContext->deferred, &result); + } else { + napi_get_undefined(env, &result); + } + + napi_value resourceName = nullptr; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + StopSyncRemoteMissionsAsyncWork(env, resourceName, syncContext); + HILOGI("%{public}s, end.", __func__); + return result; +} + +RegisterMissonCB *CreateRegisterMissonCBCBInfo(napi_env env) +{ + HILOGI("%{public}s called.", __func__); + auto registerMissonCB = new (std::nothrow) RegisterMissonCB; + if (registerMissonCB == nullptr) { + HILOGE("%{public}s registerMissonCB == nullptr", __func__); + return nullptr; + } + registerMissonCB->cbBase.cbInfo.env = env; + registerMissonCB->cbBase.asyncWork = nullptr; + registerMissonCB->cbBase.deferred = nullptr; + registerMissonCB->callbackRef = nullptr; + HILOGI("%{public}s end.", __func__); + return registerMissonCB; +} + +void RegisterMissonExecuteCB(napi_env env, void *data) +{ + HILOGI("%{public}s called.", __func__); + auto registerMissonCB = (RegisterMissonCB*)data; + if (registerMissonCB == nullptr) { + HILOGE("%{public}s registerMissonCB == nullptr.", __func__); + registerMissonCB->result = -1; + return; + } + HILOGI("create registerMissonCB success."); + + std::lock_guard autoLock(registrationLock_); + sptr registration; + auto item = registration_.find(registerMissonCB->deviceId); + if (item != registration_.end()) { + HILOGI("registration exits."); + registration = registration_[registerMissonCB->deviceId]; + } else { + HILOGI("registration not exits."); + registration = new (std::nothrow) NAPIMissionRegistration(); + } + registerMissonCB->missionRegistration = registration; + if (registerMissonCB->missionRegistration == nullptr) { + HILOGE("%{public}s missionRegistration == nullptr.", __func__); + registerMissonCB->result = -1; + return; + } + registerMissonCB->missionRegistration->SetEnv(env); + registerMissonCB->missionRegistration-> + SetNotifyMissionsChangedCBRef(registerMissonCB->missionRegistrationCB.callback[0]); + registerMissonCB->missionRegistration-> + SetNotifySnapshotCBRef(registerMissonCB->missionRegistrationCB.callback[1]); + registerMissonCB->missionRegistration-> + SetNotifyNetDisconnectCBRef(registerMissonCB-> + missionRegistrationCB.callback[2]); // 2 refers the second argument + HILOGI("set callback success."); + + registerMissonCB->result = -1; + // registerMissonCB->result = + // AbilityManagerClient::GetInstance()-> + // RegisterMissionListener(registerMissonCB->deviceId.c_str(), + // registerMissonCB->missionRegistration); + // std::lock_guard autoLock(registrationLock_); + // if (registerMissonCB->result == NO_ERROR) { + // HILOGI("add registration."); + // registration_[registerMissonCB->deviceId] = registration; + // } + // HILOGI("%{public}s end.deviceId:%{public}d ", __func__, registerMissonCB->result); +} + +void RegisterMissonCallbackCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOGI("%{public}s called.", __func__); + auto registerMissonCB = static_cast(data); + // set result + napi_value result[2] = { 0 }; + napi_get_undefined(env, &result[1]); + if (registerMissonCB->result == 0) { + napi_get_undefined(env, &result[0]); + } else { + napi_value message = nullptr; + napi_create_string_utf8(env, ("registerMissionListener failed, error : " + + std::to_string(registerMissonCB->result)).c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(env, nullptr, message, &result[0]); + } + + if (registerMissonCB->callbackRef == nullptr) { // promise + if (registerMissonCB->result == 0) { + napi_resolve_deferred(env, registerMissonCB->cbBase.deferred, result[1]); + } else { + napi_reject_deferred(env, registerMissonCB->cbBase.deferred, result[0]); + } + } else { // AsyncCallback + napi_value callback = nullptr; + napi_get_reference_value(env, registerMissonCB->callbackRef, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult); + napi_delete_reference(env, registerMissonCB->callbackRef); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, registerMissonCB->cbBase.asyncWork)); + delete registerMissonCB; + registerMissonCB = nullptr; + HILOGI("%{public}s end.", __func__); +} + +napi_value RegisterMissonAsync(napi_env env, napi_value *args, RegisterMissonCB *registerMissonCB) +{ + HILOGI("%{public}s asyncCallback.", __func__); + if (args == nullptr || registerMissonCB == nullptr) { + HILOGE("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value result = nullptr; + if (registerMissonCB->callbackRef == nullptr) { + napi_create_promise(env, ®isterMissonCB->cbBase.deferred, &result); + } else { + napi_get_undefined(env, &result); + } + napi_value resourceName = nullptr; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + RegisterMissonExecuteCB, + RegisterMissonCallbackCompletedCB, + (void *)registerMissonCB, + ®isterMissonCB->cbBase.asyncWork); + napi_queue_async_work(env, registerMissonCB->cbBase.asyncWork); + HILOGI("%{public}s asyncCallback end.", __func__); + return result; +} + +bool SetCallbackReference(napi_env env, const napi_value& value, RegisterMissonCB *registerMissonCB) +{ + HILOGI("%{public}s called.", __func__); + bool isFirstCallback = false; + napi_has_named_property(env, value, "notifyMissionsChanged", &isFirstCallback); + bool isSecondCallback = false; + napi_has_named_property(env, value, "notifySnapshot", &isSecondCallback); + bool isThirdCallback = false; + napi_has_named_property(env, value, "notifyNetDisconnect", &isThirdCallback); + if (!isFirstCallback || !isSecondCallback || !isThirdCallback) { + HILOGE("%{public}s, Wrong argument name for callback.", __func__); + return false; + } + napi_value jsMethod = nullptr; + napi_get_named_property(env, value, "notifyMissionsChanged", &jsMethod); + if (jsMethod == nullptr) { + HILOGE("%{public}s, not find callback notifyMissionsChanged.", __func__); + return false; + } + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, jsMethod, &valuetype); + if (valuetype != napi_function) { + HILOGE("%{public}s, notifyMissionsChanged callback error type.", __func__); + return false; + } + napi_create_reference(env, jsMethod, 1, ®isterMissonCB->missionRegistrationCB.callback[0]); + + napi_get_named_property(env, value, "notifySnapshot", &jsMethod); + if (jsMethod == nullptr) { + HILOGE("%{public}s, not find callback notifySnapshot.", __func__); + return false; + } + napi_typeof(env, jsMethod, &valuetype); + if (valuetype != napi_function) { + HILOGE("%{public}s, notifySnapshot callback error type.", __func__); + return false; + } + napi_create_reference(env, jsMethod, 1, ®isterMissonCB->missionRegistrationCB.callback[1]); + + napi_get_named_property(env, value, "notifyNetDisconnect", &jsMethod); + if (jsMethod == nullptr) { + HILOGE("%{public}s, not find callback notifyNetDisconnect.", __func__); + return false; + } + napi_typeof(env, jsMethod, &valuetype); + if (valuetype != napi_function) { + HILOGE("%{public}s, notifyNetDisconnect callback error type.", __func__); + return false; + } + napi_create_reference(env, jsMethod, 1, + ®isterMissonCB->missionRegistrationCB.callback[2]); // 2 refers the second argument + HILOGI("%{public}s called end.", __func__); + return true; +} + +bool CreateCallbackReference(napi_env env, const napi_value& value, RegisterMissonCB *registerMissonCB) +{ + HILOGI("%{public}s called.", __func__); + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, value, &valuetype); + if (valuetype == napi_object) { + if (!SetCallbackReference(env, value, registerMissonCB)) { + HILOGE("%{public}s, Wrong callback.", __func__); + return false; + } + } else { + HILOGE("%{public}s, Wrong argument type.", __func__); + return false; + } + HILOGI("%{public}s called end.", __func__); + return true; +} + +napi_value RegisterMissonWrap(napi_env env, napi_callback_info info, RegisterMissonCB *registerMissonCB) +{ + HILOGI("%{public}s called.", __func__); + size_t argcAsync = 3; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr); + HILOGI("argcAsync is %{public}zu", argcAsync); + if (argcAsync != ARGS_TWO && argcAsync != ARGS_THREE) { + HILOGE("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + napi_value firstNApi = nullptr; + napi_valuetype valueType = napi_undefined; + bool isDeviceId = false; + napi_has_named_property(env, args[0], "deviceId", &isDeviceId); + napi_typeof(env, args[0], &valueType); + if (isDeviceId && valueType == napi_object) { + napi_get_named_property(env, args[0], "deviceId", &firstNApi); + } else { + HILOGE("%{public}s, Wrong argument name for deviceId.", __func__); + return nullptr; + } + if (firstNApi == nullptr) { + HILOGE("%{public}s, not find deviceId.", __func__); + return nullptr; + } + + char16_t deviceIdList[128] = {0}; + size_t valueLen = 0; + napi_typeof(env, firstNApi, &valueType); + if (valueType != napi_string) { + HILOGE("%{public}s, deviceId error type.", __func__); + return nullptr; + } + napi_get_value_string_utf16(env, firstNApi, deviceIdList, VALUE_BUFFER_SIZE, &valueLen); + registerMissonCB->deviceId = deviceIdList; + HILOGI("%{public}s deviceId:%{public}s", __func__, Str16ToStr8(registerMissonCB->deviceId).c_str()); + + if (argcAsync > 1 && !CreateCallbackReference(env, args[1], registerMissonCB)) { + HILOGE("%{public}s, Wrong arguments.", __func__); + return nullptr; + } + + if (argcAsync == ARGS_THREE) { + napi_typeof(env, args[ARGS_TWO], &valueType); + if (valueType != napi_function) { + HILOGE("%{public}s, callback error type.", __func__); + return nullptr; + } + napi_create_reference(env, args[ARGS_TWO], 1, ®isterMissonCB->callbackRef); + } + + ret = RegisterMissonAsync(env, args, registerMissonCB); + HILOGI("%{public}s called end.", __func__); + return ret; +} + +napi_value NAPI_RegisterMissionListener(napi_env env, napi_callback_info info) +{ + HILOGI("%{public}s called.", __func__); + RegisterMissonCB *registerMissonCB = CreateRegisterMissonCBCBInfo(env); + if (registerMissonCB == nullptr) { + HILOGE("%{public}s registerMissonCB == nullptr", __func__); + return nullptr; + } + + napi_value ret = RegisterMissonWrap(env, info, registerMissonCB); + if (ret == nullptr) { + HILOGE("%{public}s ret == nullptr", __func__); + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + NAPI_ASSERT(env, ret == nullptr, "wrong arguments"); + } + HILOGI("%{public}s end.", __func__); + return ret; +} + +void NAPIMissionRegistration::SetEnv(const napi_env &env) +{ + env_ = env; +} + +void NAPIMissionRegistration::SetNotifyMissionsChangedCBRef(const napi_ref &ref) +{ + notifyMissionsChangedRef_ = ref; +} + +void NAPIMissionRegistration::SetNotifySnapshotCBRef(const napi_ref &ref) +{ + notifySnapshotRef_ = ref; +} + +void NAPIMissionRegistration::SetNotifyNetDisconnectCBRef(const napi_ref &ref) +{ + notifyNetDisconnectRef_ = ref; +} + +void UvWorkNotifyMissionChanged(uv_work_t *work, int status) +{ + HILOGI("UvWorkNotifyMissionChanged, uv_queue_work"); + if (work == nullptr) { + HILOGE("UvWorkNotifyMissionChanged, work is null"); + return; + } + RegisterMissonCB *registerMissonCB = static_cast(work->data); + if (registerMissonCB == nullptr) { + HILOGE("UvWorkNotifyMissionChanged, registerMissonCB is null"); + return; + } + napi_value result = nullptr; + HILOGI("UvWorkNotifyMissionChanged, deviceId = %{public}s", Str16ToStr8(registerMissonCB->deviceId).c_str()); + result = + WrapString(registerMissonCB->cbBase.cbInfo.env, Str16ToStr8(registerMissonCB->deviceId).c_str(), "deviceId"); + + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_get_undefined(registerMissonCB->cbBase.cbInfo.env, &undefined); + napi_value callResult = nullptr; + napi_get_reference_value(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->cbBase.cbInfo.callback, &callback); + + napi_call_function(registerMissonCB->cbBase.cbInfo.env, undefined, callback, 1, &result, &callResult); + if (registerMissonCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->cbBase.cbInfo.callback); + } + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + HILOGI("UvWorkNotifyMissionChanged, uv_queue_work end"); +} + +void NAPIMissionRegistration::NotifyMissionsChanged(const std::u16string deviceId) +{ + HILOGI("%{public}s, called. deviceId = %{public}s", __func__, Str16ToStr8(deviceId).c_str()); + uv_loop_s *loop = nullptr; + + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + HILOGE("%{public}s, loop == nullptr.", __func__); + return; + } + + uv_work_t *work = new uv_work_t; + if (work == nullptr) { + HILOGE("%{public}s, work==nullptr.", __func__); + return; + } + + auto registerMissonCB = new (std::nothrow) RegisterMissonCB; + if (registerMissonCB == nullptr) { + HILOGE("%{public}s, registerMissonCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + registerMissonCB->cbBase.cbInfo.env = env_; + registerMissonCB->cbBase.cbInfo.callback = notifyMissionsChangedRef_; + registerMissonCB->deviceId = deviceId; + work->data = (void *)registerMissonCB; + + int rev = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvWorkNotifyMissionChanged); + if (rev != 0) { + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } + HILOGI("%{public}s, end.", __func__); +} + +void UvWorkNotifySnapshot(uv_work_t *work, int status) +{ + HILOGI("UvWorkNotifySnapshot, uv_queue_work"); + if (work == nullptr) { + HILOGE("UvWorkNotifySnapshot, work is null"); + return; + } + RegisterMissonCB *registerMissonCB = static_cast(work->data); + if (registerMissonCB == nullptr) { + HILOGE("UvWorkNotifySnapshot, registerMissonCB is null"); + return; + } + napi_value result[2] = {0}; + HILOGI("UvWorkNotifySnapshot, deviceId = %{public}s", Str16ToStr8(registerMissonCB->deviceId).c_str()); + result[0] = + WrapString(registerMissonCB->cbBase.cbInfo.env, Str16ToStr8(registerMissonCB->deviceId).c_str(), "deviceId"); + HILOGI("UvWorkNotifySnapshot, missionId = %{public}d", registerMissonCB->missionId); + result[1] = + WrapInt32(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->missionId, "missionId"); + + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_get_undefined(registerMissonCB->cbBase.cbInfo.env, &undefined); + napi_value callResult = nullptr; + napi_get_reference_value(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->cbBase.cbInfo.callback, &callback); + + napi_call_function(registerMissonCB->cbBase.cbInfo.env, undefined, callback, ARGS_TWO, &result[0], &callResult); + if (registerMissonCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->cbBase.cbInfo.callback); + } + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + HILOGI("UvWorkNotifySnapshot, uv_queue_work end"); +} + +void NAPIMissionRegistration::NotifySnapshot(const std::u16string deviceId, int32_t missionId) +{ + HILOGI("%{public}s, called. deviceId = %{public}s", __func__, Str16ToStr8(deviceId).c_str()); + uv_loop_s *loop = nullptr; + + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + HILOGE("%{public}s, loop == nullptr.", __func__); + return; + } + + uv_work_t *work = new uv_work_t; + if (work == nullptr) { + HILOGE("%{public}s, work==nullptr.", __func__); + return; + } + + auto registerMissonCB = new (std::nothrow) RegisterMissonCB; + if (registerMissonCB == nullptr) { + HILOGE("%{public}s, registerMissonCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + registerMissonCB->cbBase.cbInfo.env = env_; + registerMissonCB->cbBase.cbInfo.callback = notifySnapshotRef_; + registerMissonCB->deviceId = deviceId; + registerMissonCB->missionId = missionId; + work->data = (void *)registerMissonCB; + + int rev = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvWorkNotifySnapshot); + if (rev != 0) { + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } + HILOGI("%{public}s, end.", __func__); +} + +void UvWorkNotifyNetDisconnect(uv_work_t *work, int status) +{ + HILOGI("UvWorkNotifyNetDisconnect, uv_queue_work"); + if (work == nullptr) { + HILOGE("UvWorkNotifyNetDisconnect, work is null"); + return; + } + RegisterMissonCB *registerMissonCB = static_cast(work->data); + if (registerMissonCB == nullptr) { + HILOGE("UvWorkNotifyNetDisconnect, registerMissonCB is null"); + return; + } + napi_value result[2] = {0}; + HILOGI("UvWorkNotifyNetDisconnect, deviceId = %{public}s", Str16ToStr8(registerMissonCB->deviceId).c_str()); + result[0] = + WrapString(registerMissonCB->cbBase.cbInfo.env, Str16ToStr8(registerMissonCB->deviceId).c_str(), "deviceId"); + HILOGI("UvWorkNotifyNetDisconnect, state = %{public}d", registerMissonCB->state); + result[1] = + WrapInt32(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->state, "state"); + + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_get_undefined(registerMissonCB->cbBase.cbInfo.env, &undefined); + napi_value callResult = nullptr; + napi_get_reference_value(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->cbBase.cbInfo.callback, &callback); + + napi_call_function(registerMissonCB->cbBase.cbInfo.env, undefined, callback, ARGS_TWO, &result[0], &callResult); + if (registerMissonCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(registerMissonCB->cbBase.cbInfo.env, registerMissonCB->cbBase.cbInfo.callback); + } + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + HILOGI("UvWorkNotifyNetDisconnect, uv_queue_work end"); +} + +void NAPIMissionRegistration::NotifyNetDisconnect(const std::u16string deviceId, int32_t state) +{ + HILOGI("%{public}s called. deviceId = %{public}s. state = %{public}d", __func__, + Str16ToStr8(deviceId).c_str(), state); + uv_loop_s *loop = nullptr; + + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + HILOGE("%{public}s, loop == nullptr.", __func__); + return; + } + + uv_work_t *work = new uv_work_t; + if (work == nullptr) { + HILOGE("%{public}s, work==nullptr.", __func__); + return; + } + + auto registerMissonCB = new (std::nothrow) RegisterMissonCB; + if (registerMissonCB == nullptr) { + HILOGE("%{public}s, registerMissonCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + registerMissonCB->cbBase.cbInfo.env = env_; + registerMissonCB->cbBase.cbInfo.callback = notifyNetDisconnectRef_; + registerMissonCB->deviceId = deviceId; + registerMissonCB->state = state; + work->data = (void *)registerMissonCB; + + int rev = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvWorkNotifyNetDisconnect); + if (rev != 0) { + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } + HILOGI("%{public}s, end.", __func__); +} + +void UnRegisterMissonExecuteCB(napi_env env, void *data) +{ + HILOGI("%{public}s called.", __func__); + auto registerMissonCB = (RegisterMissonCB*)data; + if (registerMissonCB == nullptr) { + HILOGE("%{public}s registerMissonCB == nullptr.", __func__); + registerMissonCB->result = -1; + return; + } + + std::lock_guard autoLock(registrationLock_); + sptr registration; + auto item = registration_.find(registerMissonCB->deviceId); + if (item != registration_.end()) { + HILOGI("registration exits."); + registration = registration_[registerMissonCB->deviceId]; + } else { + HILOGI("registration not exits."); + registerMissonCB->result = -1; + return; + } + registerMissonCB->missionRegistration = registration; + + registerMissonCB->result = -1; + // registerMissonCB->result = + // AbilityManagerClient::GetInstance()-> + // UnRegisterMissionListener(registerMissonCB->deviceId.c_str(), + // registerMissonCB->missionRegistration); + // if (registerMissonCB->result == NO_ERROR) { + // HILOGI("remove registration."); + // registration_.erase(registerMissonCB->deviceId); + // } + // HILOGI("%{public}s end.deviceId:%{public}d ", __func__, registerMissonCB->result); +} + +void UnRegisterMissonPromiseCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOGI("%{public}s called.", __func__); + auto registerMissonCB = (RegisterMissonCB*)data; + // set result + napi_value result[2] = { 0 }; + napi_get_undefined(env, &result[1]); + if (registerMissonCB->result == 0) { + napi_get_undefined(env, &result[0]); + } else { + napi_value message = nullptr; + napi_create_string_utf8(env, ("unRegisterMissionListener failed, error : " + + std::to_string(registerMissonCB->result)).c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(env, nullptr, message, &result[0]); + } + + if (registerMissonCB->callbackRef == nullptr) { // promise + if (registerMissonCB->result == 0) { + napi_resolve_deferred(env, registerMissonCB->cbBase.deferred, result[1]); + } else { + napi_reject_deferred(env, registerMissonCB->cbBase.deferred, result[0]); + } + } else { // AsyncCallback + napi_value callback = nullptr; + napi_get_reference_value(env, registerMissonCB->callbackRef, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult); + napi_delete_reference(env, registerMissonCB->callbackRef); + } + napi_delete_async_work(env, registerMissonCB->cbBase.asyncWork); + delete registerMissonCB; + registerMissonCB = nullptr; + HILOGI("%{public}s end.", __func__); +} + +napi_value UnRegisterMissonPromise(napi_env env, RegisterMissonCB *registerMissonCB) +{ + HILOGI("%{public}s asyncCallback.", __func__); + if (registerMissonCB == nullptr) { + HILOGE("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value promise = nullptr; + if (registerMissonCB->callbackRef == nullptr) { + napi_create_promise(env, ®isterMissonCB->cbBase.deferred, &promise); + } else { + napi_get_undefined(env, &promise); + } + + napi_value resourceName = nullptr; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + UnRegisterMissonExecuteCB, + UnRegisterMissonPromiseCompletedCB, + (void *)registerMissonCB, + ®isterMissonCB->cbBase.asyncWork); + napi_queue_async_work(env, registerMissonCB->cbBase.asyncWork); + HILOGI("%{public}s asyncCallback end.", __func__); + return promise; +} + +bool GetUnRegisterMissonDeviceId(napi_env env, const napi_value& value, RegisterMissonCB *registerMissonCB) +{ + HILOGI("%{public}s called.", __func__); + napi_value firstNApi = nullptr; + napi_valuetype valueType = napi_undefined; + bool isDeviceId = false; + napi_has_named_property(env, value, "deviceId", &isDeviceId); + napi_typeof(env, value, &valueType); + if (isDeviceId && valueType == napi_object) { + napi_get_named_property(env, value, "deviceId", &firstNApi); + } else { + HILOGE("%{public}s, Wrong argument name for deviceId.", __func__); + return false; + } + if (firstNApi == nullptr) { + HILOGE("%{public}s, not find deviceId.", __func__); + return false; + } + + char16_t deviceIdList[VALUE_BUFFER_SIZE] = {0}; + size_t valueLen = 0; + napi_typeof(env, firstNApi, &valueType); + if (valueType != napi_string) { + HILOGE("%{public}s, Wrong argument type.", __func__); + return false; + } + napi_get_value_string_utf16(env, firstNApi, deviceIdList, VALUE_BUFFER_SIZE, &valueLen); + registerMissonCB->deviceId = deviceIdList; + HILOGI("%{public}s deviceId:%{public}s", __func__, Str16ToStr8(registerMissonCB->deviceId).c_str()); + HILOGI("%{public}s called end.", __func__); + return true; +} + +napi_value UnRegisterMissonWrap(napi_env env, napi_callback_info info, RegisterMissonCB *registerMissonCB) +{ + HILOGI("%{public}s called.", __func__); + size_t argc = 2; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + HILOGI("argc is %{public}zu", argc); + if (argc != ARGS_ONE && argc != ARGS_TWO) { + HILOGE("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (!GetUnRegisterMissonDeviceId(env, args[0], registerMissonCB)) { + HILOGE("%{public}s, Wrong argument.", __func__); + return nullptr; + } + + if (argc == ARGS_TWO) { + napi_valuetype valueType = napi_undefined; + napi_typeof(env, args[1], &valueType); + if (valueType != napi_function) { + HILOGE("%{public}s, callback error type.", __func__); + return nullptr; + } + napi_create_reference(env, args[1], 1, ®isterMissonCB->callbackRef); + } + ret = UnRegisterMissonPromise(env, registerMissonCB); + HILOGI("%{public}s called end.", __func__); + return ret; +} + +napi_value NAPI_UnRegisterMissionListener(napi_env env, napi_callback_info info) +{ + HILOGI("%{public}s called.", __func__); + RegisterMissonCB *registerMissonCB = CreateRegisterMissonCBCBInfo(env); + if (registerMissonCB == nullptr) { + HILOGE("%{public}s registerMissonCB == nullptr", __func__); + return nullptr; + } + + napi_value ret = UnRegisterMissonWrap(env, info, registerMissonCB); + if (ret == nullptr) { + HILOGE("%{public}s ret == nullptr", __func__); + if (registerMissonCB != nullptr) { + delete registerMissonCB; + registerMissonCB = nullptr; + } + NAPI_ASSERT(env, ret == nullptr, "wrong arguments"); + } + HILOGI("%{public}s end.", __func__); + return ret; +} + +napi_value WrapString(napi_env env, const std::string& param, const std::string& paramName) +{ + HILOGI("%{public}s called.", __func__); + + napi_value jsObject = nullptr; + napi_create_object(env, &jsObject); + + napi_value jsValue = nullptr; + HILOGI("%{public}s called. %{public}s = %{public}s", __func__, paramName.c_str(), param.c_str()); + napi_create_string_utf8(env, param.c_str(), NAPI_AUTO_LENGTH, &jsValue); + napi_set_named_property(env, jsObject, paramName.c_str(), jsValue); + + return jsObject; +} + +napi_value WrapInt32(napi_env env, int32_t num, const std::string& paramName) +{ + HILOGI("%{public}s called.", __func__); + + napi_value jsObject = nullptr; + napi_create_object(env, &jsObject); + + napi_value jsValue = nullptr; + HILOGI("%{public}s called. %{public}s = %{public}d", __func__, paramName.c_str(), num); + napi_create_int32(env, num, &jsValue); + napi_set_named_property(env, jsObject, paramName.c_str(), jsValue); + + return jsObject; +} + +ContinueAbilityCB *CreateContinueAbilityCBCBInfo(napi_env env) +{ + HILOGI("%{public}s called.", __func__); + auto continueAbilityCB = new (std::nothrow) ContinueAbilityCB; + if (continueAbilityCB == nullptr) { + HILOGE("%{public}s continueAbilityCB == nullptr", __func__); + return nullptr; + } + continueAbilityCB->cbBase.cbInfo.env = env; + continueAbilityCB->cbBase.asyncWork = nullptr; + continueAbilityCB->cbBase.deferred = nullptr; + HILOGI("%{public}s end.", __func__); + return continueAbilityCB; +} + +void ContinueAbilityExecuteCB(napi_env env, void *data) +{ + HILOGI("%{public}s called.", __func__); + auto continueAbilityCB = static_cast(data); + if (continueAbilityCB == nullptr) { + HILOGE("%{public}s continueAbilityCB == nullptr.", __func__); + return; + } + HILOGI("create continueAbilityCB success."); + sptr continuation(new (std::nothrow) NAPIMissionRegistration()); + continueAbilityCB->abilityContinuation = continuation; + if (continueAbilityCB->abilityContinuation == nullptr) { + HILOGE("%{public}s abilityContinuation == nullptr.", __func__); + return; + } + continueAbilityCB->abilityContinuation->SetContinueAbilityEnv(env); + HILOGI("set env success."); + continueAbilityCB->abilityContinuation-> + SetContinueAbilityCBRef(continueAbilityCB->abilityContinuationCB.callback[0]); + HILOGI("set callback success."); + continueAbilityCB->result = -1; + // continueAbilityCB->result = AAFwk::AbilityManagerClient::GetInstance()-> + // ContinueMission(continueAbilityCB->srcDeviceId, continueAbilityCB->dstDeviceId, + // continueAbilityCB->missionId, continueAbilityCB->abilityContinuation, + // continueAbilityCB->wantParams); + HILOGI("%{public}s end. error:%{public}d ", __func__, continueAbilityCB->result); +} + +void ContinueAbilityCallbackCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOGI("%{public}s called.", __func__); + auto continueAbilityCB = static_cast(data); + // set result + napi_value result[2] = { 0 }; + napi_get_undefined(env, &result[1]); + if (continueAbilityCB->result == 0) { + napi_get_undefined(env, &result[0]); + } else { + napi_value message = nullptr; + napi_create_string_utf8(env, ("ContinueAbility failed, error : " + + std::to_string(continueAbilityCB->result)).c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(env, nullptr, message, &result[0]); + } + + if (continueAbilityCB->callbackRef == nullptr) { // promise + if (continueAbilityCB->result == 0) { + napi_resolve_deferred(env, continueAbilityCB->cbBase.deferred, result[1]); + } else { + napi_reject_deferred(env, continueAbilityCB->cbBase.deferred, result[0]); + } + } else { // AsyncCallback + napi_value callback = nullptr; + napi_get_reference_value(env, continueAbilityCB->callbackRef, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult); + napi_delete_reference(env, continueAbilityCB->callbackRef); + } + napi_delete_async_work(env, continueAbilityCB->cbBase.asyncWork); + delete continueAbilityCB; + continueAbilityCB = nullptr; + HILOGI("%{public}s end.", __func__); +} + +napi_value ContinueAbilityAsync(napi_env env, napi_value *args, ContinueAbilityCB *continueAbilityCB) +{ + HILOGI("%{public}s asyncCallback.", __func__); + if (args == nullptr || continueAbilityCB == nullptr) { + HILOGE("%{public}s, param == nullptr.", __func__); + return nullptr; + } + + napi_value result = nullptr; + if (continueAbilityCB->callbackRef == nullptr) { + napi_create_promise(env, &continueAbilityCB->cbBase.deferred, &result); + } else { + napi_get_undefined(env, &result); + } + + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "ContinueAbilityAsyncForLauncher", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + ContinueAbilityExecuteCB, + ContinueAbilityCallbackCompletedCB, + (void *)continueAbilityCB, + &continueAbilityCB->cbBase.asyncWork); + napi_queue_async_work(env, continueAbilityCB->cbBase.asyncWork); + HILOGI("%{public}s asyncCallback end.", __func__); + return result; +} + +bool CheckContinueFirstArgs(napi_env env, const napi_value &value, ContinueAbilityCB *continueAbilityCB) +{ + HILOGI("%{public}s called.", __func__); + bool isSrcDeviceId = false; + napi_has_named_property(env, value, "srcDeviceId", &isSrcDeviceId); + bool isDstDeviceId = false; + napi_has_named_property(env, value, "dstDeviceId", &isDstDeviceId); + bool isMissionId = false; + napi_has_named_property(env, value, "missionId", &isMissionId); + bool isWantParam = false; + napi_has_named_property(env, value, "wantParam", &isWantParam); + if (!isSrcDeviceId && !isDstDeviceId && !isMissionId && !isWantParam) { + HILOGE("%{public}s, Wrong argument key.", __func__); + return false; + } + napi_value firstNApi = nullptr; + napi_value secondNApi = nullptr; + napi_value thirdNApi = nullptr; + napi_value fourthNApi = nullptr; + napi_valuetype valueType = napi_undefined; + napi_typeof(env, value, &valueType); + if (valueType == napi_object) { + napi_get_named_property(env, value, "srcDeviceId", &firstNApi); + napi_get_named_property(env, value, "dstDeviceId", &secondNApi); + napi_get_named_property(env, value, "missionId", &thirdNApi); + napi_get_named_property(env, value, "wantParam", &fourthNApi); + } else { + HILOGE("%{public}s, Wrong argument type.", __func__); + return false; + } + if (firstNApi == nullptr || secondNApi == nullptr || thirdNApi == nullptr || fourthNApi == nullptr) { + HILOGE("%{public}s, miss required parameters.", __func__); + return false; + } + napi_typeof(env, firstNApi, &valueType); + if (valueType != napi_string) { + HILOGE("%{public}s, Wrong argument type srcDeviceId.", __func__); + return false; + } + continueAbilityCB->srcDeviceId = AppExecFwk::UnwrapStringFromJS(env, firstNApi, ""); + napi_typeof(env, secondNApi, &valueType); + if (valueType == napi_string) { + continueAbilityCB->dstDeviceId = AppExecFwk::UnwrapStringFromJS(env, secondNApi, ""); + HILOGI("dstDeviceId is %{public}s", continueAbilityCB->dstDeviceId.c_str()); + } else { + HILOGE("%{public}s, Wrong argument type dstDeviceId.", __func__); + return false; + } + napi_typeof(env, thirdNApi, &valueType); + if (valueType != napi_number) { + HILOGE("%{public}s, Wrong argument type missionId.", __func__); + return false; + } + continueAbilityCB->missionId = AppExecFwk::UnwrapInt32FromJS(env, thirdNApi, -1); + napi_typeof(env, fourthNApi, &valueType); + if (valueType != napi_object) { + HILOGE("%{public}s, Wrong argument type wantParam.", __func__); + return false; + } + AppExecFwk::UnwrapWantParams(env, fourthNApi, continueAbilityCB->wantParams); + HILOGI("%{public}s called end.", __func__); + return true; +} + +napi_value ContinueAbilityWrap(napi_env env, napi_callback_info info, ContinueAbilityCB *continueAbilityCB) +{ + HILOGI("%{public}s called.", __func__); + size_t argcAsync = 3; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr); + HILOGI("argcAsync is %{public}zu", argcAsync); + if (argcAsync != ARGS_TWO && argcAsync != ARGS_THREE) { + HILOGE("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (!CheckContinueFirstArgs(env, args[0], continueAbilityCB)) { + HILOGE("%{public}s, Wrong first arguments.", __func__); + return nullptr; + } + + if (argcAsync > 1) { + napi_value jsMethod = nullptr; + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[1], &valuetype); + if (valuetype == napi_object) { + bool isFirstCallback = false; + napi_has_named_property(env, args[1], "onContinueDone", &isFirstCallback); + if (!isFirstCallback) { + HILOGE("%{public}s, Wrong argument name for onContinueDone.", __func__); + return nullptr; + } + napi_get_named_property(env, args[1], "onContinueDone", &jsMethod); + if (jsMethod == nullptr) { + HILOGE("%{public}s, not find callback onContinueDone.", __func__); + return nullptr; + } + napi_typeof(env, jsMethod, &valuetype); + if (valuetype != napi_function) { + HILOGE("%{public}s, onContinueDone callback error type.", __func__); + return nullptr; + } + napi_create_reference(env, jsMethod, 1, &continueAbilityCB->abilityContinuationCB.callback[0]); + } else { + HILOGE("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + } + + if (argcAsync == ARGS_THREE) { + napi_valuetype valueType = napi_undefined; + napi_typeof(env, args[ARGS_TWO], &valueType); + if (valueType != napi_function) { + HILOGE("%{public}s, callback error type.", __func__); + return nullptr; + } + napi_create_reference(env, args[ARGS_TWO], 1, &continueAbilityCB->callbackRef); + } + + ret = ContinueAbilityAsync(env, args, continueAbilityCB); + HILOGI("%{public}s called end.", __func__); + return ret; +} + +napi_value NAPI_ContinueAbility(napi_env env, napi_callback_info info) +{ + HILOGI("%{public}s called.", __func__); + ContinueAbilityCB *continueAbilityCB = CreateContinueAbilityCBCBInfo(env); + if (continueAbilityCB == nullptr) { + HILOGE("%{public}s continueAbilityCB == nullptr", __func__); + return nullptr; + } + + napi_value ret = ContinueAbilityWrap(env, info, continueAbilityCB); + if (ret == nullptr) { + HILOGE("%{public}s ret == nullptr", __func__); + if (continueAbilityCB != nullptr) { + delete continueAbilityCB; + continueAbilityCB = nullptr; + } + NAPI_ASSERT(env, ret == nullptr, "wrong arguments"); + } + HILOGI("%{public}s end.", __func__); + return ret; +} + +void UvWorkOnContinueDone(uv_work_t *work, int status) +{ + HILOGI("UvWorkOnCountinueDone, uv_queue_work"); + if (work == nullptr) { + HILOGE("UvWorkOnCountinueDone, work is null"); + return; + } + ContinueAbilityCB *continueAbilityCB = static_cast(work->data); + if (continueAbilityCB == nullptr) { + HILOGE("UvWorkOnCountinueDone, continueAbilityCB is null"); + return; + } + napi_value result = nullptr; + HILOGI("UvWorkOnCountinueDone, resultCode = %{public}d", continueAbilityCB->resultCode); + result = + WrapInt32(continueAbilityCB->cbBase.cbInfo.env, continueAbilityCB->resultCode, "resultCode"); + + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_get_undefined(continueAbilityCB->cbBase.cbInfo.env, &undefined); + napi_value callResult = nullptr; + napi_get_reference_value(continueAbilityCB->cbBase.cbInfo.env, + continueAbilityCB->cbBase.cbInfo.callback, &callback); + + napi_call_function(continueAbilityCB->cbBase.cbInfo.env, undefined, callback, 1, &result, &callResult); + if (continueAbilityCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(continueAbilityCB->cbBase.cbInfo.env, continueAbilityCB->cbBase.cbInfo.callback); + } + if (continueAbilityCB != nullptr) { + delete continueAbilityCB; + continueAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + HILOGI("UvWorkOnCountinueDone, uv_queue_work end"); +} + +void NAPIMissionRegistration::OnContinueDone(int32_t result) +{ + HILOGI("%{public}s, called. result = %{public}d", __func__, result); + uv_loop_s *loop = nullptr; + + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + HILOGE("%{public}s, loop == nullptr.", __func__); + return; + } + + uv_work_t *work = new uv_work_t; + if (work == nullptr) { + HILOGE("%{public}s, work==nullptr.", __func__); + return; + } + + auto continueAbilityCB = new (std::nothrow) ContinueAbilityCB; + if (continueAbilityCB == nullptr) { + HILOGE("%{public}s, continueAbilityCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + continueAbilityCB->cbBase.cbInfo.env = env_; + continueAbilityCB->cbBase.cbInfo.callback = onContinueDoneRef_; + continueAbilityCB->resultCode = result; + work->data = (void *)continueAbilityCB; + + int rev = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvWorkOnContinueDone); + if (rev != 0) { + if (continueAbilityCB != nullptr) { + delete continueAbilityCB; + continueAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } + HILOGI("%{public}s, end.", __func__); +} + +void NAPIMissionRegistration::SetContinueAbilityEnv(const napi_env &env) +{ + env_ = env; +} + +void NAPIMissionRegistration::SetContinueAbilityCBRef(const napi_ref &ref) +{ + onContinueDoneRef_ = ref; +} + +napi_value DistributedMissionManagerExport(napi_env env, napi_value exports) +{ + HILOGI("%{public}s,called", __func__); + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("startSyncRemoteMissions", NAPI_StartSyncRemoteMissions), + DECLARE_NAPI_FUNCTION("stopSyncRemoteMissions", NAPI_StopSyncRemoteMissions), + DECLARE_NAPI_FUNCTION("registerMissionListener", NAPI_RegisterMissionListener), + DECLARE_NAPI_FUNCTION("unRegisterMissionListener", NAPI_UnRegisterMissionListener), + DECLARE_NAPI_FUNCTION("continueAbility", NAPI_ContinueAbility), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties)); + return exports; +} + +static napi_module missionModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = DistributedMissionManagerExport, + .nm_modname = "missionRegistration", + .nm_priv = ((void*)0), + .reserved = {0} +}; + +extern "C" __attribute__((constructor)) void AbilityRegister() +{ + napi_module_register(&missionModule); +} +} +} \ No newline at end of file diff --git a/interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.h b/interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.h new file mode 100644 index 00000000000..b6f3f097983 --- /dev/null +++ b/interfaces/kits/napi/aafwk/mission_manager/napi_mission_registration.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_MISSION_MANAGER_H +#define OHOS_DISTRIBUTED_MISSION_MANAGER_H + +#include + +#include "distributed_sched_interface.h" +#include "mission_callback_interface.h" +#include "mission_callback_stub.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "parcel_helper.h" +#include "securec.h" +#include "want.h" + +namespace OHOS { +namespace DistributedSchedule { +napi_value NAPI_StartSyncRemoteMissions(napi_env env, napi_callback_info info); +napi_value NAPI_StopSyncRemoteMissions(napi_env env, napi_callback_info info); +napi_value NAPI_RegisterMissionListener(napi_env env, napi_callback_info info); +napi_value NAPI_UnRegisterMissionListener(napi_env env, napi_callback_info info); +napi_value NAPI_ContinueAbility(napi_env env, napi_callback_info info); +napi_value WrapString(napi_env env, const std::string& deviceId, const std::string& paramName); +napi_value WrapInt32(napi_env env, int32_t num, const std::string& paramName); + +class NAPIMissionRegistration : public MissionCallbackStub { +public: + void NotifyMissionsChanged(const std::u16string deviceId) override; + void NotifySnapshot(const std::u16string deviceId, int32_t missionId) override; + void NotifyNetDisconnect(const std::u16string deviceId, int32_t state) override; + void OnContinueDone(int32_t result) override; + void SetContinueEnv(const napi_env &env); + void SetEnv(const napi_env &env); + void SetNotifyMissionsChangedCBRef(const napi_ref &ref); + void SetNotifySnapshotCBRef(const napi_ref &ref); + void SetNotifyNetDisconnectCBRef(const napi_ref &ref); + void SetContinueAbilityEnv(const napi_env &env); + void SetContinueAbilityCBRef(const napi_ref &ref); + +private: + napi_env env_ = nullptr; + napi_ref notifyMissionsChangedRef_ = nullptr; + napi_ref notifySnapshotRef_ = nullptr; + napi_ref notifyNetDisconnectRef_ = nullptr; + napi_ref onContinueDoneRef_ = nullptr; +}; + +struct CallbackInfo { + napi_env env; + napi_ref callback; + napi_deferred deferred; +}; + +struct CBBase { + CallbackInfo cbInfo; + napi_async_work asyncWork; + napi_deferred deferred; + int errCode = 0; +}; + +struct MissionRegistrationCB { + napi_env env = nullptr; + napi_ref callback[3] = {0}; + int resultCode = 0; +}; + +struct RegisterMissonCB { + CBBase cbBase; + std::u16string deviceId; + sptr missionRegistration; + MissionRegistrationCB missionRegistrationCB; + int result = 0; + int missionId = 0; + int state = 0; + napi_ref callbackRef; +}; + +struct AbilityContinuationCB { + napi_env env; + napi_ref callback[1] = {0}; +}; + +struct ContinueAbilityCB { + CBBase cbBase; + std::string dstDeviceId; + std::string srcDeviceId; + sptr abilityContinuation; + AbilityContinuationCB abilityContinuationCB; + AAFwk::WantParams wantParams; + ErrCode result = 0; + int resultCode = 0; + int missionId = 0; + napi_ref callbackRef; +}; + +struct SyncRemoteMissionsContext { + napi_env env; + napi_async_work work; + + char16_t deviceId[128] = {0}; + size_t valueLen = 0; + bool fixConflict = false; + int64_t tag = -1; + int result = 0; + + napi_deferred deferred; + napi_ref callbackRef; +}; + +bool SetSyncRemoteMissionsContext( + const napi_env &env, const napi_value &value, SyncRemoteMissionsContext* context); +bool ProcessSyncInput(napi_env env, napi_callback_info info, bool isStart, + SyncRemoteMissionsContext* syncContext); +std::mutex registrationLock_; +static std::map> registration_; + +enum ErrorCode { + NO_ERROR = 0, + INVALID_PARAMETER = -1, + MISSION_NOT_FOUND = -2, + PERMISSION_DENY = -3, + REGISTRATION_NOT_FOUND = -4, +}; +} // namespace DistributedSchedule +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_MISSION_MANAGER_H \ No newline at end of file -- Gitee