From 1803e6f4e868627f1e1377ff55a475d4c53af768 Mon Sep 17 00:00:00 2001 From: mjh Date: Tue, 26 Aug 2025 17:08:06 +0800 Subject: [PATCH] cloud disk interface Signed-off-by: mjh --- BUILD.gn | 7 + bundle.json | 16 + .../cloud_disk_service_callback_client.h | 42 ++ .../cloud_disk_service_callback_stub.h | 39 ++ .../include/cloud_disk_service_manager_impl.h | 47 +++ .../include/service_proxy.h | 45 ++ .../src/cloud_disk_common.cpp | 57 +++ .../cloud_disk_service_callback_client.cpp | 19 + .../src/cloud_disk_service_callback_stub.cpp | 58 +++ .../src/cloud_disk_service_manager.cpp | 24 ++ .../src/cloud_disk_service_manager_impl.cpp | 106 +++++ .../src/cloud_disk_service_task_manager.cpp | 152 +++++++ .../src/service_proxy.cpp | 101 +++++ .../clouddiskservice_kit_inner/BUILD.gn | 99 +++++ .../cloud_disk_common.h | 47 +++ .../cloud_disk_service_callback.h | 30 ++ .../cloud_disk_service_manager.h | 37 ++ .../cloud_disk_service_task_manager.h | 71 ++++ .../i_cloud_disk_service_callback.h | 33 ++ .../svc_death_recipient.h | 41 ++ interfaces/kits/js/clouddiskmanager/BUILD.gn | 68 +++ .../cloud_disk_manager_napi.cpp | 56 +++ .../cloud_disk_manager_napi.h | 24 ++ .../cloud_disk_manager_napi_utils.cpp | 237 +++++++++++ .../cloud_disk_manager_napi_utils.h | 40 ++ .../sync_folder_handler_callback_napi.cpp | 179 ++++++++ .../sync_folder_handler_callback_napi.h | 48 +++ .../sync_folder_handler_napi.cpp | 399 ++++++++++++++++++ .../sync_folder_handler_napi.h | 44 ++ services/5207.json | 19 + services/BUILD.gn | 5 + services/clouddiskservice/BUILD.gn | 123 ++++++ .../clouddiskservice/ICloudDiskService.idl | 22 + .../include/ipc/cloud_disk_service.h | 65 +++ .../ipc/cloud_disk_service_callback_manager.h | 37 ++ .../ipc/cloud_disk_service_callback_proxy.h | 36 ++ .../src/ipc/cloud_disk_service.cpp | 107 +++++ .../cloud_disk_service_callback_manager.cpp | 45 ++ .../ipc/cloud_disk_service_callback_proxy.cpp | 54 +++ services/distributedfile.cfg | 9 + 40 files changed, 2688 insertions(+) create mode 100644 frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_client.h create mode 100644 frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_stub.h create mode 100644 frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_manager_impl.h create mode 100644 frameworks/native/clouddiskservice_kit_inner/include/service_proxy.h create mode 100644 frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp create mode 100644 frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_client.cpp create mode 100644 frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_stub.cpp create mode 100644 frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager.cpp create mode 100644 frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager_impl.cpp create mode 100644 frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_task_manager.cpp create mode 100644 frameworks/native/clouddiskservice_kit_inner/src/service_proxy.cpp create mode 100644 interfaces/inner_api/native/clouddiskservice_kit_inner/BUILD.gn create mode 100644 interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_common.h create mode 100644 interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_callback.h create mode 100644 interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_manager.h create mode 100644 interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_task_manager.h create mode 100644 interfaces/inner_api/native/clouddiskservice_kit_inner/i_cloud_disk_service_callback.h create mode 100644 interfaces/inner_api/native/clouddiskservice_kit_inner/svc_death_recipient.h create mode 100644 interfaces/kits/js/clouddiskmanager/BUILD.gn create mode 100644 interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.cpp create mode 100644 interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.h create mode 100644 interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.cpp create mode 100644 interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.h create mode 100644 interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.cpp create mode 100644 interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.h create mode 100644 interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.cpp create mode 100644 interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.h create mode 100644 services/5207.json create mode 100644 services/clouddiskservice/BUILD.gn create mode 100644 services/clouddiskservice/ICloudDiskService.idl create mode 100644 services/clouddiskservice/include/ipc/cloud_disk_service.h create mode 100644 services/clouddiskservice/include/ipc/cloud_disk_service_callback_manager.h create mode 100644 services/clouddiskservice/include/ipc/cloud_disk_service_callback_proxy.h create mode 100644 services/clouddiskservice/src/ipc/cloud_disk_service.cpp create mode 100644 services/clouddiskservice/src/ipc/cloud_disk_service_callback_manager.cpp create mode 100644 services/clouddiskservice/src/ipc/cloud_disk_service_callback_proxy.cpp diff --git a/BUILD.gn b/BUILD.gn index e77869cad..b2eb4efcf 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -16,6 +16,7 @@ import("//foundation/filemanagement/dfs_service/distributedfile.gni") group("services_target") { deps = [ + "${services_path}:clouddiskservice_sa_profile", "${services_path}:cloudsyncservice.para", "${services_path}:cloudsyncservice.para.dac", "${services_path}:distributed_file.para", @@ -24,6 +25,7 @@ group("services_target") { "${services_path}/clouddisk_database:clouddisk_database", "${services_path}/cloudfiledaemon:cloudfiledaemon", "${services_path}/cloudsyncservice:cloudsync_sa", + "${services_path}/clouddiskservice:clouddiskservice_sa", ] if (dfs_service_feature_enable_dist_file_daemon) { @@ -50,6 +52,11 @@ group("cloud_file_kit_inner_target") { deps = [ "interfaces/inner_api/native/cloud_file_kit_inner:cloudfile_kit" ] } +group("clouddiskservice_kit_inner_target") { + deps = + [ "interfaces/inner_api/native/clouddiskservice_kit_inner:clouddiskservice_kit_inner" ] +} + group("cloudsync_asset_kit_inner_target") { deps = [ "interfaces/inner_api/native/cloudsync_kit_inner:cloudsync_asset_kit_inner", diff --git a/bundle.json b/bundle.json index 5460115ae..c9ee1327c 100644 --- a/bundle.json +++ b/bundle.json @@ -82,12 +82,14 @@ "fwk_group": [], "service_group": [ "//foundation/filemanagement/dfs_service:services_target", + "//foundation/filemanagement/dfs_service:clouddiskservice_kit_inner_target", "//foundation/filemanagement/dfs_service:cloudsync_kit_inner_target", "//foundation/filemanagement/dfs_service:cloud_daemon_kit_inner_target", "//foundation/filemanagement/dfs_service:cloud_file_kit_inner_target", "//foundation/filemanagement/dfs_service:cloudsync_asset_kit_inner_target", "//foundation/filemanagement/dfs_service:distributed_file_daemon_kit_inner_target", "//foundation/filemanagement/dfs_service/interfaces/kits/js/ani:ani_package", + "//foundation/filemanagement/dfs_service/interfaces/kits/js/clouddiskmanager:clouddiskmanager", "//foundation/filemanagement/dfs_service/interfaces/kits/js/cloudsyncmanager:cloudsyncmanager", "//foundation/filemanagement/dfs_service/interfaces/kits/js/cloudfilesync:cloudsync", "//foundation/filemanagement/dfs_service/adapter/cloud_adapter_example:cloud_adapter_example_target" @@ -108,6 +110,20 @@ "header_base": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/cloudsync_kit_inner" } }, + { + "name": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/clouddiskservice_kit_inner:clouddiskservice_kit_inner", + "header": { + "header_files": [ + "cloud_disk_common.h", + "cloud_disk_service_callback.h", + "cloud_disk_service_manager.h", + "cloud_disk_service_task_manager.h", + "i_cloud_disk_service_callback.h", + "svc_death_recipient.h" + ], + "header_base": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/clouddiskservice_kit_inner" + } + }, { "name": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/cloudsync_kit_inner:cloudsync_asset_kit_inner", "header": { diff --git a/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_client.h b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_client.h new file mode 100644 index 000000000..75b02c641 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_client.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_CLIENT_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_CLIENT_H + +#include "cloud_disk_service_callback.h" +#include "cloud_disk_service_callback_stub.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceCallbackClient final : public CloudDiskServiceCallbackStub { +public: + explicit CloudDiskServiceCallbackClient(const std::shared_ptr &callback) + :callback_(callback) {} + + int32_t OnChangeData(ChangeData & changeData) override { + if (callback_ == nullptr) { + LOGE("callback_ is nullptr"); + return 0; + } + callback_->OnChangeData(changeData); + return 0; + } +private: + std::shared_ptr callback_{ nullptr }; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_CLIENT_H \ No newline at end of file diff --git a/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_stub.h b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_stub.h new file mode 100644 index 000000000..452e0013d --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_stub.h @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_STUB_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_STUB_H + +#include + +#include "i_cloud_disk_service_callback.h" +#include "iremote_stub.h" + +namespace OHOS::FileManagement::CloudDiskService { +using ServiceInterface = std::function; +class CloudDiskServiceCallbackStub : public IRemoteStub { +public: + CloudDiskServiceCallbackStub(); + virtual ~CloudDiskServiceCallbackStub() = default; + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + std::map opToInterfaceMap_; + + int32_t HandleOnChangeData(MessageParcel &data, MessageParcel &reply); +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_STUB_H \ No newline at end of file diff --git a/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_manager_impl.h b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_manager_impl.h new file mode 100644 index 000000000..4b22d6367 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_manager_impl.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_IMPL_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_IMPL_H + +#include + +#include "nocopyable.h" + +#include "cloud_disk_service_manager.h" +#include "cloud_disk_service_callback_client.h" +#include "svc_death_recipient.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceManagerImpl final : public CloudDiskServiceManager, public NoCopyable { +public: + static CloudDiskServiceManagerImpl &GetInstance(); + + int32_t RegisterSyncRootChanges(const std::string &syncRootUri, + const std::shared_ptr changeCallback, std::string &syncRootIndex) override; + int32_t UnregisterSyncRootChanges(const std::string &syncRootUri, bool &isOk) override; + int32_t GetSyncRootChanges(const std::string &syncRootUri, int32_t maxSize, + std::vector &syncRootRecords) override; + +private: + void SetDeathRecipient(const sptr &remoteObject); + std::shared_ptr callback_; + sptr deathRecipient_; + std::mutex callbackMutex_; + std::atomic_flag isFirstCall_{false}; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_IMPL_H diff --git a/frameworks/native/clouddiskservice_kit_inner/include/service_proxy.h b/frameworks/native/clouddiskservice_kit_inner/include/service_proxy.h new file mode 100644 index 000000000..9133dffc6 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/service_proxy.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_SERVICE_PROXY_H +#define OHOS_FILEMGMT_SERVICE_PROXY_H + +#include "icloud_disk_service.h" +#include "iremote_proxy.h" +#include "system_ability_load_callback_stub.h" + +namespace OHOS::FileManagement::CloudDiskService { +class ServiceProxy : public IRemoteProxy { +public: + static sptr GetInstance(); + static void InvaildInstance(); + + class CloudDiskServiceProxyLoadCallback : public SystemAbilityLoadCallbackStub { + public: + void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr &remoteObject) override; + void OnLoadSystemAbilityFail(int32_t systemAbilityId) override; + + std::condition_variable proxyConVar_; + std::atomic isLoadSuccess_{false}; + }; + +private: + static inline std::mutex proxyMutex_; + static inline std::mutex instanceMutex_; + static inline sptr serviceProxy_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_SERVICE_PROXY_H diff --git a/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp new file mode 100644 index 000000000..b67f1df11 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_common.h" + +#include + +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +namespace { +} + +bool ChangeData::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteUint64(operationType)) { + LOGE("failed to write operationType"); + return false; + } + + return true; +} + +ChangeData *ChangeData::Unmarshalling(Parcel &parcel) +{ + ChangeData *info = new (std::nothrow) ChangeData(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool ChangeData::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.WriteUint64(operationType)) { + LOGE("failed to read operationType"); + return false; + } + + return true; +} + +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_client.cpp b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_client.cpp new file mode 100644 index 000000000..148c3423c --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_client.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service_callback_client.h" + +namespace OHOS::FileManagement::CloudDiskService { +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_stub.cpp b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_stub.cpp new file mode 100644 index 000000000..251750f76 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_stub.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service_callback_stub.h" +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +CloudDiskServiceCallbackStub::CloudDiskServiceCallbackStub() +{ + opToInterfaceMap_[SERVICE_CMD_ON_PROCESS] = [this](MessageParcel &data, MessageParcel &reply) { + return this->HandleOnChangeData(data, reply); + }; +} + +int32_t CloudDiskServiceCallbackStub::OnRemoteRequest(uint32_t code, + MessageParcel &data, + MessageParcel &reply, + MessageOption &option) +{ + if (data.ReadInterfaceToken() != GetDescriptor()) { + return E_SERVICE_DESCRIPTOR_IS_EMPTY; + } + auto interfaceIndex = opToInterfaceMap_.find(code); + if (interfaceIndex == opToInterfaceMap_.end() || !interfaceIndex->second) { + LOGE("Cannot response request %d: unknown tranction", code); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + auto memberFunc = interfaceIndex->second; + return memberFunc(data, reply); +} + +int32_t CloudDiskServiceCallbackStub::HandleOnChangeData(MessageParcel &data, MessageParcel &reply) +{ + sptr progress = data.ReadParcelable(); + if (!progress) { + LOGE("object of ChangeData is nullptr"); + return E_INVAL_ARG; + } + OnChangeData(*progress); + LOGI("OnChangeData"); + return E_OK; +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager.cpp b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager.cpp new file mode 100644 index 000000000..808ff75d8 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service_manager_impl.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +CloudDiskServiceManager &CloudDiskServiceManager::GetInstance() +{ + return CloudDiskServiceManagerImpl::GetInstance(); +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager_impl.cpp b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager_impl.cpp new file mode 100644 index 000000000..5bfe65b5d --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager_impl.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service_manager_impl.h" + +#include "cloud_disk_service_callback_client.h" +#include "dfs_error.h" +#include "iservice_registry.h" +#include "service_proxy.h" +#include "system_ability_definition.h" +#include "utils_directory.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +CloudDiskServiceManagerImpl &CloudDiskServiceManagerImpl::GetInstance() +{ + static CloudDiskServiceManagerImpl instance; + return instance; +} + +void CloudDiskServiceManagerImpl::SetDeathRecipient(const sptr &remoteObject) +{ + if (!isFirstCall_.test_and_set()) { + auto deathCallback = [this](const wptr &obj) { + LOGE("service died."); + ServiceProxy::InvaildInstance(); + if (callback_) { + callback_->OnDeathRecipient(); + } + isFirstCall_.clear(); + }; + deathRecipient_ = sptr(new SvcDeathRecipient(deathCallback)); + if (!remoteObject->AddDeathRecipient(deathRecipient_)) { + LOGE("add death recipient failed"); + isFirstCall_.clear(); + } + } +} + +int32_t CloudDiskServiceManagerImpl::RegisterSyncRootChanges(const std::string &syncRootUri, + const std::shared_ptr changeCallback, std::string &syncRootIndex) +{ + LOGI("RegisterSyncRootChanges start, syncRootUri: %{public}s", syncRootUri.c_str()); + auto CloudDiskServiceProxy = ServiceProxy::GetInstance(); + if (CloudDiskServiceProxy == nullptr) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + sptr changeDataCb = + sptr(new (std::nothrow) CloudDiskServiceCallbackClient(changeCallback)); + if (changeDataCb == nullptr) { + LOGE("changeDataCb is null"); + return E_SA_LOAD_FAILED; + } + int32_t ret = CloudDiskServiceProxy->RegisterSyncRootChanges(syncRootUri, changeDataCb, syncRootIndex); + SetDeathRecipient(CloudDiskServiceProxy->AsObject()); + LOGI("RegisterSyncRootChanges ret: %{public}d, syncRootIndex: %{public}s", ret, syncRootIndex.c_str()); + return ret; +} + +int32_t CloudDiskServiceManagerImpl::UnregisterSyncRootChanges(const std::string &syncRootUri, bool &isOk) +{ + LOGI("UnregisterSyncRootChanges start, syncRootUri: %{public}s", syncRootUri.c_str()); + auto CloudDiskServiceProxy = ServiceProxy::GetInstance(); + if (CloudDiskServiceProxy == nullptr) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + int32_t ret = CloudDiskServiceProxy->UnregisterSyncRootChanges(syncRootUri, isOk); + SetDeathRecipient(CloudDiskServiceProxy->AsObject()); + LOGI("UnregisterSyncRootChanges ret: %{public}d, isOk: %{public}d", ret, isOk); + return ret; +} + +int32_t CloudDiskServiceManagerImpl::GetSyncRootChanges(const std::string &syncRootUri, int32_t maxSize, + std::vector &syncRootRecords) +{ + LOGI("GetSyncRootChanges start, syncRootUri: %{public}s, maxSize: %{public}d", syncRootUri.c_str(), maxSize); + auto CloudDiskServiceProxy = ServiceProxy::GetInstance(); + if (CloudDiskServiceProxy == nullptr) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + int32_t ret = E_OK; + //int32_t ret = CloudDiskServiceProxy->GetSyncRootChanges(syncRootUri, isOk); + SetDeathRecipient(CloudDiskServiceProxy->AsObject()); + LOGI("GetSyncRootChanges ret: %{public}d", ret); + return ret; +} +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_task_manager.cpp b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_task_manager.cpp new file mode 100644 index 000000000..c701d1599 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_task_manager.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service_task_manager.h" + +#include "iservice_registry.h" +#include "mem_mgr_client.h" +#include "parameters.h" +#include "system_ability_definition.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +using namespace std; + +const int32_t DELAY_TIME = 90000; // ms +const int32_t SYSTEM_LOAD_DELAY_TIME = 600000; // ms + +CloudDiskServiceTaskManager &CloudDiskServiceTaskManager::GetInstance() +{ + static CloudDiskServiceTaskManager instance; + return instance; +} + +CloudDiskServiceTaskManager::CloudDiskServiceTaskManager() : queue_("unloadTask") +{ +} + +void CloudDiskServiceTaskManager::StartTask(TaskKey key, TaskType task) +{ + CancelUnloadTask(); + std::lock_guard lock(taskMapsMutex_); + if (criticalStatus_ == false) { + int32_t ret = Memory::MemMgrClient::GetInstance().SetCritical(getpid(), + true, FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID); + if (ret == ERR_OK) { + criticalStatus_ = true; + } + } + auto iterator = taskMaps_.find(key); + if (iterator == taskMaps_.end()) { + taskMaps_[key] = static_cast(task); + return; + } + auto taskState = iterator->second | static_cast(task); + taskMaps_[key] = taskState; +} + +void CloudDiskServiceTaskManager::CompleteTask(TaskKey key, TaskType task) +{ + std::lock_guard lock(taskMapsMutex_); + auto iterator = taskMaps_.find(key); + if (iterator == taskMaps_.end()) { + LOGE("task is not started"); + } else { + taskMaps_[key] = iterator->second & ~static_cast(task); + if (taskMaps_[key] == 0) { + LOGI("start erase"); + taskMaps_.erase(key); + } + } + if (taskMaps_.empty()) { + DelayUnloadTask(true); + } +} + +void CloudDiskServiceTaskManager::StartTask() +{ + std::lock_guard lock(taskMapsMutex_); + if (taskMaps_.empty()) { + DelayUnloadTask(false); + } +} + +bool CloudDiskServiceTaskManager::HasTask(TaskKey key, TaskType task) +{ + std::lock_guard lock(taskMapsMutex_); + auto iterator = taskMaps_.find(key); + if (iterator != taskMaps_.end()) { + if (taskMaps_[key] & static_cast(task)) { + return true; + } + } + return false; +} + + +void CloudDiskServiceTaskManager::CancelUnloadTask() +{ + std::lock_guard lock(unloadTaskMutex_); + if (unloadTaskHandle_ == nullptr) { + return; + } + LOGD("cancel unload task"); + queue_.cancel(unloadTaskHandle_); + unloadTaskHandle_ = nullptr; +} + +void CloudDiskServiceTaskManager::DelayUnloadTask(bool needSetCritical) +{ + LOGI("delay unload task begin"); + auto delayTime = DELAY_TIME; + + if (needSetCritical == true && criticalStatus_ == true) { + int32_t ret = Memory::MemMgrClient::GetInstance().SetCritical(getpid(), + false, FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID); + if (ret == ERR_OK) { + criticalStatus_ = false; + } + } + auto task = [this]() { + LOGI("do unload task"); + { + std::lock_guard lock(unloadTaskMutex_); + unloadTaskHandle_ = nullptr; + } + + auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgrProxy == nullptr) { + LOGE("get samgr failed"); + return; + } + // system::SetParameter(CLOUD_FILE_SERVICE_SA_STATUS_FLAG, CLOUD_FILE_SERVICE_SA_END); + int32_t ret = samgrProxy->UnloadSystemAbility(FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID); + if (ret != ERR_OK) { + LOGE("remove system ability failed"); + return; + } + }; + + CancelUnloadTask(); + std::lock_guard lock(unloadTaskMutex_); + std::chrono::milliseconds ms(delayTime); + auto us = std::chrono::duration_cast(ms); + unloadTaskHandle_ = queue_.submit_h(task, ffrt::task_attr().delay(us.count())); +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/clouddiskservice_kit_inner/src/service_proxy.cpp b/frameworks/native/clouddiskservice_kit_inner/src/service_proxy.cpp new file mode 100644 index 000000000..ec8cdf454 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/service_proxy.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 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 "service_proxy.h" + +#include + +#include "cloud_disk_service_proxy.h" +#include "dfs_error.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +constexpr int LOAD_SA_TIMEOUT_MS = 2000; + +sptr ServiceProxy::GetInstance() +{ + LOGD("getinstance"); + unique_lock lock(instanceMutex_); + if (serviceProxy_ != nullptr) { + if (serviceProxy_->AsObject() != nullptr && !serviceProxy_->AsObject()->IsObjectDead()) { + return serviceProxy_; + } + } + + auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgr == nullptr) { + LOGE("Samgr is nullptr"); + return nullptr; + } + + sptr cloudDiskServiceLoadCallback = new CloudDiskServiceProxyLoadCallback(); + if (cloudDiskServiceLoadCallback == nullptr) { + LOGE("cloudDiskServiceLoadCallback is nullptr"); + return nullptr; + } + + int32_t ret = samgr->LoadSystemAbility(FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID, cloudDiskServiceLoadCallback); + if (ret != E_OK) { + LOGE("Failed to Load systemAbility, systemAbilityId:%{public}d, ret code:%{public}d", + FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID, ret); + return nullptr; + } + + unique_lock proxyLock(proxyMutex_); + auto waitStatus = cloudDiskServiceLoadCallback->proxyConVar_.wait_for( + proxyLock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS), + [cloudDiskServiceLoadCallback]() { return cloudDiskServiceLoadCallback->isLoadSuccess_.load(); }); + if (!waitStatus) { + LOGE("Load CloudDiskService SA timeout"); + return nullptr; + } + return serviceProxy_; +} + +void ServiceProxy::InvaildInstance() +{ + LOGI("invalid instance"); + unique_lock lock(instanceMutex_); + serviceProxy_ = nullptr; +} + +void ServiceProxy::CloudDiskServiceProxyLoadCallback::OnLoadSystemAbilitySuccess( + int32_t systemAbilityId, + const sptr &remoteObject) +{ + LOGI("Load CloudSync SA success,systemAbilityId:%{public}d, remoteObj result:%{private}s", systemAbilityId, + (remoteObject == nullptr ? "false" : "true")); + unique_lock lock(proxyMutex_); + if (serviceProxy_ != nullptr) { + LOGE("CloudDiskService SA proxy has been loaded"); + } else { + serviceProxy_ = iface_cast(remoteObject); + } + isLoadSuccess_.store(true); + proxyConVar_.notify_one(); +} + +void ServiceProxy::CloudDiskServiceProxyLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId) +{ + LOGI("Load CloudDiskService SA failed,systemAbilityId:%{public}d", systemAbilityId); + unique_lock lock(proxyMutex_); + serviceProxy_ = nullptr; + isLoadSuccess_.store(false); + proxyConVar_.notify_one(); +} +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/interfaces/inner_api/native/clouddiskservice_kit_inner/BUILD.gn b/interfaces/inner_api/native/clouddiskservice_kit_inner/BUILD.gn new file mode 100644 index 000000000..083c2101d --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/BUILD.gn @@ -0,0 +1,99 @@ +# Copyright (C) 2025 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. + +import("//build/ohos.gni") +import("//foundation/filemanagement/dfs_service/distributedfile.gni") + +config("public_config") { + include_dirs = [ + ".", + "${distributedfile_path}/interfaces/inner_api/native/clouddiskservice_kit_inner", + ] +} + +config("private_config") { + include_dirs = [ + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/include", + "${distributedfile_path}/interfaces/inner_api/native/clouddiskservice_kit_inner", + "${distributedfile_path}/utils/log/include", + ] +} + +config("optimize-size") { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-fvisibility-inlines-hidden", + "-Oz", + ] +} + +ohos_shared_library("clouddiskservice_kit_inner") { + branch_protector_ret = "pac_ret" + configs = [ ":optimize-size" ] + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_stub.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager_impl.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_task_manager.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/service_proxy.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", + ] + + defines = [ + "LOG_DOMAIN=0xD004309", + "LOG_TAG=\"CLOUDDISKSERVICE_API\"", + ] + + configs += [ ":private_config" ] + public_configs = [ + ":public_config", + "${services_path}/clouddiskservice:cloud_disk_service_public_config", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "ffrt:libffrt", + "hilog:libhilog", + "ipc:ipc_single", + "memmgr:memmgrclient", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + deps = [ + "${services_path}/clouddiskservice:libcloud_disk_service_proxy", + "${utils_path}:libdistributedfiledentry", + "${utils_path}:libdistributedfileutils", + ] + + use_exceptions = true + part_name = "dfs_service" + subsystem_name = "filemanagement" +} + diff --git a/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_common.h b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_common.h new file mode 100644 index 000000000..230942dcc --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_common.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_COMMON_H +#define OHOS_FILEMGMT_CLOUD_DISK_COMMON_H + +#include +#include + +#include "parcel.h" + +namespace OHOS::FileManagement::CloudDiskService { +struct FileAttributes { + uint16_t mode{0}; + uint16_t nameLen{0}; + uint64_t size{0}; + uint64_t mtime{0}; + uint64_t atime{0}; +}; + +struct ChangeData : public Parcelable { + uint8_t recordId[33]{0}; + uint32_t operationType{0}; + std::string relativePath; + std::string syncRootIndex; + uint64_t timestamp; + struct FileAttributes fileAttributes; + + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static ChangeData *Unmarshalling(Parcel &parcel); +}; + +} // namespace OHOS::FileManagement::CloudDiskService +#endif // OHOS_FILEMGMT_CLOUD_DISK_COMMON_H diff --git a/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_callback.h b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_callback.h new file mode 100644 index 000000000..84c107d35 --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_callback.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_H + +#include "cloud_disk_common.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceCallback { +public: + virtual ~CloudDiskServiceCallback() = default; + virtual int32_t OnChangeData(ChangeData &changeData) = 0; + virtual void OnDeathRecipient() {}; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_H \ No newline at end of file diff --git a/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_manager.h b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_manager.h new file mode 100644 index 000000000..52c22162d --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_manager.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_H + +#include + +#include "cloud_disk_common.h" +#include "cloud_disk_service_callback.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceManager { +public: + static CloudDiskServiceManager &GetInstance(); + + virtual int32_t RegisterSyncRootChanges(const std::string &syncRootUri, + const std::shared_ptr changeCallback, std::string &syncRootIndex) = 0; + virtual int32_t UnregisterSyncRootChanges(const std::string &syncRootUri, bool &isOk) = 0; + virtual int32_t GetSyncRootChanges(const std::string &syncRootUri, int32_t maxSize, + std::vector &syncRootRecords) = 0; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_H diff --git a/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_task_manager.h b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_task_manager.h new file mode 100644 index 000000000..b65c3e841 --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_task_manager.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_SERVICE_TASK_MANAGER_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_TASK_MANAGER_H + +#include +#include +#include "ffrt_inner.h" + +namespace OHOS::FileManagement::CloudDiskService { +// static const std::string CLOUD_FILE_SERVICE_SA_STATUS_FLAG = "persist.kernel.medialibrarydata.stopflag"; +// static const std::string CLOUD_FILE_SERVICE_SA_START = "0"; +// static const std::string CLOUD_FILE_SERVICE_SA_END = "1"; +enum class TaskType : uint64_t { + REGISTER_TASK = 1, + UNREGISTER_TASK = 1 << 1, + GET_TASK = 1 << 2, +}; + +struct TaskKey { + std::string bundleName; + std::string syncChronousRootPath; + + bool operator ==(const TaskKey& other) const { + return bundleName == other.bundleName && + syncChronousRootPath == other.syncChronousRootPath; + } + + struct Hash { + size_t operator()(const TaskKey& key) const { + auto hasher = std::hash(); + return hasher(key.bundleName) ^ (hasher(key.syncChronousRootPath) << 1); + } + }; +}; + +class CloudDiskServiceTaskManager : public NoCopyable { +public: + static CloudDiskServiceTaskManager &GetInstance(); + ~CloudDiskServiceTaskManager() = default; + void StartTask(TaskKey key, TaskType task); + void CompleteTask(TaskKey key, TaskType task); + bool HasTask(TaskKey key, TaskType task); + void StartTask(); +private: + CloudDiskServiceTaskManager(); + void DelayUnloadTask(bool needSetCritical); + void CancelUnloadTask(); + + bool criticalStatus_ = true; + std::mutex taskMapsMutex_; + std::unordered_map taskMaps_; + ffrt::queue queue_; + ffrt::task_handle unloadTaskHandle_; + ffrt::mutex unloadTaskMutex_; +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_TASK_MANAGER_H \ No newline at end of file diff --git a/interfaces/inner_api/native/clouddiskservice_kit_inner/i_cloud_disk_service_callback.h b/interfaces/inner_api/native/clouddiskservice_kit_inner/i_cloud_disk_service_callback.h new file mode 100644 index 000000000..ef88b6e60 --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/i_cloud_disk_service_callback.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_I_CLOUD_DISK_SERVICE_CALLBACK_H +#define OHOS_FILEMGMT_I_CLOUD_DISK_SERVICE_CALLBACK_H + +#include "iremote_broker.h" +#include "cloud_disk_service_callback.h" + +namespace OHOS::FileManagement::CloudDiskService { +class ICloudDiskServiceCallback : public CloudDiskServiceCallback, public IRemoteBroker { +public: + enum { + SERVICE_CMD_ON_PROCESS = 0, + }; + + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Filemanagement.Dfs.ICloudDiskServiceCallback") +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_I_CLOUD_DISK_SERVICE_CALLBACK_H \ No newline at end of file diff --git a/interfaces/inner_api/native/clouddiskservice_kit_inner/svc_death_recipient.h b/interfaces/inner_api/native/clouddiskservice_kit_inner/svc_death_recipient.h new file mode 100644 index 000000000..bd5b79a3f --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/svc_death_recipient.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_SVC_DEATH_RECIPIENT_H +#define OHOS_FILEMGMT_SVC_DEATH_RECIPIENT_H + +#include + +#include "iremote_object.h" + +namespace OHOS::FileManagement::CloudDiskService { +class SvcDeathRecipient : public IRemoteObject::DeathRecipient { +public: + explicit SvcDeathRecipient(std::function &)> functor) : functor_(functor){}; + void OnRemoteDied(const wptr &object) override + { + if (object == nullptr) { + return; + } + object->RemoveDeathRecipient(this); + functor_(object); + } + +private: + std::function &)> functor_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_SVC_DEATH_RECIPIENT_H \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/BUILD.gn b/interfaces/kits/js/clouddiskmanager/BUILD.gn new file mode 100644 index 000000000..a48144eb1 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2025 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. + +import("//build/ohos.gni") +import("//foundation/filemanagement/dfs_service/distributedfile.gni") + +config("optimize-size") { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-fvisibility-inlines-hidden", + "-Oz", + ] +} + +ohos_shared_library("clouddiskmanager") { + branch_protector_ret = "pac_ret" + configs = [ ":optimize-size" ] + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "cloud_disk_manager_napi_utils.cpp", + "cloud_disk_manager_napi.cpp", + "sync_folder_handler_callback_napi.cpp", + "sync_folder_handler_napi.cpp", + ] + deps = [ + "${innerkits_native_path}/clouddiskservice_kit_inner:clouddiskservice_kit_inner", + "${utils_path}:libdistributedfileutils", + ] + + external_deps = [ + "c_utils:utils", + "file_api:filemgmt_libhilog", + "file_api:filemgmt_libn", + "hilog:libhilog", + "napi:ace_napi", + ] + + defines = [ + "LOG_DOMAIN=0xD004309", + "LOG_TAG=\"CLOUD_FILE_SYNC\"", + ] + + relative_install_dir = "module/file" + + part_name = "dfs_service" + subsystem_name = "filemanagement" +} diff --git a/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.cpp b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.cpp new file mode 100644 index 000000000..d0aa2a564 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_manager_napi.h" + +#include "sync_folder_handler_napi.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace FileManagement::LibN; +/*********************************************** + * Module export and register + ***********************************************/ +static napi_value Init(napi_env env, napi_value exports) +{ + LOGI("CloudDiskManager napi init"); + std::vector> products; + products.emplace_back(std::make_unique(env, exports)); + for (auto &&product : products) { + if (!product->Export()) { + LOGE("INNER BUG. Failed to export class %{public}s for module cloudDiskManager", + product->GetClassName().c_str()); + return nullptr; + } else { + LOGI("Class %{public}s for module cloudDiskManager has been exported", product->GetClassName().c_str()); + } + } + + return exports; +} + +static napi_module _module = {.nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "file.cloudDiskManager", + .nm_priv = ((void *)0), + .reserved = {0}}; + +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace OHOS::FileManagement::CloudSync diff --git a/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.h b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.h new file mode 100644 index 000000000..1fc7b9ace --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_MANAGER_NAPI_H +#define OHOS_FILEMGMT_CLOUD_DISK_MANAGER_NAPI_H + +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::CloudDiskService { +//void CloudDiskGlobalFuncExport(napi_env env, napi_value exports); +} // namespace OHOS::FileManagement::CloudDiskService +#endif // OHOS_FILEMGMT_CLOUD_DISK_MANAGER_NAPI_H \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.cpp b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.cpp new file mode 100644 index 000000000..6f9fdac58 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_manager_napi_utils.h" + +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace FileManagement::LibN; +using namespace std; + +NVal ChangeDataToNapi(napi_env env, const ChangeData &record) +{ + NVal obj = NVal::CreateObject(env); + obj.AddProp("updateSequenceNumber", NVal::CreateBigIntUint64(env, record.updateSequenceNumber).val_); + obj.AddProp("fileId", NVal::CreateUTF8String(env, record.fileId).val_); + obj.AddProp("parentFileId", NVal::CreateUTF8String(env, record.parentFileId).val_); + //obj.AddProp("syncFolderIndex", NVal::CreateUTF8String(env, record.syncFolderIndex).val_); + obj.AddProp("relativePath", NVal::CreateUTF8String(env, record.relativePath).val_); + obj.AddProp("operationType", NVal::CreateInt32(env, static_cast(record.operationType)).val_); + obj.AddProp("size", NVal::CreateBigIntUint64(env, record.size).val_); + obj.AddProp("mtime", NVal::CreateBigIntUint64(env, record.mtime).val_); + obj.AddProp("timeStamp", NVal::CreateBigIntUint64(env, record.timeStamp).val_); + return obj; +} + +NVal ChangeDataVectorToNapi(napi_env env, const std::vector &syncRootRecords) +{ + napi_value results = nullptr; + + napi_status status = napi_create_array(env, &results); + if (status != napi_ok) { + LOGE("Failed to create array"); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + + int32_t index = 0; + for (const ChangeData &record : syncRootRecords) { + status = napi_set_element(env, results, index, ChangeDataToNapi(env, record).val_); + if (status != napi_ok) { + LOGE("Failed to set element on data, index: %{public}d", index); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + index++; + } + return {env, results}; +} + +LibN::NVal ChangesResultToNapi(napi_env env, const ChangesResult &changesResult) +{ + NVal obj = NVal::CreateObject(env); + obj.AddProp("nextUsn", NVal::CreateBigIntUint64(env, changesResult.nextUsn).val_); + obj.AddProp("isEof", NVal::CreateBool(env, changesResult.isEof).val_); + obj.AddProp("changesData", ChangeDataVectorToNapi(env, changesResult.changesData).val_); + return obj; +} + +LibN::NVal FileSyncStateToNapi(napi_env env, const FileSyncState &fileSyncStates) +{ + NVal obj = NVal::CreateObject(env); + obj.AddProp("path", NVal::CreateUTF8String(env, fileSyncStates.path).val_); + obj.AddProp("state", NVal::CreateInt32(env, static_cast(fileSyncStates.state)).val_); + return obj; +} + +LibN::NVal FileSyncStateVectorToNapi(napi_env env, const std::vector &fileSyncStates) +{ + napi_value results = nullptr; + + napi_status status = napi_create_array(env, &results); + if (status != napi_ok) { + LOGE("Failed to create array"); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + + int32_t index = 0; + for (const FileSyncState &fileSyncState : fileSyncStates) { + status = napi_set_element(env, results, index, FileSyncStateToNapi(env, fileSyncState).val_); + if (status != napi_ok) { + LOGE("Failed to set element on data, index: %{public}d", index); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + index++; + } + return {env, results}; +} + +LibN::NVal StringVectorToNapi(napi_env env, const std::vector &strs) +{ + napi_value results = nullptr; + + napi_status status = napi_create_array(env, &results); + if (status != napi_ok) { + LOGE("Failed to create array"); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + + int32_t index = 0; + for (const std::string &s : strs) { + status = napi_set_element(env, results, index, NVal::CreateUTF8String(env, s).val_); + if (status != napi_ok) { + LOGE("Failed to set element on data, index: %{public}d", index); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + index++; + } + return {env, results}; +} + +LibN::NVal FailedListToNapi(napi_env env, const FailedList &failed) +{ + NVal obj = NVal::CreateObject(env); + obj.AddProp("path", NVal::CreateUTF8String(env, failed.path).val_); + obj.AddProp("error", NVal::CreateInt32(env, static_cast(failed.error)).val_); + return obj; +} + +LibN::NVal FailedListVectorToNapi(napi_env env, const std::vector &failedList) +{ + napi_value results = nullptr; + + napi_status status = napi_create_array(env, &results); + if (status != napi_ok) { + LOGE("Failed to create array"); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + + int32_t index = 0; + for (const FailedList &failed : failedList) { + status = napi_set_element(env, results, index, FailedListToNapi(env, failed).val_); + if (status != napi_ok) { + LOGE("Failed to set element on data, index: %{public}d", index); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + index++; + } + return {env, results}; +} + +LibN::NVal ResultListToNapi(napi_env env, const ResultList &result) +{ + NVal obj = NVal::CreateObject(env); + obj.AddProp("path", NVal::CreateUTF8String(env, result.path).val_); + obj.AddProp("error", NVal::CreateInt32(env, static_cast(result.error)).val_); + obj.AddProp("isSuccess", NVal::CreateBool(env, result.isSuccess).val_); + obj.AddProp("state", NVal::CreateInt32(env, static_cast(result.state)).val_); + return obj; +} + +LibN::NVal ResultListVectorToNapi(napi_env env, const std::vector &resultList) +{ + napi_value results = nullptr; + + napi_status status = napi_create_array(env, &results); + if (status != napi_ok) { + LOGE("Failed to create array"); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + + int32_t index = 0; + for (const ResultList &ret : resultList) { + status = napi_set_element(env, results, index, ResultListToNapi(env, ret).val_); + if (status != napi_ok) { + LOGE("Failed to set element on data, index: %{public}d", index); + return {env, NError(LibN::STORAGE_SERVICE_SYS_CAP_TAG + LibN::E_IPCSS).GetNapiErr(env)}; + } + index++; + } + return {env, results}; +} + + +bool ParseFileSyncState(LibN::NVal fileSyncStateVal, FileSyncState &fileSyncState) +{ + if (!fileSyncStateVal.TypeIs(napi_object) || !fileSyncStateVal.HasProp("path") || + !fileSyncStateVal.HasProp("state")) { + LOGE("fileSyncStateVal not FileSyncState"); + return false; + } + + bool succ = false; + std::unique_ptr pathVal; + tie(succ, pathVal, std::ignore) = fileSyncStateVal.GetProp("path").ToUTF8String(); + if (!succ) { + LOGE("parse path failed"); + return false; + } + + int32_t state = 0; + tie(succ, state) = fileSyncStateVal.GetProp("state").ToInt32(); + if (!succ) { + LOGE("parse state failed"); + return false; + } + + fileSyncState.path = std::string(pathVal.get()); + fileSyncState.state = static_cast(state); + return true; +} + +bool ParseFileSyncStateArray(LibN::NVal fileSyncStatesVal, std::vector &fileSyncStates) +{ + if (!fileSyncStatesVal.TypeIs(napi_object)) { + LOGE("fileSyncStatesVal not array"); + return false; + } + + uint32_t size = 0; + napi_get_array_length(fileSyncStatesVal.env_, fileSyncStatesVal.val_, &size); + napi_value element; + FileSyncState fileSyncState; + for (uint32_t i = 0; i < size; ++i) { + napi_get_element(fileSyncStatesVal.env_, fileSyncStatesVal.val_, i, &element); + NVal fileSyncStateVal = NVal(fileSyncStatesVal.env_, element); + if (!ParseFileSyncState(fileSyncStateVal, fileSyncState)) { + LOGE("ParseFileSyncState %{public}d failed", (int32_t)i); + return false; + } + fileSyncStates.emplace_back(fileSyncState); + } + + return true; +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.h b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.h new file mode 100644 index 000000000..7f4bf554e --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/cloud_disk_manager_napi_utils.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_MANAGER_NAPI_UTILS_H +#define OHOS_FILEMGMT_CLOUD_DISK_MANAGER_NAPI_UTILS_H + +#include + +#include "cloud_disk_common.h" +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::CloudDiskService { +// LibN::NVal FileAttributesToNapi(napi_env env, const FileAttributes &fileAttributes); +LibN::NVal ChangeDataToNapi(napi_env env, const ChangeData &record); +LibN::NVal ChangeDataVectorToNapi(napi_env env, const std::vector &syncRootRecords); +LibN::NVal ChangesResultToNapi(napi_env env, const ChangesResult &changesResult); +LibN::NVal FileSyncStateToNapi(napi_env env, const FileSyncState &fileSyncStates); +LibN::NVal FileSyncStateVectorToNapi(napi_env env, const std::vector &fileSyncStates); +LibN::NVal StringVectorToNapi(napi_env env, const std::vector &strs); +LibN::NVal FailedListToNapi(napi_env env, const FailedList &failed); +LibN::NVal FailedListVectorToNapi(napi_env env, const std::vector &failedList); +LibN::NVal ResultListToNapi(napi_env env, const ResultList &result); +LibN::NVal ResultListVectorToNapi(napi_env env, const std::vector &resultList); + +bool ParseFileSyncStateArray(LibN::NVal fileSyncStatesVal, std::vector &fileSyncStates); +bool ParseFileSyncState(LibN::NVal fileSyncStateVal, FileSyncState &fileSyncState); +} // namespace OHOS::FileManagement::CloudDiskService +#endif // OHOS_FILEMGMT_CLOUD_DISK_MANAGER_NAPI_UTILS_H \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.cpp b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.cpp new file mode 100644 index 000000000..0efb45d07 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2025 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 "sync_folder_handler_callback_napi.h" + +#include "cloud_disk_manager_napi_utils.h" +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +SyncFolderHandlerCallbackImpl::SyncFolderHandlerCallbackImpl(napi_env env, napi_value func): env_(env) +{ + napi_status status = napi_create_reference(env_, func, 1, &cbOnRef_); + if (status != napi_ok) { + LOGE("Failed to create napi ref, %{public}d", status); + } +} + +SyncFolderHandlerCallbackImpl::~SyncFolderHandlerCallbackImpl() +{ + if (cbOnRef_ != nullptr) { + napi_status status = napi_delete_reference(env_, cbOnRef_); + if (status != napi_ok) { + LOGE("Failed to delete napi ref, %{public}d", status); + } + cbOnRef_ = nullptr; + } +} + +void SyncFolderHandlerCallbackImpl::OnChangeData(std::vector &changeData) +{ + std::shared_ptr callbackImpl = shared_from_this(); + napi_status status = napi_send_event( + callbackImpl->env_, + [callbackImpl, changeData]() mutable { + auto env = callbackImpl->env_; + auto ref = callbackImpl->cbOnRef_; + if (env == nullptr || ref == nullptr) { + LOGE("The env context is invalid"); + return; + } + napi_handle_scope scope = nullptr; + napi_status status = napi_open_handle_scope(env, &scope); + if (status != napi_ok) { + LOGE("Failed to open handle scope, status: %{public}d", status); + return; + } + napi_value jsCallback = nullptr; + status = napi_get_reference_value(env, ref, &jsCallback); + if (status != napi_ok) { + LOGE("Create reference failed, status: %{public}d", status); + napi_close_handle_scope(env, scope); + return; + } + napi_value jsProgress = ChangeDataVectorToNapi(env, changeData).val_; + if (jsProgress == nullptr) { + napi_close_handle_scope(env, scope); + return; + } + napi_value jsResult = nullptr; + status = napi_call_function(env, nullptr, jsCallback, 1, &jsProgress, &jsResult); + if (status != napi_ok) { + LOGE("napi call function failed, status: %{public}d", status); + return; + } + napi_close_handle_scope(env, scope); + }, + napi_eprio_immediate); + if (status != napi_ok) { + LOGE("Failed to execute libuv work queue, status: %{public}d", status); + } +} + +void SyncFolderHandlerCallbackImpl::OnReturnSetFailedList(std::vector &failedList) +{ + std::shared_ptr callbackImpl = shared_from_this(); + napi_status status = napi_send_event( + callbackImpl->env_, + [callbackImpl, failedList]() mutable { + auto env = callbackImpl->env_; + auto ref = callbackImpl->cbOnRef_; + if (env == nullptr || ref == nullptr) { + LOGE("The env context is invalid"); + return; + } + napi_handle_scope scope = nullptr; + napi_status status = napi_open_handle_scope(env, &scope); + if (status != napi_ok) { + LOGE("Failed to open handle scope, status: %{public}d", status); + return; + } + napi_value jsCallback = nullptr; + status = napi_get_reference_value(env, ref, &jsCallback); + if (status != napi_ok) { + LOGE("Create reference failed, status: %{public}d", status); + napi_close_handle_scope(env, scope); + return; + } + napi_value jsProgress = FailedListVectorToNapi(env, failedList).val_; + if (jsProgress == nullptr) { + napi_close_handle_scope(env, scope); + return; + } + napi_value jsResult = nullptr; + status = napi_call_function(env, nullptr, jsCallback, 1, &jsProgress, &jsResult); + if (status != napi_ok) { + LOGE("napi call function failed, status: %{public}d", status); + return; + } + napi_close_handle_scope(env, scope); + }, + napi_eprio_immediate); + if (status != napi_ok) { + LOGE("Failed to execute libuv work queue, status: %{public}d", status); + } +} + +void SyncFolderHandlerCallbackImpl::OnReturnGetResult(std::vector &resultList) +{ + std::shared_ptr callbackImpl = shared_from_this(); + napi_status status = napi_send_event( + callbackImpl->env_, + [callbackImpl, resultList]() mutable { + auto env = callbackImpl->env_; + auto ref = callbackImpl->cbOnRef_; + if (env == nullptr || ref == nullptr) { + LOGE("The env context is invalid"); + return; + } + napi_handle_scope scope = nullptr; + napi_status status = napi_open_handle_scope(env, &scope); + if (status != napi_ok) { + LOGE("Failed to open handle scope, status: %{public}d", status); + return; + } + napi_value jsCallback = nullptr; + status = napi_get_reference_value(env, ref, &jsCallback); + if (status != napi_ok) { + LOGE("Create reference failed, status: %{public}d", status); + napi_close_handle_scope(env, scope); + return; + } + napi_value jsProgress = ResultListVectorToNapi(env, resultList).val_; + if (jsProgress == nullptr) { + napi_close_handle_scope(env, scope); + return; + } + napi_value jsResult = nullptr; + status = napi_call_function(env, nullptr, jsCallback, 1, &jsProgress, &jsResult); + if (status != napi_ok) { + LOGE("napi call function failed, status: %{public}d", status); + return; + } + napi_close_handle_scope(env, scope); + }, + napi_eprio_immediate); + if (status != napi_ok) { + LOGE("Failed to execute libuv work queue, status: %{public}d", status); + } +} + +void SyncFolderHandlerCallbackImpl::OnDeathRecipient() +{ + +} + +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.h b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.h new file mode 100644 index 000000000..181fa6a73 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_callback_napi.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_SYNC_FOLDER_HANDLER_CALLBACK_NAPI_H +#define OHOS_FILEMGMT_SYNC_FOLDER_HANDLER_CALLBACK_NAPI_H + +#include +#include + +#include "cloud_disk_service_callback.h" +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::CloudDiskService { + +class SyncFolderHandlerCallbackImpl : public CloudDiskServiceCallback, + public std::enable_shared_from_this { +public: + SyncFolderHandlerCallbackImpl(napi_env env, napi_value func); + ~SyncFolderHandlerCallbackImpl(); + void OnChangeData(std::vector &changeData) override; + void OnReturnSetFailedList(std::vector &failedList) override; + void OnReturnGetResult(std::vector &resultList) override; + void OnDeathRecipient() override; + +public: + napi_ref cbOnRef_; + napi_env env_; +}; + +struct SyncFolderHandlerEntity { + explicit SyncFolderHandlerEntity(const std::string &folder) : syncFolder(folder) {}; + std::string syncFolder; + // std::shared_ptr callbackImpl = nullptr; +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif // OHOS_FILEMGMT_SYNC_FOLDER_HANDLER_CALLBACK_NAPI_H \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.cpp b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.cpp new file mode 100644 index 000000000..2e1b6ead9 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.cpp @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2025 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 "sync_folder_handler_napi.h" + +#include "async_work.h" +#include "sync_folder_handler_callback_napi.h" +#include "cloud_disk_manager_napi_utils.h" +#include "cloud_disk_service_manager.h" +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace FileManagement::LibN; +using namespace std; + +struct CloudDiskServiceParam { + // std::string syncRootIndex; + ChangesResult changesResult; + // std::vector failedList; + // std::vector fileSyncStates; +}; + +std::string SyncFolderHandlerNapi::GetClassName() +{ + return className_; +} + +bool SyncFolderHandlerNapi::Export() +{ + std::vector props = { + NVal::DeclareNapiFunction("registerSyncFolderChanges", SyncFolderHandlerNapi::RegisterSyncFolderChanges), + NVal::DeclareNapiFunction("unregisterSyncFolderChanges", SyncFolderHandlerNapi::UnregisterSyncFolderChanges), + NVal::DeclareNapiFunction("getSyncFolderChanges", SyncFolderHandlerNapi::GetSyncFolderChanges), + NVal::DeclareNapiFunction("getFileSyncStates", SyncFolderHandlerNapi::GetFileSyncStates), + NVal::DeclareNapiFunction("setFileSyncStates", SyncFolderHandlerNapi::SetFileSyncStates), + }; + + return ToExport(props); +} + +bool SyncFolderHandlerNapi::ToExport(std::vector props) +{ + std::string className = GetClassName(); + auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props)); + if (!succ) { + NError(Convert2JsErrNum(E_SERVICE_INNER_ERROR)).ThrowErr(exports_.env_); + LOGE("Failed to define SyncRootManager class"); + return false; + } + + succ = NClass::SaveClass(exports_.env_, className, classValue); + if (!succ) { + NError(Convert2JsErrNum(E_SERVICE_INNER_ERROR)).ThrowErr(exports_.env_); + LOGE("Failed to save SyncRootManager class"); + return false; + } + + return exports_.AddProp(className, classValue); +} + +napi_value SyncFolderHandlerNapi::Constructor(napi_env env, napi_callback_info info) +{ + LOGI("mjh: napi SyncRootManager Constructor start"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + LOGE("Start Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + bool succ = false; + std::unique_ptr syncFolderVal; + tie(succ, syncFolderVal, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + LOGE("get param syncFolder failed"); + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + std::string syncFolder(syncFolderVal.get()); + LOGI("mjh: napi SyncRootManager Constructor syncFolder: %{public}s", syncFolder.c_str()); + auto syncRootFolderEntity = make_unique(syncFolder); + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), move(syncRootFolderEntity))) { + LOGE("Failed to set syncRootFolderEntity"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + LOGI("mjh: napi SyncRootManager Constructor end"); + return funcArg.GetThisVar(); +} + +napi_value SyncFolderHandlerNapi::RegisterSyncFolderChanges(napi_env env, napi_callback_info info) +{ + LOGI("mjh: napi RegisterSyncFolderChanges start"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(static_cast(NARG_CNT::ONE))) { + NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + NVal callbackVal = NVal(env, funcArg[NARG_POS::FIRST]); + if (!callbackVal.TypeIs(napi_function)) { + LOGE("callback not function"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + auto syncFolderHandlerEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolderHandlerEntity) { + LOGE("failed to get syncFolderHandlerEntity"); + NError(Convert2JsErrNum(E_SERVICE_INNER_ERROR)).ThrowErr(env); + return nullptr; + } + std::string syncFolder = syncFolderHandlerEntity->syncFolder; + //syncFolderHandlerEntity->callbackImpl = std::make_shared(env, callbackVal.val_); + std::shared_ptr callbackImpl = + std::make_shared(env, callbackVal.val_); + + LOGI("mjh: napi RegisterSyncFolderChanges uri: %{public}s", syncFolder.c_str()); + auto cbExec = [syncFolder, callbackImpl]() -> NError { + int32_t ret = CloudDiskServiceManager::GetInstance().RegisterSyncFolderChanges(syncFolder, callbackImpl); + //int32_t ret = E_OK; + LOGI("mjh: napi RegisterSyncFolderChanges end, ret: %{public}d", ret); + if (ret != E_OK) { + return NError(Convert2JsErrNum(ret)); + } else { + return NError(ERRNO_NOERR); + } + }; + auto cbComplete = [](napi_env env, NError err) -> NVal { + LOGI("mjh: napi RegisterSyncFolderChanges complete"); + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return { NVal::CreateUndefined(env) }; + } + }; + + std::string procedureName = "RegisterSyncFolderChanges"; + auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast(NARG_CNT::TWO)); + return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbComplete).val_; +} + +napi_value SyncFolderHandlerNapi::UnregisterSyncFolderChanges(napi_env env, napi_callback_info info) +{ + LOGI("mjh: napi UnregisterSyncFolderChanges start"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(static_cast(NARG_CNT::ZERO))) { + NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + auto syncFolderHandlerEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolderHandlerEntity) { + LOGE("failed to get syncFolderHandlerEntity"); + NError(Convert2JsErrNum(E_SERVICE_INNER_ERROR)).ThrowErr(env); + return nullptr; + } + std::string syncFolder = syncFolderHandlerEntity->syncFolder; + + LOGI("mjh: napi UnregisterSyncFolderChanges syncFolder: %{public}s", syncFolder.c_str()); + auto cbExec = [syncFolder]() -> NError { + int32_t ret = CloudDiskServiceManager::GetInstance().UnregisterSyncFolderChanges(syncFolder); + //int32_t ret = E_OK; + LOGI("mjh: napi UnregisterSyncFolderChanges end, ret: %{public}d", ret); + if (ret != E_OK) { + return NError(Convert2JsErrNum(ret)); + } else { + return NError(ERRNO_NOERR); + } + }; + auto cbComplete = [](napi_env env, NError err) -> NVal { + LOGI("mjh: napi UnregisterSyncFolderChanges complete"); + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return { NVal::CreateUndefined(env) }; + } + }; + + std::string procedureName = "UnregisterSyncFolderChanges"; + auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast(NARG_CNT::ONE)); + return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbComplete).val_; +} + +napi_value SyncFolderHandlerNapi::GetSyncFolderChanges(napi_env env, napi_callback_info info) +{ + LOGI("mjh: napi GetSyncFolderChanges start"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(static_cast(NARG_CNT::TWO))) { + NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + bool succ = false; + bool lossless = false; + uint64_t count = 0; + tie(succ, count, lossless) = NVal(env, funcArg[NARG_POS::FIRST]).ToUint64(); + if (!succ || !lossless) { + LOGE("get param count failed, succ: %{public}d, lossless: %{public}d", succ, lossless); + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + uint64_t startUsn = 0; + tie(succ, startUsn, lossless) = NVal(env, funcArg[NARG_POS::SECOND]).ToUint64(); + if (!succ || !lossless) { + LOGE("get param startUSN failed, succ: %{public}d, lossless: %{public}d", succ, lossless); + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + auto syncFolderHandlerEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolderHandlerEntity) { + LOGE("failed to get syncFolderHandlerEntity"); + NError(Convert2JsErrNum(E_SERVICE_INNER_ERROR)).ThrowErr(env); + return nullptr; + } + std::string syncFolder = syncFolderHandlerEntity->syncFolder; + + std::shared_ptr param = std::make_shared(); + LOGI("mjh: napi GetSyncFolderChanges syncFolder: %{public}s, count: %{public}d, startUSN: %{public}d", + syncFolder.c_str(), (int32_t)count, (int32_t)startUsn); + auto cbExec = [syncFolder, count, startUsn, param]() -> NError { + int32_t ret = CloudDiskServiceManager::GetInstance().GetSyncFolderChanges(syncFolder, count, startUsn, + param->changesResult); + // param->changesResult.nextUsn = 100; + // param->changesResult.isEof = true; + // int32_t ret = E_OK; + LOGI("mjh: napi GetSyncFolderChanges end, ret: %{public}d", ret); + if (ret != E_OK) { + return NError(Convert2JsErrNum(ret)); + } else { + return NError(ERRNO_NOERR); + } + }; + auto cbComplete = [param](napi_env env, NError err) -> NVal { + LOGI("mjh: napi GetSyncFolderChanges complete, changesResult.nextUsn: %{public}d, isEof: %{public}d", + (int32_t)param->changesResult.nextUsn, param->changesResult.isEof); + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return ChangesResultToNapi(env, param->changesResult); + } + }; + + std::string procedureName = "GetSyncFolderChanges"; + auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast(NARG_CNT::THREE)); + return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbComplete).val_; +} + +napi_value SyncFolderHandlerNapi::GetFileSyncStates(napi_env env, napi_callback_info info) +{ + LOGI("mjh: napi GetFileSyncStates start"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(static_cast(NARG_CNT::TWO))) { + NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + NVal pathArrayVal(env, funcArg[NARG_POS::FIRST]); + if (!pathArrayVal.TypeIs(napi_object)) { + LOGE("Invalid uris argments not is napi_object"); + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + bool succ = false; + std::vector pathArray; + tie(succ, pathArray, ignore) = pathArrayVal.ToStringArray(); + if (!succ) { + LOGE("Invalid pathArray argments"); + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + NVal callbackVal = NVal(env, funcArg[NARG_POS::SECOND]); + if (!callbackVal.TypeIs(napi_function)) { + LOGE("callback not function"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + auto syncFolderHandlerEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolderHandlerEntity) { + LOGE("failed to get syncFolderHandlerEntity"); + NError(Convert2JsErrNum(E_SERVICE_INNER_ERROR)).ThrowErr(env); + return nullptr; + } + std::string syncFolder = syncFolderHandlerEntity->syncFolder; + //syncFolderHandlerEntity->callbackImpl = std::make_shared(env, callbackVal.val_); + std::shared_ptr callbackImpl = + std::make_shared(env, callbackVal.val_); + + LOGI("mjh: napi GetFileSyncStates syncFolder: %{public}s, pathArray.size: %{public}d", + syncFolder.c_str(), (int32_t)pathArray.size()); + for (const auto &s : pathArray) { + LOGI("mjh: napi path: %{public}s", s.c_str()); + } + auto cbExec = [syncFolder, pathArray, callbackImpl]() -> NError { + int32_t ret = CloudDiskServiceManager::GetInstance().GetFileSyncStates(syncFolder, pathArray, callbackImpl); + // int32_t ret = E_OK; + LOGI("mjh: napi GetFileSyncStates end, ret: %{public}d", ret); + if (ret != E_OK) { + return NError(Convert2JsErrNum(ret)); + } else { + return NError(ERRNO_NOERR); + } + }; + auto cbComplete = [](napi_env env, NError err) -> NVal { + LOGI("mjh: napi GetFileSyncStates complete"); + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return { NVal::CreateUndefined(env) }; + } + }; + + std::string procedureName = "GetFileSyncStates"; + auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast(NARG_CNT::THREE)); + return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbComplete).val_; +} + +napi_value SyncFolderHandlerNapi::SetFileSyncStates(napi_env env, napi_callback_info info) +{ + LOGI("mjh: napi SetFileSyncStates start"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(static_cast(NARG_CNT::TWO))) { + NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + NVal fileSyncStatesVal = NVal(env, funcArg[NARG_POS::FIRST]); + std::vector fileSyncStates; + if (!ParseFileSyncStateArray(fileSyncStatesVal, fileSyncStates)) { + LOGE("get param fileSyncStates failed"); + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + NVal callbackVal = NVal(env, funcArg[NARG_POS::SECOND]); + if (!callbackVal.TypeIs(napi_function)) { + LOGE("callback not function"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + auto syncFolderHandlerEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolderHandlerEntity) { + LOGE("failed to get syncFolderHandlerEntity"); + NError(Convert2JsErrNum(E_SERVICE_INNER_ERROR)).ThrowErr(env); + return nullptr; + } + std::string syncFolder = syncFolderHandlerEntity->syncFolder; + //syncFolderHandlerEntity->callbackImpl = std::make_shared(env, callbackVal.val_); + std::shared_ptr callbackImpl = + std::make_shared(env, callbackVal.val_); + + LOGI("mjh: napi SetFileSyncStates syncFolder: %{public}s, fileSyncStates.size: %{public}d", + syncFolder.c_str(), (int32_t)fileSyncStates.size()); + for (const auto &state : fileSyncStates) { + LOGI("mjh: napi path: %{public}s, state: %{public}d", state.path.c_str(), (int32_t)state.state); + } + auto cbExec = [syncFolder, fileSyncStates, callbackImpl]() -> NError { + int32_t ret = CloudDiskServiceManager::GetInstance().SetFileSyncStates(syncFolder, fileSyncStates, + callbackImpl); + // int32_t ret = E_OK; + LOGI("mjh: napi SetFileSyncStates end, ret: %{public}d", ret); + if (ret != E_OK) { + return NError(Convert2JsErrNum(ret)); + } else { + return NError(ERRNO_NOERR); + } + }; + auto cbComplete = [](napi_env env, NError err) -> NVal { + LOGI("mjh: napi SetFileSyncStates complete"); + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return { NVal::CreateUndefined(env) }; + } + }; + + std::string procedureName = "SetFileSyncStates"; + auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast(NARG_CNT::THREE)); + return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbComplete).val_; +} + +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.h b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.h new file mode 100644 index 000000000..1ece409f8 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/sync_folder_handler_napi.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_SYNC_FOLDER_HANDLER_NAPI_H +#define OHOS_FILEMGMT_SYNC_FOLDER_HANDLER_NAPI_H + +#include +#include + +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::CloudDiskService { +class SyncFolderHandlerNapi final : public LibN::NExporter { +public: + SyncFolderHandlerNapi(napi_env env, napi_value exports) : NExporter(env, exports) {} + ~SyncFolderHandlerNapi() = default; + + bool Export() override; + bool ToExport(std::vector props); + std::string GetClassName() override; + static napi_value Constructor(napi_env env, napi_callback_info info); + static napi_value RegisterSyncFolderChanges(napi_env env, napi_callback_info info); + static napi_value UnregisterSyncFolderChanges(napi_env env, napi_callback_info info); + static napi_value GetSyncFolderChanges(napi_env env, napi_callback_info info); + static napi_value GetFileSyncStates(napi_env env, napi_callback_info info); + static napi_value SetFileSyncStates(napi_env env, napi_callback_info info); + +private: + inline static std::string className_ = "SyncFolderHandler"; +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif // OHOS_FILEMGMT_SYNC_FOLDER_HANDLER_NAPI_H \ No newline at end of file diff --git a/services/5207.json b/services/5207.json new file mode 100644 index 000000000..ecd254f9b --- /dev/null +++ b/services/5207.json @@ -0,0 +1,19 @@ +{ + "process": "clouddiskservice", + "systemability": [ + { + "name": 5207, + "libpath": "libclouddiskservice_sa.z.so", + "run-on-create": false, + "distributed": false, + "dump-level": 1, + "start-on-demand": { + "commonevent": [ + { + "name": "usual.event.SCREEN_OFF" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/services/BUILD.gn b/services/BUILD.gn index 0eec280de..f3b113a9c 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -25,6 +25,11 @@ ohos_sa_profile("distributedfile_sa_profile") { part_name = "dfs_service" } +ohos_sa_profile("clouddiskservice_sa_profile") { + sources = [ "5207.json" ] + part_name = "dfs_service" +} + ohos_prebuilt_etc("distributedfile_etc") { source = "distributedfile.cfg" relative_install_dir = "init" diff --git a/services/clouddiskservice/BUILD.gn b/services/clouddiskservice/BUILD.gn new file mode 100644 index 000000000..54635168a --- /dev/null +++ b/services/clouddiskservice/BUILD.gn @@ -0,0 +1,123 @@ +# Copyright (C) 2025 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. + +import("//build/config/components/idl_tool/idl.gni") +import("//build/ohos.gni") +import("//foundation/filemanagement/dfs_service/distributedfile.gni") + +config("optimize-size") { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-fvisibility-inlines-hidden", + "-Oz", + ] +} + +config("cloud_disk_service_public_config") { + include_dirs = [ "${target_gen_dir}" ] +} + +idl_gen_interface("cloud_disk_service") { + sources = [ "ICloudDiskService.idl" ] + sources_cpp = [] + sub_include = [ + "${innerkits_native_path}/clouddiskservice_kit_inner", + ] + configs = [] + innerapi_tags = [ "platformsdk" ] + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + log_domainid = "0xD003900" + log_tag = "CloudDiskService" + subsystem_name = "filemanagement" + part_name = "dfs_service" +} + +ohos_shared_library("clouddiskservice_sa") { + branch_protector_ret = "pac_ret" + configs = [ ":optimize-size" ] + public_configs = [ ":cloud_disk_service_public_config" ] + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + include_dirs = [ + "include", + "include/ipc", + "${innerkits_native_path}/clouddiskservice_kit_inner", + ] + + sources = [ + "src/ipc/cloud_disk_service.cpp", + "src/ipc/cloud_disk_service_callback_manager.cpp", + "src/ipc/cloud_disk_service_callback_proxy.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", + ] + + output_values = get_target_outputs(":cloud_disk_service") + sources += filter_include(output_values, [ "*_stub.cpp" ]) + + defines = [ + "LOG_DOMAIN=0xD004308", + "LOG_TAG=\"CLOUDDISKSERVICE_SA\"", + ] + + deps = [ + ":cloud_disk_service", + ":libcloud_disk_service_proxy", + "${innerkits_native_path}/clouddiskservice_kit_inner:clouddiskservice_kit_inner", + "${utils_path}:libdistributedfiledentry", + "${utils_path}:libdistributedfileutils", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "app_file_service:sandbox_helper_native", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "dsoftbus:softbus_client", + "ffrt:libffrt", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_single", + "libfuse:libfuse", + "memmgr:memmgrclient", + "netmanager_base:net_conn_manager_if", + "os_account:os_account_innerkits", + "preferences:native_preferences", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + use_exceptions = true + part_name = "dfs_service" + subsystem_name = "filemanagement" +} diff --git a/services/clouddiskservice/ICloudDiskService.idl b/services/clouddiskservice/ICloudDiskService.idl new file mode 100644 index 000000000..b9693a6ff --- /dev/null +++ b/services/clouddiskservice/ICloudDiskService.idl @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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. + */ +sequenceable OHOS.IRemoteObject; + +interface OHOS.FileManagement.CloudDiskService.ICloudDiskService +{ + void RegisterSyncRootChanges([in] String syncRootUri, [in] IRemoteObject changeCallback, + [out] String syncRootIndex); + void UnregisterSyncRootChanges([in] String syncRootUri, [out] boolean isOk); +} \ No newline at end of file diff --git a/services/clouddiskservice/include/ipc/cloud_disk_service.h b/services/clouddiskservice/include/ipc/cloud_disk_service.h new file mode 100644 index 000000000..8454d7c53 --- /dev/null +++ b/services/clouddiskservice/include/ipc/cloud_disk_service.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 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 CLOUD_DISK_SERVICE_H +#define CLOUD_DISK_SERVICE_H + +#include +#include +#include + +#include "iremote_stub.h" +#include "nocopyable.h" +#include "refbase.h" +#include "system_ability.h" + +#include "cloud_disk_service_stub.h" +#include "icloud_disk_service.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; + +class CloudDiskService final : public SystemAbility, public CloudDiskServiceStub, protected NoCopyable { + DECLARE_SYSTEM_ABILITY(CloudDiskService); + +public: + explicit CloudDiskService(int32_t saID, bool runOnCreate = true); + virtual ~CloudDiskService() = default; + + void OnStart() override; + void OnStop() override; + ServiceRunningState QueryServiceState() const + { + return state_; + } + + int32_t RegisterSyncRootChanges(const std::string &syncRootUri, const sptr &changeCallback, + std::string &syncRootIndex) override; + int32_t UnregisterSyncRootChanges(const std::string &syncRootUri, bool &isOk) override; + +private: + CloudDiskService(); + ServiceRunningState state_ { ServiceRunningState::STATE_NOT_START }; + static sptr instance_; + static std::mutex instanceLock_; + bool registerToService_ { false }; + void PublishSA(); +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SERVICE_H diff --git a/services/clouddiskservice/include/ipc/cloud_disk_service_callback_manager.h b/services/clouddiskservice/include/ipc/cloud_disk_service_callback_manager.h new file mode 100644 index 000000000..3e2d47f91 --- /dev/null +++ b/services/clouddiskservice/include/ipc/cloud_disk_service_callback_manager.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 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_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H + +#include "nocopyable.h" + +#include "i_cloud_disk_service_callback.h" +#include "svc_death_recipient.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceCallbackManager final : public NoCopyable { +public: + using TaskId = uint64_t; + static CloudDiskServiceCallbackManager &GetInstance(); + void AddCallback(const sptr &callback); + +private: + sptr callbackProxy_; + sptr deathRecipient_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H \ No newline at end of file diff --git a/services/clouddiskservice/include/ipc/cloud_disk_service_callback_proxy.h b/services/clouddiskservice/include/ipc/cloud_disk_service_callback_proxy.h new file mode 100644 index 000000000..a9b2c0226 --- /dev/null +++ b/services/clouddiskservice/include/ipc/cloud_disk_service_callback_proxy.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 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_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_PROXY_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_PROXY_H + +#include "iremote_proxy.h" + +#include "i_cloud_disk_service_callback.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceCallbackProxy : public IRemoteProxy { +public: + explicit CloudDiskServiceCallbackProxy(const sptr &impl) : IRemoteProxy(impl) {} + ~CloudDiskServiceCallbackProxy() override {} + + int32_t OnChangeData(ChangeData &changeData) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_PROXY_H \ No newline at end of file diff --git a/services/clouddiskservice/src/ipc/cloud_disk_service.cpp b/services/clouddiskservice/src/ipc/cloud_disk_service.cpp new file mode 100644 index 000000000..6396e3c1e --- /dev/null +++ b/services/clouddiskservice/src/ipc/cloud_disk_service.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service.h" + +#include +#include +#include +#include +#include +#include + +#include "cloud_disk_service_callback_manager.h" +#include "cloud_disk_service_task_manager.h" +#include "cloud_disk_service_callback_proxy.h" +#include "dfs_error.h" +#include "ffrt_inner.h" +#include "iremote_object.h" +#include "parameters.h" +#include "system_ability_definition.h" +#include "utils_directory.h" +#include "utils_log.h" +#ifdef HICOLLIE_ENABLE +#include "xcollie_helper.h" +#endif + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +using namespace std; + +namespace { +} +REGISTER_SYSTEM_ABILITY_BY_ID(CloudDiskService, FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID, true); + +CloudDiskService::CloudDiskService(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate) +{ +} + +void CloudDiskService::PublishSA() +{ + LOGI("Begin to init"); + if (!registerToService_) { + bool ret = SystemAbility::Publish(this); + if (!ret) { + throw runtime_error("Failed to publish the daemon"); + } + registerToService_ = true; + } + LOGI("Init finished successfully"); +} + +void CloudDiskService::OnStart() +{ + LOGI("Begin to start service"); + if (state_ == ServiceRunningState::STATE_RUNNING) { + LOGI("CloudDiskService has already started"); + return; + } + + try { + PublishSA(); + } catch (const exception &e) { + LOGE("%{public}s", e.what()); + } + + // system::SetParameter(CLOUD_FILE_SERVICE_SA_STATUS_FLAG, CLOUD_FILE_SERVICE_SA_START); + CloudDiskServiceTaskManager::GetInstance().StartTask(); + state_ = ServiceRunningState::STATE_RUNNING; + + LOGI("Start service successfully"); +} + +void CloudDiskService::OnStop() +{ + LOGI("Begin to stop"); + state_ = ServiceRunningState::STATE_NOT_START; + registerToService_ = false; + LOGI("Stop finished successfully"); +} + +int32_t CloudDiskService::RegisterSyncRootChanges(const std::string &syncRootUri, + const sptr &changeCallback, std::string &syncRootIndex) +{ + sptr changeDataCb = iface_cast(changeCallback); + return E_OK; +} + +int32_t CloudDiskService::UnregisterSyncRootChanges(const std::string &syncRootUri, bool &isOk) +{ + return E_OK; +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS diff --git a/services/clouddiskservice/src/ipc/cloud_disk_service_callback_manager.cpp b/services/clouddiskservice/src/ipc/cloud_disk_service_callback_manager.cpp new file mode 100644 index 000000000..87405f0dc --- /dev/null +++ b/services/clouddiskservice/src/ipc/cloud_disk_service_callback_manager.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 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 "ipc/cloud_disk_service_callback_manager.h" + +#include + +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +CloudDiskServiceCallbackManager &CloudDiskServiceCallbackManager::GetInstance() +{ + static CloudDiskServiceCallbackManager instance; + return instance; +} + +void CloudDiskServiceCallbackManager::AddCallback(const sptr &callback) +{ + if (callback == nullptr) { + return; + } + callbackProxy_ = callback; + auto remoteObject = callback->AsObject(); + auto deathCb = [this](const wptr &obj) { + callbackProxy_ = nullptr; + LOGE("client died"); + }; + deathRecipient_ = sptr(new SvcDeathRecipient(deathCb)); + remoteObject->AddDeathRecipient(deathRecipient_); +} + +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/src/ipc/cloud_disk_service_callback_proxy.cpp b/services/clouddiskservice/src/ipc/cloud_disk_service_callback_proxy.cpp new file mode 100644 index 000000000..85bdf81b7 --- /dev/null +++ b/services/clouddiskservice/src/ipc/cloud_disk_service_callback_proxy.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 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 "cloud_disk_service_callback_proxy.h" + +#include "cloud_file_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +int32_t CloudDiskServiceCallbackProxy::OnChangeData(ChangeData &changeData) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return -1; + } + + if (!data.WriteUint64(changeData.operationType)) { + LOGE("Failed to send the uri"); + return -1; + } + + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return -1; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_PROCESS, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return ret; + } + LOGI("End"); + return E_OK; +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/distributedfile.cfg b/services/distributedfile.cfg index 4464a8acb..0e55efdd3 100644 --- a/services/distributedfile.cfg +++ b/services/distributedfile.cfg @@ -64,5 +64,14 @@ "ohos.permission.WRITE_ALL_PHOTO", "ohos.permission.MEMOSPACE_SYNC" ] + }, { + "name": "clouddiskservice", + "path": ["/system/bin/sa_main", "/system/profile/clouddiskservice.json"], + "uid": "6161", + "gid": ["6161", "dfs"], + "sandbox": 0, + "secon": "u:r:clouddiskservice:s0", + "apl": "system_basic", + "ondemand": true }] } \ No newline at end of file -- Gitee