From 1531039ac60a3d51d187645b637a3af3873c997b Mon Sep 17 00:00:00 2001 From: fuletian Date: Sat, 6 Sep 2025 10:44:07 +0800 Subject: [PATCH 01/13] add tdd --- BUILD.gn | 13 + bundle.json | 67 +- distributedfile.gni | 1 + .../cloud_disk_service_callback_client.h | 68 ++ .../cloud_disk_service_callback_stub.h | 41 ++ .../include/cloud_disk_service_manager_impl.h | 49 ++ .../include/service_proxy.h | 45 ++ .../src/cloud_disk_common.cpp | 330 ++++++++++ .../cloud_disk_service_callback_client.cpp | 19 + .../src/cloud_disk_service_callback_stub.cpp | 118 ++++ .../src/cloud_disk_service_manager.cpp | 24 + .../src/cloud_disk_service_manager_impl.cpp | 208 ++++++ .../src/cloud_disk_service_task_manager.cpp | 152 +++++ .../src/service_proxy.cpp | 114 ++++ .../clouddiskservice_kit_inner/BUILD.gn | 101 +++ .../cloud_disk_common.h | 111 ++++ .../cloud_disk_service_callback.h | 32 + .../cloud_disk_service_manager.h | 39 ++ .../cloud_disk_service_task_manager.h | 71 +++ .../i_cloud_disk_service_callback.h | 38 ++ .../svc_death_recipient.h | 41 ++ services/5207.json | 12 + services/BUILD.gn | 12 + services/clouddiskservice.cfg | 12 + services/clouddiskservice/BUILD.gn | 134 ++++ .../clouddiskservice/ICloudDiskService.idl | 28 + .../ipc/include/account_status_listener.h | 45 ++ .../ipc/include/cloud_disk_service.h | 73 +++ .../cloud_disk_service_callback_manager.h | 45 ++ .../cloud_disk_service_callback_proxy.h | 38 ++ .../ipc/include/cloud_disk_sync_folder.h | 47 ++ .../ipc/src/account_status_listener.cpp | 85 +++ .../ipc/src/cloud_disk_service.cpp | 403 ++++++++++++ .../cloud_disk_service_callback_manager.cpp | 104 +++ .../src/cloud_disk_service_callback_proxy.cpp | 137 ++++ .../ipc/src/cloud_disk_sync_folder.cpp | 61 ++ .../monitor/include/disk_monitor.h | 63 ++ .../monitor/include/disk_notifier.h | 39 ++ .../monitor/include/disk_types.h | 65 ++ .../monitor/include/disk_utils.h | 33 + .../monitor/src/disk_monitor.cpp | 302 +++++++++ .../monitor/src/disk_notifier.cpp | 89 +++ .../monitor/src/disk_utils.cpp | 72 +++ .../clouddiskservice/seccomp_policy/BUILD.gn | 28 + .../clouddiskservice.seccomp.policy | 341 ++++++++++ .../monitor/disk_monitor_test.cpp | 603 ++++++++++++++++++ .../monitor/disk_notifier_test.cpp | 203 ++++++ .../monitor/disk_utils_test.cpp | 194 ++++++ .../system/include/dfsu_access_token_helper.h | 1 + 49 files changed, 4926 insertions(+), 25 deletions(-) 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 services/5207.json create mode 100644 services/clouddiskservice.cfg create mode 100644 services/clouddiskservice/BUILD.gn create mode 100644 services/clouddiskservice/ICloudDiskService.idl create mode 100644 services/clouddiskservice/ipc/include/account_status_listener.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_service.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_sync_folder.h create mode 100644 services/clouddiskservice/ipc/src/account_status_listener.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_service.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp create mode 100644 services/clouddiskservice/monitor/include/disk_monitor.h create mode 100644 services/clouddiskservice/monitor/include/disk_notifier.h create mode 100644 services/clouddiskservice/monitor/include/disk_types.h create mode 100644 services/clouddiskservice/monitor/include/disk_utils.h create mode 100644 services/clouddiskservice/monitor/src/disk_monitor.cpp create mode 100644 services/clouddiskservice/monitor/src/disk_notifier.cpp create mode 100644 services/clouddiskservice/monitor/src/disk_utils.cpp create mode 100644 services/clouddiskservice/seccomp_policy/BUILD.gn create mode 100644 services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy create mode 100644 test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp create mode 100644 test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp create mode 100644 test/unittests/clouddiskservice/monitor/disk_utils_test.cpp diff --git a/BUILD.gn b/BUILD.gn index e77869cad..117fb2d47 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -33,6 +33,14 @@ group("services_target") { if (dfs_service_feature_enable_cloud_adapter) { deps += [ "${services_path}:cloudfiledaemon_etc" ] } + if (dfs_service_feature_enable_cloud_disk) { + deps += [ + "${services_path}:clouddiskservice_sa_profile", + "${services_path}/clouddiskservice:clouddiskservice_sa", + "${services_path}:clouddiskservice_etc", + "${services_path}/clouddiskservice/seccomp_policy:disk_monitor_seccomp_filter", + ] + } } group("cloudsync_kit_inner_target") { @@ -50,6 +58,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..5c36e9712 100644 --- a/bundle.json +++ b/bundle.json @@ -17,12 +17,13 @@ "syscap": [ "SystemCapability.FileManagement.DistributedFileService.CloudSync.Core", "SystemCapability.FileManagement.DistributedFileService.CloudSyncManager" - ], - "features": [ - "dfs_service_feature_enable_cloud_adapter", - "dfs_service_feature_enable_dist_file_daemon" - ], - "adapted_system_type": [ + ], + "features": [ + "dfs_service_feature_enable_cloud_adapter", + "dfs_service_feature_enable_cloud_disk", + "dfs_service_feature_enable_dist_file_daemon" + ], + "adapted_system_type": [ "small", "standard" ], @@ -69,22 +70,24 @@ "samgr", "selinux_adapter", "thermal_manager", - "os_account", - "power_manager", - "libfuse", - "zlib" - ], - "third_party": [] - }, + "os_account", + "power_manager", + "libfuse", + "zlib", + "user_file_service" + ], + "third_party": [] + }, "build": { "group_type": { "base_group": [], - "fwk_group": [], - "service_group": [ - "//foundation/filemanagement/dfs_service:services_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", + "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", @@ -105,12 +108,26 @@ "cloud_sync_constants.h", "cloud_sync_common.h" ], - "header_base": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/cloudsync_kit_inner" - } - }, - { - "name": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/cloudsync_kit_inner:cloudsync_asset_kit_inner", - "header": { + "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": { "header_files": [ "cloud_sync_asset_manager.h" ], diff --git a/distributedfile.gni b/distributedfile.gni index 2e8d8a0c1..3dafabb3b 100644 --- a/distributedfile.gni +++ b/distributedfile.gni @@ -37,6 +37,7 @@ declare_args() { cloudsync_service_power = false } dfs_service_feature_enable_cloud_adapter = false + dfs_service_feature_enable_cloud_disk = true dfs_service_feature_enable_dist_file_daemon = true if (defined(global_parts_info) && 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..2149c09e1 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_client.h @@ -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. + */ + +#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) {} + + void OnChangeData(std::vector& changeData) override { + if (callback_ == nullptr) { + LOGE("callback_ is nullptr"); + return; + } + callback_->OnChangeData(changeData); + } + + void OnReturnSetFailedList(std::vector& failedList) override { + if (callback_ == nullptr) { + LOGE("callback_ is nullptr"); + return; + } + callback_->OnReturnSetFailedList(failedList); + } + + void OnReturnGetResult(std::vector& resultList) override { + if (callback_ == nullptr) { + LOGE("callback_ is nullptr"); + return; + } + callback_->OnReturnGetResult(resultList); + } +private: + std::shared_ptr callback_{ nullptr }; +}; + +// class CloudDiskServiceCallbackImpl final : public CloudDiskServiceCallback { +// public: +// void OnChangeData(std::vector& changeData) override { +// LOGE("start in client"); +// } + +// void OnReturnSetFailedList(vector& failedList) override { +// LOGE("start in client"); +// } +// }; +} // 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..00ee31581 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_stub.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_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); + int32_t HandleOnReturnSetFailedList(MessageParcel &data, MessageParcel &reply); + int32_t HandleOnReturnGetResult(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..2b90c4ace --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_manager_impl.h @@ -0,0 +1,49 @@ +/* + * 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 RegisterSyncFolderChanges(const std::string& syncFolder, const std::shared_ptr callback) override; + int32_t UnregisterSyncFolderChanges(const std::string& syncFolder) override; + int32_t GetSyncFolderChanges(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) override; + int32_t SetFileSyncStates(const std::string& syncFolder, const std::vector& fileSyncStates, const std::shared_ptr callback) override; + int32_t GetFileSyncStates(const std::string& syncFolder, const std::vector& pathArray, const std::shared_ptr callback) override; + int32_t RegisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) override; + int32_t UnregisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) 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..23b900812 --- /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..fd4d47481 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp @@ -0,0 +1,330 @@ +/* + * 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 { + +// CloudDiskCommon &CloudDiskCommon::GetInstance() +// { +// static CloudDiskCommon instance; +// return instance; +// } + + +bool FileSyncState::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(path)) { + LOGE("failed to write path"); + return false; + } + + if (!parcel.WriteInt32(static_cast(state))) { + LOGE("failed to write state"); + return false; + } + + return true; +} + +FileSyncState *FileSyncState::Unmarshalling(Parcel &parcel) +{ + FileSyncState *info = new (std::nothrow) FileSyncState(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool FileSyncState::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(path)) { + LOGE("failed to write path"); + return false; + } + + int32_t readState = 0; + if (!parcel.ReadInt32(readState)) { + LOGE("failed to write state"); + return false; + } + state = static_cast(readState); + + return true; +} + + +bool ChangeData::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteUint64(updateSequenceNumber)) { + LOGE("failed to write updateSequenceNumber"); + return false; + } + + if (!parcel.WriteString(fileId)) { + LOGE("failed to write fileId"); + return false; + } + + if (!parcel.WriteString(parentFileId)) { + LOGE("failed to write parentFileId"); + return false; + } + + if (!parcel.WriteString(relativePath)) { + LOGE("failed to write relativePath"); + return false; + } + + if (!parcel.WriteInt32(static_cast(operationType))) { + LOGE("failed to write operationType"); + return false; + } + + if (!parcel.WriteUint64(size)) { + LOGE("failed to write size"); + return false; + } + + if (!parcel.WriteUint64(mtime)) { + LOGE("failed to write mtime"); + return false; + } + + if (!parcel.WriteUint64(timeStamp)) { + LOGE("failed to write timeStamp"); + 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.ReadUint64(updateSequenceNumber)) { + LOGE("failed to read updateSequenceNumber"); + return false; + } + + if (!parcel.ReadString(fileId)) { + LOGE("failed to read fileId"); + return false; + } + + if (!parcel.ReadString(parentFileId)) { + LOGE("failed to read parentFileId"); + return false; + } + + if (!parcel.ReadString(relativePath)) { + LOGE("failed to read relativePath"); + return false; + } + + int32_t readType = 0; + if (!parcel.ReadInt32(readType)) { + LOGE("failed to write operationType"); + return false; + } + operationType = static_cast(readType); + + if (!parcel.ReadUint64(size)) { + LOGE("failed to read size"); + return false; + } + + if (!parcel.ReadUint64(mtime)) { + LOGE("failed to read mtime"); + return false; + } + + if (!parcel.ReadUint64(timeStamp)) { + LOGE("failed to read timeStamp"); + return false; + } + + return true; +} + +bool ChangesResult::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteUint64(nextUsn)) { + LOGE("failed to write nextUsn"); + return false; + } + + if (!parcel.WriteInt32(static_cast(isEof))) { + LOGE("failed to write isEof"); + return false; + } + + if (!parcel.WriteInt32(static_cast(changesData.size()))) { + LOGE("failed to write changeData"); + return false; + } + + for(auto& item : changesData) { + item.Marshalling(parcel); + } + + return true; +} + +ChangesResult *ChangesResult::Unmarshalling(Parcel &parcel) +{ + ChangesResult *info = new (std::nothrow) ChangesResult(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool ChangesResult::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadUint64(nextUsn)) { + LOGE("failed to read nextUSN"); + return false; + } + + int32_t readIsEof = 0; + if (!parcel.ReadInt32(readIsEof)) { + LOGE("failed to read isEof"); + return false; + } + isEof = readIsEof; + + int32_t size = 0; + if (!parcel.ReadInt32(size)) { + LOGE("failed to read changeData size"); + return false; + } + for(int32_t i = 0; i < size; ++i) { + ChangeData changeData; + changeData.ReadFromParcel(parcel); + changesData.push_back(changeData); + } + + return true; +} + +bool FailedList::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(path)) { + LOGE("failed to write path"); + return false; + } + + if (!parcel.WriteInt32(static_cast(error))) { + LOGE("failed to write error"); + return false; + } + + return true; +} + +FailedList *FailedList::Unmarshalling(Parcel &parcel) +{ + FailedList *info = new (std::nothrow) FailedList(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool FailedList::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(path)) { + LOGE("failed to read path"); + return false; + } + + int32_t readError = 0; + if (!parcel.ReadInt32(readError)) { + LOGE("failed to write errno"); + return false; + } + error = static_cast(readError); + + return true; +} + +bool ResultList::Marshalling(Parcel &parcel) const +{ + + if (!parcel.WriteInt32(static_cast(isSuccess))) { + LOGE("failed to write isSuccess"); + return false; + } + + if (!parcel.WriteInt32(static_cast(state))) { + LOGE("failed to write state"); + return false; + } + + return true; +} + +ResultList *ResultList::Unmarshalling(Parcel &parcel) +{ + ResultList *info = new (std::nothrow) ResultList(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool ResultList::ReadFromParcel(Parcel &parcel) +{ + int32_t readIsSuccess = 0; + if (!parcel.ReadInt32(readIsSuccess)) { + LOGE("failed to write isSuccess"); + return false; + } + isSuccess= readIsSuccess; + + int32_t readState = 0; + if (!parcel.ReadInt32(readState)) { + LOGE("failed to write state"); + return false; + } + state = static_cast(readState); + + 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..e4f533e7b --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_stub.cpp @@ -0,0 +1,118 @@ +/* + * 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_CHANGE_DATA] = [this](MessageParcel &data, MessageParcel &reply) { + return this->HandleOnChangeData(data, reply); + }; + opToInterfaceMap_[SERVICE_CMD_ON_RETURN_SET_FAILED_LIST] = [this](MessageParcel &data, MessageParcel &reply) { + return this->HandleOnReturnSetFailedList(data, reply); + }; + opToInterfaceMap_[SERVICE_CMD_ON_RETURN_GET_RESULT] = [this](MessageParcel &data, MessageParcel &reply) { + return this->HandleOnReturnGetResult(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) +{ + std::vector changesData; + + auto size = data.ReadInt32(); + if (size > static_cast(VECTOR_MAX_SIZE)) { + return ERR_INVALID_DATA; + } + for (int i = 0; i < size; ++i) { + std::unique_ptr value(data.ReadParcelable()); + if(!value) { + LOGE("object of ChangeData is nullptr"); + return E_INVAL_ARG; + } + changesData.push_back(*value); + } + + OnChangeData(changesData); + LOGI("HandleOnChangeData end"); + return E_OK; +} + +int32_t CloudDiskServiceCallbackStub::HandleOnReturnSetFailedList(MessageParcel &data, MessageParcel &reply) +{ + std::vector failedList; + + auto size = data.ReadInt32(); + if (size > static_cast(VECTOR_MAX_SIZE)) { + return ERR_INVALID_DATA; + } + for (int i = 0; i < size; ++i) { + std::unique_ptr value(data.ReadParcelable()); + if(!value) { + LOGE("object of failedList is nullptr"); + return E_INVAL_ARG; + } + failedList.push_back(*value); + } + + OnReturnSetFailedList(failedList); + LOGI("HandleOnReturnSetFailedList end"); + return E_OK; +} + +int32_t CloudDiskServiceCallbackStub::HandleOnReturnGetResult(MessageParcel &data, MessageParcel &reply) +{ + std::vector resultList; + + auto size = data.ReadInt32(); + if (size > static_cast(VECTOR_MAX_SIZE)) { + return ERR_INVALID_DATA; + } + for (int i = 0; i < size; ++i) { + std::unique_ptr value(data.ReadParcelable()); + if(!value) { + LOGE("object of resultList is nullptr"); + return E_INVAL_ARG; + } + resultList.push_back(*value); + } + + OnReturnGetResult(resultList); + LOGI("HandleOnReturnGetResult end"); + 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..1f9cb668f --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager_impl.cpp @@ -0,0 +1,208 @@ +/* + * 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 "dfsu_access_token_helper.h" +#include "cloud_disk_service_callback_client.h" +#include "cloud_file_utils.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; +} + +int32_t CloudDiskServiceManagerImpl::RegisterSyncFolderChanges(const std::string& syncFolder, + const std::shared_ptr callback) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + if (!callback) { + LOGE("callback is null"); + return E_INVAL_ARG; + } + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + auto ret = serviceProxy->RegisterSyncFolderChangesInner(syncFolder, + sptr(new (std::nothrow) CloudDiskServiceCallbackClient(callback))); + { + unique_lock lock(callbackMutex_); + callback_ = callback; + } + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("RegisterSyncFolderChanges ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::UnregisterSyncFolderChanges(const std::string& syncFolder) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->UnregisterSyncFolderChangesInner(syncFolder); + { + unique_lock lock(callbackMutex_); + callback_ = nullptr; + } + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("UnregisterSyncFolderChanges ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::GetSyncFolderChanges(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->GetSyncFolderChangesInner(syncFolder, count, startUsn, changesResult); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("GetSyncFolderChangesInner ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::SetFileSyncStates(const std::string& syncFolder, const std::vector& fileSyncStates, + const std::shared_ptr callback) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("start SetXattr in impl"); + + if (!callback) { + LOGE("callback is null"); + return E_INVAL_ARG; + } + + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->SetFileSyncStatesInner(syncFolder, fileSyncStates, sptr(new (std::nothrow) CloudDiskServiceCallbackClient(callback))); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("SetFileSyncState, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::GetFileSyncStates(const std::string& syncFolder, const std::vector& pathArray, const std::shared_ptr callback) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("start GetXattr in impl"); + + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->GetFileSyncStatesInner(syncFolder, pathArray, sptr(new (std::nothrow) CloudDiskServiceCallbackClient(callback))); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("GetFileSyncState, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::RegisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + LOGI("start RegisterSyncFolder in impl"); + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->RegisterSyncFolderInner(userId, bundleName, path); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("RegisterSyncFolder, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::UnregisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + LOGI("start UnregisterSyncFolder in impl"); + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->UnregisterSyncFolderInner(userId, bundleName, path); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("UnregisterSyncFolder, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +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(); + } + } +} + +} // 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..145c3a0b0 --- /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..9fa81d389 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/service_proxy.cpp @@ -0,0 +1,114 @@ +/* + * 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; + } + + auto object = samgr->CheckSystemAbility(FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID); + if (object == nullptr) { + LOGE("CloudDiskService::Connect object == nullptr"); + return nullptr; + } + + serviceProxy_ = iface_cast(object); + if (serviceProxy_ == nullptr) { + LOGE("CloudDiskService::Connect service == 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..8094983b2 --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/BUILD.gn @@ -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. + +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\"", + ] + + if (dfs_service_feature_enable_cloud_disk) { + defines += [ "SUPPORT_CLOUD_DISK_SERVICE "] + } + + 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", + ] + + 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..454ef967e --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_common.h @@ -0,0 +1,111 @@ +/* + * 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 { + +/* +When adding new enumeration values, pay attention to the maximum enumeration value judgment of the getxattr method in clouddiskservice.cpp +*/ +enum class SyncState { + IDLE = 0, + SYNCING, + SYNC_SUCCESSED, + SYNC_FAILED, + SYNC_CANCELED, + SYNC_CONFLICTED, +}; + +enum class OperationType : uint8_t { + NONE = 0, + CREATE, + DELETE, + MOVE_FROM, + MOVE_TO, + CLOSE_WRITE, + SYNC_FOLDER_INVALID, + OPERATION_MAX, +}; + +struct FileSyncState : public Parcelable{ + std::string path; + SyncState state; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static FileSyncState *Unmarshalling(Parcel &parcel); +}; + +struct ChangeData : public Parcelable { + uint64_t updateSequenceNumber; + std::string fileId; + std::string parentFileId; + std::string relativePath; + OperationType operationType; + uint64_t size; + uint64_t mtime; + uint64_t timeStamp; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static ChangeData *Unmarshalling(Parcel &parcel); +}; + +struct ChangesResult : public Parcelable { + uint64_t nextUsn; + bool isEof; + std::vector changesData; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static ChangesResult *Unmarshalling(Parcel &parcel); +}; + +enum class ErrorReason { + INVALID_ARGUMENT = 0, + NO_SUCH_FILE, + NO_SPACE_LEFT, + OUT_OF_RANGE, +}; + +struct FailedList : public Parcelable { + std::string path; + ErrorReason error; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static FailedList *Unmarshalling(Parcel &parcel); +}; + +struct ResultList : public FailedList { + bool isSuccess; + SyncState state; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static ResultList *Unmarshalling(Parcel &parcel); +}; + +#define RETURN_ON_ERR(ret) \ + do { \ + int32_t res = ret; \ + if ((res) != E_OK) { \ + return res; \ + } \ + } while (0) +} // 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..254134a9d --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_callback.h @@ -0,0 +1,32 @@ +/* + * 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 void OnChangeData(std::vector &changeData) = 0; + virtual void OnReturnSetFailedList(std::vector &FailedList) = 0; + virtual void OnReturnGetResult(std::vector &resultList) = 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..c7cb36bcb --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_manager.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_MANAGER_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_H + +#include + +#include "cloud_disk_service_callback.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceManager { +public: + static CloudDiskServiceManager &GetInstance(); + + virtual int32_t RegisterSyncFolderChanges(const std::string& syncFolder, + const std::shared_ptr callback) = 0; + virtual int32_t UnregisterSyncFolderChanges(const std::string& syncFolder) = 0; + virtual int32_t GetSyncFolderChanges(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) = 0; + virtual int32_t SetFileSyncStates(const std::string& syncFolder, const std::vector& fileSyncStates, const std::shared_ptr callback) = 0; + virtual int32_t GetFileSyncStates(const std::string& syncFolder, const std::vector& pathArray, const std::shared_ptr callback) = 0; + virtual int32_t RegisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) = 0; + virtual int32_t UnregisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) = 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..97f4aa30c --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/i_cloud_disk_service_callback.h @@ -0,0 +1,38 @@ +/* + * 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_CHANGE_DATA = 0, + SERVICE_CMD_ON_RETURN_SET_FAILED_LIST = 1, + SERVICE_CMD_ON_RETURN_GET_RESULT = 2, + }; + + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Filemanagement.Dfs.ICloudDiskServiceCallback") + +protected : + const int VECTOR_MAX_SIZE = 102400; +}; +} // 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/services/5207.json b/services/5207.json new file mode 100644 index 000000000..62f22ff23 --- /dev/null +++ b/services/5207.json @@ -0,0 +1,12 @@ +{ + "process": "clouddiskservice", + "systemability": [ + { + "name": 5207, + "libpath": "libclouddiskservice_sa.z.so", + "run-on-create": true, + "distributed": false, + "dump-level": 1 + } + ] +} \ No newline at end of file diff --git a/services/BUILD.gn b/services/BUILD.gn index 0eec280de..01f49084f 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" @@ -32,6 +37,13 @@ ohos_prebuilt_etc("distributedfile_etc") { subsystem_name = "filemanagement" } +ohos_prebuilt_etc("clouddiskservice_etc") { + source = "clouddiskservice.cfg" + relative_install_dir = "init" + part_name = "dfs_service" + subsystem_name = "filemanagement" +} + ohos_prebuilt_etc("cloudfiledaemon_etc") { source = "cloudfiledaemon.cfg" relative_install_dir = "init" diff --git a/services/clouddiskservice.cfg b/services/clouddiskservice.cfg new file mode 100644 index 000000000..cb0d09c6f --- /dev/null +++ b/services/clouddiskservice.cfg @@ -0,0 +1,12 @@ +{ + "services": [ { + "name": "clouddiskservice", + "path": ["/system/bin/sa_main", "/system/profile/clouddiskservice.json"], + "uid": "6161", + "gid": ["6161", "dfs", "1006"], + "sandbox": 0, + "secon": "u:r:clouddiskservice:s0", + "caps": ["CAP_SYS_ADMIN", "CAP_DAC_READ_SEARCH"], + "apl": "system_basic" + }] +} \ No newline at end of file diff --git a/services/clouddiskservice/BUILD.gn b/services/clouddiskservice/BUILD.gn new file mode 100644 index 000000000..22851541e --- /dev/null +++ b/services/clouddiskservice/BUILD.gn @@ -0,0 +1,134 @@ +# 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 = [ + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", + ] + sub_include = [ + "${distributedfile_path}/utils/log/include", + "${innerkits_native_path}/clouddiskservice_kit_inner", + ] + configs = [] + + sequenceable_ext_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + + 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 = [ + "ipc/include", + "monitor/include", + # "${innerkits_native_path}/clouddiskservice_kit_inner", + ] + + sources = [ + "ipc/src/cloud_disk_service.cpp", + "ipc/src/cloud_disk_service_callback_manager.cpp", + "ipc/src/cloud_disk_service_callback_proxy.cpp", + "ipc/src/cloud_disk_sync_folder.cpp", + "ipc/src/account_status_listener.cpp", + "monitor/src/disk_monitor.cpp", + "monitor/src/disk_notifier.cpp", + "monitor/src/disk_utils.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.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", + ] + + if (build_seccomp) { + deps += [ "${services_path}/clouddiskservice/seccomp_policy:disk_monitor_seccomp_filter" ] + } + + external_deps = [ + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "ffrt:libffrt", + "e2fsprogs:libext2_uuid", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_single", + "samgr:samgr_proxy", + "safwk:system_ability_fwk", + "user_file_service:cloud_disk_manager_kit" + ] + + 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..a2b40a18b --- /dev/null +++ b/services/clouddiskservice/ICloudDiskService.idl @@ -0,0 +1,28 @@ +/* + * 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; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.ChangesResult; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.FileSyncState; + +interface OHOS.FileManagement.CloudDiskService.ICloudDiskService +{ + void RegisterSyncFolderChangesInner([in] String syncFolder, [in] IRemoteObject remoteobject); + void UnregisterSyncFolderChangesInner([in] String syncFolder); + ChangesResult GetSyncFolderChangesInner([in] String syncFolder, [in] unsigned long count, [in] unsigned long startUSN); + void SetFileSyncStatesInner([in] String syncFolder, [in] List fileSyncStates, [in] IRemoteObject remoteobject); + void GetFileSyncStatesInner([in] String syncFolder, [in] List pathArray, [in] IRemoteObject remoteobject); + void RegisterSyncFolderInner([in] int userId, [in] String bundleName, [in] String path); + void UnregisterSyncFolderInner([in] int userId, [in] String bundleName, [in] String path); +} diff --git a/services/clouddiskservice/ipc/include/account_status_listener.h b/services/clouddiskservice/ipc/include/account_status_listener.h new file mode 100644 index 000000000..198d513e4 --- /dev/null +++ b/services/clouddiskservice/ipc/include/account_status_listener.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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_ACCOUNT_STATUS_LISTENER_H +#define CLOUD_DISK_SERVICE_ACCOUNT_STATUS_LISTENER_H + +#include "cloud_file_utils.h" +#include "common_event_subscriber.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +class AccountStatusListener { +public: + explicit AccountStatusListener() = default; + ~AccountStatusListener(); + void Start(); + void Stop(); + +private: + std::shared_ptr commonEventSubscriber_ = nullptr; +}; + +class AccountStatusSubscriber : public EventFwk::CommonEventSubscriber { +public: + AccountStatusSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo); + ~AccountStatusSubscriber() override {} + void OnReceiveEvent(const EventFwk::CommonEventData &eventData) override; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SERVICE_ACCOUNT_STATUS_LISTENER_H \ No newline at end of file diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service.h b/services/clouddiskservice/ipc/include/cloud_disk_service.h new file mode 100644 index 000000000..f8fee675a --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service.h @@ -0,0 +1,73 @@ +/* + * 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 "account_status_listener.h" +#include "cloud_disk_service_stub.h" +#include "dfsu_access_token_helper.h" +#include "icloud_disk_service.h" +#include "i_cloud_disk_service_callback.h" +#include "iremote_stub.h" +#include "nocopyable.h" +#include "refbase.h" +#include "system_ability.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; + static CloudDiskService &GetInstance(); + + void OnStart() override; + void OnStop() override; + ErrCode RegisterSyncFolderChangesInner(const std::string& syncFolder, + const sptr& remoteObject) override; + ErrCode UnregisterSyncFolderChangesInner(const std::string& syncFolder) override; + ErrCode GetSyncFolderChangesInner(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) override; + ErrCode SetFileSyncStatesInner(const std::string& syncFolder, const std::vector& fileSyncStates, const sptr& remoteObject) override; + ErrCode GetFileSyncStatesInner(const std::string& syncFolder, const std::vector& pathArray, const sptr& remoteObject) override; + ErrCode RegisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) override; + ErrCode UnregisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) override; + + bool CheckSyncFolder(const uint32_t syncFolderIndex); + +private: + CloudDiskService(); + ServiceRunningState state_ { ServiceRunningState::STATE_NOT_START }; + static sptr instance_; + static std::mutex instanceLock_; + bool registerToService_ { false }; + std::mutex callbackMutex_; + void PublishSA(); + void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; + std::shared_ptr accountStatusListener_ = nullptr; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SERVICE_H diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h new file mode 100644 index 000000000..c50ffffc0 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.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_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 RigisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex, const sptr &callback); + void UnregisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex); + void AddCallback(const std::string bundleName, const sptr &callback); + void OnChangeData(const uint32_t syncFolderIndex, std::vector &changeData); + + struct CallbackValue { + sptr callback; + std::vector syncFolderIndexs; + }; + std::map callbackAppMap_; // map -> callback + std::map> callbackIndexMap_; + std::mutex callbackAppMutex_; + std::mutex callbackIndexMutex_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H \ No newline at end of file diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h new file mode 100644 index 000000000..fb84354f7 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h @@ -0,0 +1,38 @@ +/* + * 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_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 {} + + void OnChangeData(std::vector &changeData) override; + void OnReturnSetFailedList(std::vector &FailedList) override; + void OnReturnGetResult(std::vector &resultList) 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/ipc/include/cloud_disk_sync_folder.h b/services/clouddiskservice/ipc/include/cloud_disk_sync_folder.h new file mode 100644 index 000000000..a6bd32c75 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_sync_folder.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 CLOUD_DISK_SYNC_FOLDER_H +#define CLOUD_DISK_SYNC_FOLDER_H + +#include +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +struct SyncFolderValue { + std::string bundleName; + std::string path; +}; + +class CloudDiskSyncFolder { + +public: + static CloudDiskSyncFolder &GetInstance(); + void AddSyncFolder(const uint32_t syncFolderIndex, SyncFolderValue syncFolderValue); + void DeleteSyncFolder(const uint32_t syncFolderIndex); + int32_t GetSyncFolderSize(); + bool CheckSyncFolder(const uint32_t syncFolderIndex); + +private: + std::unordered_map syncFolderMap; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SYNC_FOLDER_H diff --git a/services/clouddiskservice/ipc/src/account_status_listener.cpp b/services/clouddiskservice/ipc/src/account_status_listener.cpp new file mode 100644 index 000000000..03cf83dcf --- /dev/null +++ b/services/clouddiskservice/ipc/src/account_status_listener.cpp @@ -0,0 +1,85 @@ +/* + * 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 "account_status_listener.h" + +#include + +#include "common_event_manager.h" +#include "common_event_support.h" +#include "cloud_disk_sync_folder.h" +#include "cloud_disk_comm.h" +#include "cloud_disk_manager.h" + +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +AccountStatusSubscriber::AccountStatusSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) + : EventFwk::CommonEventSubscriber(subscribeInfo) +{ +} + +void AccountStatusSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + auto action = eventData.GetWant().GetAction(); + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_STARTED) { + LOGI("OnStartUser!"); + + std::vector syncFolders = + OHOS::FileManagement::CloudDiskManager::GetInstance().GetAllSyncFoldersForSa(); + for (auto item : syncFolders) { + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = item.bundleName_; + syncFolderValue.path = item.uri_; + uint32_t syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(item.uri_); + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + } + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 0) { + // 启动监听 + // DiskMonitor::GetInstance().StartMonitor(DfsuAccessTokenHelper::GetUserId()); + } + } +} + +AccountStatusListener::~AccountStatusListener() +{ + Stop(); +} + +void AccountStatusListener::Start() +{ + /* subscribe Account login, logout, Package remove and Datashare ready */ + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_HWID_LOGIN); + EventFwk::CommonEventSubscribeInfo info(matchingSkills); + commonEventSubscriber_ = std::make_shared(info); + auto subRet = EventFwk::CommonEventManager::SubscribeCommonEvent(commonEventSubscriber_); + LOGI("Subscriber end, SubscribeResult = %{public}d", subRet); +} + +void AccountStatusListener::Stop() +{ + if (commonEventSubscriber_ != nullptr) { + EventFwk::CommonEventManager::UnSubscribeCommonEvent(commonEventSubscriber_); + commonEventSubscriber_ = nullptr; + } +} + +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service.cpp new file mode 100644 index 000000000..fdafe5da0 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service.cpp @@ -0,0 +1,403 @@ +/* + * 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 + +#include "cloud_disk_service_callback_manager.h" +#include "cloud_disk_service_task_manager.h" +// #include "cloud_disk_service_syncroot.h" +#include "cloud_disk_sync_folder.h" +#include "dfs_error.h" +// #include "disk_monitor.h" +#include "ffrt_inner.h" +#include "iremote_object.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; + +const int32_t GET_FILE_SYNC_MAX = 100; +constexpr const char* FILE_SYNC_STATE = "user.clouddisk.filesyncstate"; + +namespace { +} +REGISTER_SYSTEM_ABILITY_BY_ID(CloudDiskService, FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID, true); + +CloudDiskService::CloudDiskService(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate) +{ + accountStatusListener_ = make_shared(); +} + +CloudDiskService::CloudDiskService() +{ +} + +CloudDiskService &CloudDiskService::GetInstance() +{ + static CloudDiskService instance; + return instance; +} + +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()); + } + + CloudDiskServiceTaskManager::GetInstance().StartTask(); + DiskMonitor::GetInstance().StartMonitor(100); + 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"); +} + +static int32_t CheckPermissions(const string &permission, bool isSystemApp) +{ + if (!permission.empty() && !DfsuAccessTokenHelper::CheckCallerPermission(permission)) { + LOGE("permission denied"); + return E_PERMISSION_DENIED; + } + return E_OK; +} + +int32_t CloudDiskService::RegisterSyncFolderChangesInner(const std::string& syncFolder, + const sptr& remoteObject) +{ + LOGI("Begin RegisterSyncFolderChangesInner"); + LOGI("RegisterSyncFolderChangesInner start uri:%{public}s", syncFolder.c_str()); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + if (remoteObject == nullptr) { + LOGE("remoteObject is nullptr"); + return E_INVAL_ARG; + } + + std::string bundleName = ""; + int ret = DfsuAccessTokenHelper::GetCallerBundleName(bundleName); + if (ret != E_OK) { + LOGE("Get bundleName failed, ret:%{public}d", ret); + return ret; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + if (CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("SyncFolder is exist"); + return E_PARAMS_; + } + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = bundleName; + syncFolderValue.path = syncFolder; + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = syncFolder; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + // int32_t userId = DfsuAccessTokenHelper::GetUserId(); + // CloudDiskServiceSyncFolder::RegisterSyncFolder(userId, syncFolderIndex, syncFolder); + + auto callback = iface_cast(remoteObject); + LOGI("callback is null : %{public}s", callback == nullptr? "true" : "false"); + + CloudDiskServiceCallbackManager::GetInstance().RigisSyncFolderMap(bundleName, syncFolderIndex, callback); + + CloudDiskServiceCallbackManager::GetInstance().AddCallback(bundleName, callback); + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("RegisterSyncFolderChangesInner end syncFolderIndex:%{public}u", syncFolderIndex); + LOGI("End RegisterSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::UnregisterSyncFolderChangesInner(const std::string& syncFolder) +{ + LOGI("Begin UnregisterSyncFolderChangesInner"); + LOGI("UnregisterSyncFolderChangesInner start syncFolder:%{public}s", syncFolder.c_str()); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + std::string bundleName = ""; + int ret = DfsuAccessTokenHelper::GetCallerBundleName(bundleName); + if (ret != E_OK) { + LOGE("Get bundleName failed, ret:%{public}d", ret); + return ret; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + CloudDiskSyncFolder::GetInstance().DeleteSyncFolder(syncFolderIndex); + + CloudDiskServiceCallbackManager::GetInstance().UnregisSyncFolderMap(bundleName, syncFolderIndex); + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = syncFolder; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + // int32_t userId = DfsuAccessTokenHelper::GetUserId(); + // CloudDiskServiceSyncFolder::UnRegisterSyncFolder(userId, syncFolderIndex); + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End UnregisterSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::GetSyncFolderChangesInner(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) +{ + LOGI("Begin GetSyncFolderChangesInner"); + LOGI("GetSyncFolderChangesInner start syncFolder:%{public}s", syncFolder.c_str()); + LOGI("GetSyncFolderChangesInner start count:%{public}ld", count); + LOGI("GetSyncFolderChangesInner start startUSN:%{public}ld", startUsn); + LOGI("GetSyncFolderChangesInner start changesResult.nextUsn:%{public}ld", changesResult.nextUsn); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + return E_PARAMS_; + } + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + + TaskKey taskKey; + taskKey.bundleName = "test"; + taskKey.syncChronousRootPath = "test"; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + // CloudDiskServiceSyncFolder::UnRegisterSyncFolder(userId, syncFolderIndex); + + ChangeData changeData; + changeData.updateSequenceNumber = 1; + changeData.fileId = "1"; + changeData.parentFileId = "1"; + changeData.relativePath = "test"; + changeData.operationType = OperationType::CREATE; + changeData.size = 1; + changeData.mtime = 1; + changeData.timeStamp = 1; + changeData.timeStamp = 1; + changesResult.nextUsn = 1; + changesResult.isEof = true; + changesResult.changesData.push_back(changeData); + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("GetSyncFolderChangesInner end changesResult.nextUsn:%{public}ld", changesResult.nextUsn); + LOGI("End GetSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::SetFileSyncStatesInner(const std::string& syncFolder, const std::vector& fileSyncStates, const sptr& remoteObject) +{ + LOGI("Begin SetXattrInner"); + FailedList failed; + std::vector failedList; + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex) || fileSyncStates.empty() || fileSyncStates.size() > GET_FILE_SYNC_MAX) { + LOGE("Invalid parameter"); + return E_PARAMS_; + } + + auto callback = iface_cast(remoteObject); + for (auto& item : fileSyncStates) { + uint8_t state = static_cast(item.state); + if (state > static_cast(SyncState::SYNC_CONFLICTED)) { + LOGE("Invalid state for %{public}s", item.path.c_str()); + failed.path = item.path; + failed.error = ErrorReason::INVALID_ARGUMENT; // 待定 + failedList.push_back(failed); + continue; + } + if (setxattr(item.path.c_str(), FILE_SYNC_STATE, &state, sizeof(state), 0) != 0) { + LOGE("Failed to set xattr for file:%{public}s, err: %{public}d", item.path.c_str(), errno); + failed.path = item.path; + failed.error = ErrorReason::NO_SUCH_FILE; // 待定 + failedList.push_back(failed); + } + } + + callback->OnReturnSetFailedList(failedList); + + if (!failedList.empty()) { + return E_IPCSS; + } + + LOGI("End SetXattrInner"); + return 0; +} + +int32_t CloudDiskService::GetFileSyncStatesInner(const std::string& syncFolder, const std::vector& pathArray, const sptr& remoteObject) +{ + LOGI("Begin GetXattrInner"); + + // auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + // if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex) || pathArray.empty() || pathArray.size() > GET_FILE_SYNC_MAX) { + // LOGE("Invalid parameter"); + // return E_PARAMS_; + // } + + // auto callback = iface_cast(remoteObject); + // FailedList failed; + // std::vector failedList; + // std::vector resultList; + + // for (auto& item : pathArray) { + // auto xattrValueSize = getxattr(item.c_str(), FILE_SYNC_STATE, nullptr, 0); + // if (xattrValueSize < 0) { + // LOGE("getxattr failed, errno : %{public}d", errno); + // failed.path = item; + // failed.error = ErrorReason::NO_SUCH_FILE; // 待定 + // failedList.push_back(failed); + // continue; + // } + // std::unique_ptr xattrValue = std::make_unique((long)xattrValueSize + 1); + // if (xattrValue == nullptr) { + // LOGE("Failed to allocate memory for xattrValue, errno : %{public}d", errno); + // failed.path = item; + // failed.error = ErrorReason::NO_SPACE_LEFT; // 待定 + // failedList.push_back(failed); + // continue; + // } + // xattrValueSize = getxattr(item.c_str(), FILE_SYNC_STATE, xattrValue.get(), xattrValueSize); + // if (xattrValueSize <= 0) { + // LOGE("getxattr failed, errno : %{public}d", errno); + // failed.path = item; + // failed.error = ErrorReason::NO_SUCH_FILE; // 待定 + // failedList.push_back(failed); + // continue; + // } + // uint8_t rawState = static_cast(xattrValue[0]); + // if (rawState > static_cast(SyncState::SYNC_CONFLICTED)) { + // LOGE("get invalid number"); + // failed.path = item; + // failed.error = ErrorReason::INVALID_ARGUMENT; // 待定 + // failedList.push_back(failed); + // continue; + // } + // FileSyncState fileSyncState; + // fileSyncState.path = syncFolder; + // fileSyncState.state = static_cast(rawState); + // resultList.push_back(fileSyncState); + // } + + // callback->OnReturnGetResult(resultList); + + LOGI("End GetXattrInner"); + return 0; +} + +int32_t CloudDiskService::RegisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) +{ + LOGI("Begin GetSyncFolderChangesInner"); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + return E_PARAMS_; + } + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = path; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = bundleName; + syncFolderValue.path = path; + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 1) { + // DiskMonitor::GetInstance().StartMonitor(userId); + } + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End GetSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::UnregisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) +{ + LOGI("Begin GetSyncFolderChangesInner"); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + return E_PARAMS_; + } + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = path; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + CloudDiskSyncFolder::GetInstance().DeleteSyncFolder(syncFolderIndex); + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 0) { + // DiskMonitor::GetInstance().StopMonitor(); + } + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End GetSyncFolderChangesInner"); + return 0; +} + +void CloudDiskService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + LOGI("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId); + accountStatusListener_->Start(); +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp new file mode 100644 index 000000000..5280d08c8 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp @@ -0,0 +1,104 @@ +/* + * 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_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 std::string bundleName, const sptr &callback) +{ + if (callbackAppMap_[bundleName].callback != nullptr) { + return; + } + if (callback == nullptr) { + LOGE("callback is nullptr"); + return; + } + callbackAppMap_[bundleName].callback = callback; + auto remoteObject = callback->AsObject(); + auto deathCb = [this, bundleName](const wptr &obj) { + LOGE("client died"); + std::vector syncFolderIndex; + auto it = callbackAppMap_.find(bundleName); + if (it != callbackAppMap_.end()) { + syncFolderIndex = it->second.syncFolderIndexs; + callbackAppMap_.erase(it); + } + for (auto item : syncFolderIndex) { + callbackIndexMap_.erase(item); + } + }; + auto death = sptr(new SvcDeathRecipient(deathCb)); + remoteObject->AddDeathRecipient(death); +} + +void CloudDiskServiceCallbackManager::OnChangeData(const uint32_t syncFolderIndex, std::vector &changeData) +{ + auto item = callbackIndexMap_.find(syncFolderIndex); + if (item == callbackIndexMap_.end() || !item->second) { + LOGE("callback is nullptr"); + return; + } + item->second->OnChangeData(changeData); +} + +void CloudDiskServiceCallbackManager::RigisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex, const sptr &callback) +{ + unique_lock lockApp(callbackAppMutex_); + unique_lock lockIndex(callbackIndexMutex_); + auto it = callbackAppMap_.find(bundleName); + if (it == callbackAppMap_.end()) { + CallbackValue callbackValue; + callbackValue.syncFolderIndexs.push_back(syncFolderIndex); + callbackAppMap_[bundleName] = callbackValue; + } else { + it->second.syncFolderIndexs.push_back(syncFolderIndex); + } + + auto item = callbackIndexMap_.find(syncFolderIndex); + if (item == callbackIndexMap_.end()) { + callbackIndexMap_[syncFolderIndex] = callback; + } +} + +void CloudDiskServiceCallbackManager::UnregisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex) +{ + unique_lock lock(callbackIndexMutex_); + auto it = callbackIndexMap_.find(syncFolderIndex); + if(it != callbackIndexMap_.end()) callbackIndexMap_.erase(it); + + auto item = callbackAppMap_.find(bundleName); + if (item == callbackAppMap_.end()) { + LOGE("no such app in callback"); + return; + } + auto& vec = item->second.syncFolderIndexs; + auto pos = std::find(vec.begin(), vec.end(), syncFolderIndex); + if (pos != vec.end()) { + vec.erase(pos); + } +} + +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp new file mode 100644 index 000000000..00ff74835 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp @@ -0,0 +1,137 @@ +/* + * 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_proxy.h" + +#include "cloud_file_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +void CloudDiskServiceCallbackProxy::OnChangeData(std::vector &changeData) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return; + } + + if (changeData.size() > static_cast(VECTOR_MAX_SIZE)) { + return; + } + + data.WriteInt32(changeData.size()); + for (auto item = changeData.begin(); item != changeData.end(); ++item) { + if (!data.WriteParcelable(&(*item))) { + return; + } + } + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_CHANGE_DATA, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return; + } + LOGI("End"); + return; +} + +void CloudDiskServiceCallbackProxy::OnReturnSetFailedList(std::vector &failedList) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return; + } + + if (failedList.size() > static_cast(VECTOR_MAX_SIZE)) { + return; + } + data.WriteInt32(failedList.size()); + for (auto item = failedList.begin(); item != failedList.end(); ++item) { + if (!data.WriteParcelable(&(*item))) { + return; + } + } + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_RETURN_SET_FAILED_LIST, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return; + } + LOGI("End"); + return; +} + +void CloudDiskServiceCallbackProxy::OnReturnGetResult(std::vector &resultList) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return; + } + + // if (resultList.size() > static_cast(VECTOR_MAX_SIZE) || failedList.size() > static_cast(VECTOR_MAX_SIZE)) { + if (resultList.size() > static_cast(VECTOR_MAX_SIZE)) { + return; + } + + data.WriteInt32(resultList.size()); + for (auto item = resultList.begin(); item != resultList.end(); ++item) { + if (!data.WriteParcelable(&(*item))) { + return; + } + } + // data.WriteInt32(failedList.size()); + // for (auto item = failedList.begin(); item != failedList.end(); ++item) { + // if (!data.WriteParcelable(&(*item))) { + // return; + // } + // } + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_RETURN_GET_RESULT, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return; + } + LOGI("End"); + return; +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp b/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp new file mode 100644 index 000000000..011f1f7d4 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp @@ -0,0 +1,61 @@ +/* + * 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_sync_folder.h" + +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +CloudDiskSyncFolder &CloudDiskSyncFolder::GetInstance() +{ + static CloudDiskSyncFolder instance; + return instance; +} + +void CloudDiskSyncFolder::AddSyncFolder(const uint32_t syncFolderIndex, SyncFolderValue syncFolderValue) +{ + auto item = syncFolderMap.find(syncFolderIndex); + if (item == syncFolderMap.end()) { + syncFolderMap[syncFolderIndex] = syncFolderValue; + } +} + +void CloudDiskSyncFolder::DeleteSyncFolder(const uint32_t syncFolderIndex) +{ + auto item = syncFolderMap.find(syncFolderIndex); + if (item == syncFolderMap.end()) { + syncFolderMap.erase(syncFolderIndex); + } +} + +int32_t CloudDiskSyncFolder::GetSyncFolderSize() +{ + return syncFolderMap.size(); +} + +bool CloudDiskSyncFolder::CheckSyncFolder(const uint32_t syncFolderIndex) { + auto it = syncFolderMap.find(syncFolderIndex); + if (it == syncFolderMap.end()) { + LOGE("no such syncFolder"); + return false; + } + return true; +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/clouddiskservice/monitor/include/disk_monitor.h b/services/clouddiskservice/monitor/include/disk_monitor.h new file mode 100644 index 000000000..63aee0990 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_monitor.h @@ -0,0 +1,63 @@ +/* + * 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_FILEMANAGEMENT_DISK_MONITOR_H +#define OHOS_FILEMANAGEMENT_DISK_MONITOR_H + +#include +#include +#include + +#include "disk_types.h" + +namespace OHOS::FileManagement::CloudDiskService { +class DiskMonitor { +public: + static DiskMonitor &GetInstance(); + bool StartMonitor(int32_t userId); + void StopMonitor(); + +private: + bool InitFanotify(); + void InitInner(int32_t userId); + void CollectEvents(); + void HandleEvents(int32_t mountFd, char eventsBuf[], size_t dataLen); + void EventProcess(struct fanotify_event_metadata *metaData, const std::string &filePath); + // events handle + void HandleCreate(const std::string &filePath); + void HandleDelete(const std::string &filePath); + void HandleMoveFrom(const std::string &filePath); + void HandleMoveTo(const std::string &filePath); + void HandleCloseWrite(const std::string &filePath); + // events filter + std::pair GetSyncFolderIndex(const std::string &filePath); + bool IsInBlackList(const std::string &path); + +private: + // monitor status + int32_t userId_{-1}; + int32_t fanotifyFd_{-1}; + DIR *mountFp_{nullptr}; + int32_t mountFd_{-1}; // will be closed automatically after close(DIR*) + bool isRunning_{true}; + // events handle + EventInfo oldEventInfo_; + bool oldIsSyncFolder_{false}; + // events filter + std::string syncFolderPrefix_; + std::vector blackList_; +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/include/disk_notifier.h b/services/clouddiskservice/monitor/include/disk_notifier.h new file mode 100644 index 000000000..1c34e2740 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_notifier.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_FILEMANAGEMENT_DISK_NOTIFIER_H +#define OHOS_FILEMANAGEMENT_DISK_NOTIFIER_H + +#include + +#include "disk_types.h" +#include "ffrt_inner.h" + +namespace OHOS::FileManagement::CloudDiskService { +class DiskNotifier { +public: + static DiskNotifier &GetInstance(); + void PostEvent(const EventInfo &eventInfo); + +private: + void NotifyEventFull(); + void NotifyEventAll(); + static void CallBack(void *data); +private: + std::vector eventList_; + ffrt_timer_t handle_{-1}; + ffrt::mutex mutex_; +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/include/disk_types.h b/services/clouddiskservice/monitor/include/disk_types.h new file mode 100644 index 000000000..8b2c982e6 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_types.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 OHOS_FILEMANAGEMENT_DISK_TYPES_H +#define OHOS_FILEMANAGEMENT_DISK_TYPES_H +#include +#include +#include + +#include "cloud_disk_common.h" + +namespace OHOS::FileManagement::CloudDiskService { +constexpr int64_t SECOND_TO_MILLISECOND = 1e3; +constexpr int64_t MILLISECOND_TO_NANOSECOND = 1e6; + +static uint64_t UTCTimeMilliSeconds() +{ + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return t.tv_sec * SECOND_TO_MILLISECOND + t.tv_nsec / MILLISECOND_TO_NANOSECOND; +} + +struct EventInfo { + int32_t userId{-1}; + uint32_t syncFolderIndex{0}; + std::string path{""}; + std::string name{""}; + uint8_t operateType{static_cast(OperationType::OPERATION_MAX)}; + uint64_t timestamp{0}; + int32_t moveOptId{0}; + + EventInfo() {} + EventInfo(int32_t uid, int32_t syncFolder, OperationType type, const std::string &filePath) + : userId(uid), syncFolderIndex(syncFolder), operateType(static_cast(type)) + { + path = std::filesystem::path(filePath).parent_path().string(); + name = std::filesystem::path(filePath).filename().string(); + timestamp = UTCTimeMilliSeconds(); + } + + void Reset() + { + userId = -1; + syncFolderIndex = 0; + path = ""; + name = ""; + operateType = static_cast(OperationType::OPERATION_MAX); + timestamp = 0; + moveOptId = 0; + } +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/include/disk_utils.h b/services/clouddiskservice/monitor/include/disk_utils.h new file mode 100644 index 000000000..b196bfbc4 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_utils.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_FILEMANAGEMENT_DISK_UTILS_H +#define OHOS_FILEMANAGEMENT_DISK_UTILS_H + +#include +#include +#include +#include + +namespace OHOS::FileManagement::CloudDiskService { +class DiskUtils { +public: + static bool ExtractFileName(int type, std::string &fileName, struct file_handle *fileHandle); + static std::string GetFilePath(int32_t eventFd, const std::string &fileName); + static void CloseFd(int &fd); + static void CloseDir(DIR *&dir); +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/src/disk_monitor.cpp b/services/clouddiskservice/monitor/src/disk_monitor.cpp new file mode 100644 index 000000000..4bf0c3702 --- /dev/null +++ b/services/clouddiskservice/monitor/src/disk_monitor.cpp @@ -0,0 +1,302 @@ +/* + * 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 "disk_monitor.h" + +#include +#include +#include + +#include "cloud_disk_sync_folder.h" +#include "disk_notifier.h" +#include "disk_utils.h" +#include "ffrt_inner.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +namespace{ +constexpr uint32_t INIT_FLAGS = FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME | FAN_UNLIMITED_QUEUE; +constexpr uint32_t INIT_EVENT_FLAGS = O_RDONLY | O_LARGEFILE; +constexpr uint32_t MARK_FLAGS = FAN_MARK_ADD | FAN_MARK_FILESYSTEM; +constexpr uint64_t MARK_MASK = FAN_CREATE | FAN_DELETE | FAN_MOVED_FROM | FAN_MOVED_TO | FAN_ONDIR | FAN_CLOSE_WRITE; +constexpr int32_t INVALID_SYNC_FOLDER = 0; +const string MOUNT_PATH = "/data/service"; +const string DATA_SERVICE_EL2 = "/data/service/el2/"; +const string HMDFS_DOCS = "/hmdfs/account/files/Docs"; +const vector BLACK_DIRS = {"/.Trash", "/.Recent", "/.thumbs", "/HO_DATA_EXT_MISC"}; +} + +DiskMonitor &DiskMonitor::GetInstance() +{ + static DiskMonitor instance_; + return instance_; +} + +bool DiskMonitor::StartMonitor(int32_t userId) +{ + LOGI("Start monitor: %{public}d", userId); + if(!InitFanotify()){ + return false; + } + + InitInner(userId); + ffrt::submit([this] { this->CollectEvents(); }); + LOGI("Start monitor finished"); + return true; +} + +void DiskMonitor::StopMonitor() +{ + userId_ = -1; + isRunning_ = false; + syncFolderPrefix_.clear(); + blackList_.clear(); + // clean fd + DiskUtils::CloseFd(fanotifyFd_); + DiskUtils::CloseDir(mountFp_); +} + +void DiskMonitor::InitInner(int32_t userId) +{ + userId_ = userId; + isRunning_ = true; + syncFolderPrefix_ = DATA_SERVICE_EL2 + to_string(userId) + HMDFS_DOCS; + for (auto &it : BLACK_DIRS) { + blackList_.push_back(DATA_SERVICE_EL2 + to_string(userId) + HMDFS_DOCS + it); + } + LOGI("debugonly: syncFolderPrefix-> %{public}s", syncFolderPrefix_.c_str()); + for (auto &it : blackList_) { + LOGI("debugonly: black-> %{public}s", it.c_str()); + } +} + +bool DiskMonitor::InitFanotify() +{ + LOGI("init start"); + fanotifyFd_ = fanotify_init(INIT_FLAGS, INIT_EVENT_FLAGS); + if (fanotifyFd_ == -1) { + LOGE("disk monitor init failed, errno: %{public}d", errno); + return false; + } + if (fanotify_mark(fanotifyFd_, MARK_FLAGS, MARK_MASK, AT_FDCWD, MOUNT_PATH.c_str()) == -1) { + LOGE("fanotify_mark failed, errno: %{public}d", errno); + DiskUtils::CloseFd(fanotifyFd_); + return false; + } + mountFp_ = opendir(MOUNT_PATH.c_str()); + if (mountFp_ == nullptr) { + LOGE("open dir failed, errno: %{public}d", errno); + DiskUtils::CloseFd(fanotifyFd_); + return false; + } + mountFd_ = dirfd(mountFp_); + if (mountFd_ == -1) { + LOGE("get dirfd failed, errno: %{public}d", errno); + DiskUtils::CloseFd(fanotifyFd_); + DiskUtils::CloseDir(mountFp_); + return false; + } + LOGI("Init end"); + return true; +} + +void DiskMonitor::CollectEvents() +{ + while (isRunning_) { + char eventsBuf[4096]{}; + ssize_t dataLen = read(fanotifyFd_, eventsBuf, sizeof(eventsBuf)); + if (dataLen == -1 && errno != EAGAIN) { + LOGE("read failed, errno: %{public}d", errno); + continue; + } + if (dataLen == 0) { + LOGI("no data to read"); + continue; + } + // TODO: check current user is active(unlock) + HandleEvents(mountFd_, eventsBuf, dataLen); + } +} + +void DiskMonitor::HandleEvents(int32_t mountFd, char eventsBuf[], size_t dataLen) +{ + for (struct fanotify_event_metadata *metaData = reinterpret_cast(eventsBuf); + FAN_EVENT_OK(metaData, dataLen); metaData = FAN_EVENT_NEXT(metaData, dataLen)) { + struct fanotify_event_info_fid *fID = reinterpret_cast(metaData + 1); + struct file_handle *fileHandle = reinterpret_cast(fID->handle); + if (fileHandle == nullptr) { + LOGE("fileHandle is null"); + continue; + } + + // get file name + string fileName; + if (!DiskUtils::ExtractFileName(fID->hdr.info_type, fileName, fileHandle)) { + continue; + } + bool isDir = metaData->mask & FAN_ONDIR; + // other info + int eventFd = open_by_handle_at(mountFd, fileHandle, O_RDONLY); + if (eventFd == -1) { + LOGE("open_by_handle_at, errno: %{public}d", errno); + continue; + } + + string filePath = DiskUtils::GetFilePath(eventFd, fileName); + if (filePath.empty()) { + close(eventFd); + continue; + } + + EventProcess(metaData, filePath); + + close(eventFd); + } +} + +void DiskMonitor::EventProcess(struct fanotify_event_metadata *metaData, const string &filePath) +{ + if (metaData->mask & FAN_CREATE) { + HandleCreate(filePath); + } else if (metaData->mask & FAN_DELETE) { + HandleDelete(filePath); + } else if (metaData->mask & FAN_MOVED_FROM) { + HandleMoveFrom(filePath); + } else if (metaData->mask & FAN_MOVED_TO) { + HandleMoveTo(filePath); + } else if (metaData->mask & FAN_CLOSE_WRITE) { + HandleCloseWrite(filePath); + } + if (!IsInBlackList(filePath)) { + LOGD("mask: %{public}llu, path: %{public}s", metaData->mask, filePath.c_str()); + } +} + +void DiskMonitor::HandleCreate(const string &filePath) +{ + auto [syncFolderIndex, _] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + auto eventInfo = EventInfo(userId_, syncFolderIndex, OperationType::CREATE, filePath); + DiskNotifier::GetInstance().PostEvent(eventInfo); +} + +void DiskMonitor::HandleDelete(const string &filePath) +{ + auto [syncFolderIndex, isSyncFolder] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + OperationType type = isSyncFolder ? OperationType::SYNC_FOLDER_INVALID : OperationType::DELETE; + auto eventInfo = EventInfo(userId_, syncFolderIndex, type, filePath); + DiskNotifier::GetInstance().PostEvent(eventInfo); +} + +void DiskMonitor::HandleMoveFrom(const string &filePath) +{ + auto [syncFolderIndex, isSyncFolder] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + oldEventInfo_ = EventInfo(userId_, syncFolderIndex, OperationType::MOVE_FROM, filePath); + oldIsSyncFolder_ = isSyncFolder; +} + +/* + * old is not in sync folder, new is not in sync folder, skip + * old is not in sync folder, new is in sync folder, create->new + * old is in sync folder, new is not in sync folder: + * 1. old is sync folder, sync_folder_invalid->old + * 2. old is not sync folder, delete->old + * old is in sync folder, new is in sync folder, sync root is the same, move_from->old + move_to->new + * old is in sync folder, new is in sync folder, sync root is not the same + * 1. old is sync folder, sync_folder_invalid->old + create->new + * 2. old is not sync folder, delete->old + create->new + */ +void DiskMonitor::HandleMoveTo(const string &filePath) +{ + auto [syncFolderIndex, _] = GetSyncFolderIndex(filePath); + auto eventInfo = EventInfo(userId_, syncFolderIndex, OperationType::MOVE_TO, filePath); + do { + // old is not in sync folder + if (oldEventInfo_.syncFolderIndex == INVALID_SYNC_FOLDER) { + if (eventInfo.syncFolderIndex == INVALID_SYNC_FOLDER) { + break; + } + eventInfo.operateType = static_cast(OperationType::CREATE); + DiskNotifier::GetInstance().PostEvent(eventInfo); + break; + } + // old is in sync folder + if (eventInfo.syncFolderIndex == INVALID_SYNC_FOLDER) { + OperationType type = oldIsSyncFolder_ ? OperationType::SYNC_FOLDER_INVALID : OperationType::DELETE; + oldEventInfo_.operateType = static_cast(type); + DiskNotifier::GetInstance().PostEvent(oldEventInfo_); + break; + } + if (oldEventInfo_.syncFolderIndex == eventInfo.syncFolderIndex) { + oldEventInfo_.operateType = static_cast(OperationType::MOVE_FROM); + eventInfo.operateType = static_cast(OperationType::MOVE_TO); + DiskNotifier::GetInstance().PostEvent(oldEventInfo_); + DiskNotifier::GetInstance().PostEvent(eventInfo); + break; + } + OperationType type = oldIsSyncFolder_ ? OperationType::SYNC_FOLDER_INVALID : OperationType::DELETE; + oldEventInfo_.operateType = static_cast(type); + eventInfo.operateType = static_cast(OperationType::CREATE); + DiskNotifier::GetInstance().PostEvent(oldEventInfo_); + DiskNotifier::GetInstance().PostEvent(eventInfo); + } while (0); + + oldEventInfo_.Reset(); +} + +void DiskMonitor::HandleCloseWrite(const string &filePath) +{ + auto [syncFolderIndex, _] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + auto eventInfo = EventInfo(userId_, syncFolderIndex, OperationType::CLOSE_WRITE, filePath); + DiskNotifier::GetInstance().PostEvent(eventInfo); +} + +pair DiskMonitor::GetSyncFolderIndex(const string &filePath) +{ + if (IsInBlackList(filePath)) { + return {INVALID_SYNC_FOLDER, false}; + } + for (auto &it : CloudDiskSyncFolder::GetInstance().GetSyncFolderMap()) { + if (filePath.find(it.second.path) == 0) { + return {it.first, filePath == it.second.path}; + } + } + return {INVALID_SYNC_FOLDER, false}; +} + +bool DiskMonitor::IsInBlackList(const string &path) +{ + if (path.find(syncFolderPrefix_) != 0) { + return true; + } + for (auto &it : blackList_) { + if (path.find(it) == 0) { + return true; + } + } + return false; +} +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/services/clouddiskservice/monitor/src/disk_notifier.cpp b/services/clouddiskservice/monitor/src/disk_notifier.cpp new file mode 100644 index 000000000..13b1c8e1c --- /dev/null +++ b/services/clouddiskservice/monitor/src/disk_notifier.cpp @@ -0,0 +1,89 @@ +/* + * 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 "disk_notifier.h" + +#include "cloud_disk_service_syncfolder.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +namespace { +constexpr uint32_t MAX_EVENT_NUM = 500; +constexpr uint64_t NOTIFY_TIMEOUT_MS = 200; +} // namespace +DiskNotifier &DiskNotifier::GetInstance() +{ + static DiskNotifier instance_; + return instance_; +} + +void DiskNotifier::PostEvent(const EventInfo &eventInfo) +{ + lock_guard lock(mutex_); + LOGD("opt: %{public}d path: %{public}s name: %{public}s", eventInfo.operateType, eventInfo.path.c_str(), + eventInfo.name.c_str()); + // 1. list is empty, firt run, setup timer + // 2. list has reached the max, notify and reset timer + if (eventList_.empty()) { + ffrt_timer_stop(ffrt_qos_default, handle_); + handle_ = ffrt_timer_start(ffrt_qos_default, NOTIFY_TIMEOUT_MS, nullptr, CallBack, false); + } else if (eventList_.size() >= MAX_EVENT_NUM) { + ffrt_timer_stop(ffrt_qos_default, handle_); + NotifyEventFull(); + handle_ = ffrt_timer_start(ffrt_qos_default, NOTIFY_TIMEOUT_MS, nullptr, CallBack, false); + } + // when recv the same eventInfo, just update timestamp + if (!eventList_.empty() && eventList_.back().operateType == eventInfo.operateType && + eventList_.back().path == eventInfo.path && eventList_.back().name == eventInfo.name) { + eventList_.back().timestamp = eventInfo.timestamp; + return; + } + eventList_.push_back(eventInfo); +} + +void DiskNotifier::NotifyEventFull() +{ + vector tempEventList; + if (eventList_.empty()) { + return; + } + eventList_.swap(tempEventList); + eventList_.clear(); + + CloudDiskServiceSyncFolder::SetSyncFolderChanges(tempEventList); + LOGI("NOTIFY_FULL: size: %{public}zu", tempEventList.size()); +} + +void DiskNotifier::NotifyEventAll() +{ + vector tempEventList; + { + lock_guard lock(mutex_); + if (eventList_.empty()) { + return; + } + eventList_.swap(tempEventList); + eventList_.clear(); + } + + CloudDiskServiceSyncFolder::SetSyncFolderChanges(tempEventList); + LOGI("NOTIFY_ALL: size: %{public}zu", tempEventList.size()); +} + +void DiskNotifier::CallBack(void *) +{ + DiskNotifier::GetInstance().NotifyEventAll(); +} +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/services/clouddiskservice/monitor/src/disk_utils.cpp b/services/clouddiskservice/monitor/src/disk_utils.cpp new file mode 100644 index 000000000..fa9995f25 --- /dev/null +++ b/services/clouddiskservice/monitor/src/disk_utils.cpp @@ -0,0 +1,72 @@ +/* + * 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 "disk_utils.h" + +#include +#include + +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +const string PROC_SELF_FD = "/proc/self/fd/"; + +bool DiskUtils::ExtractFileName(int type, string &fileName, struct file_handle *fileHandle) +{ + if (type == FAN_EVENT_INFO_TYPE_FID || type == FAN_EVENT_INFO_TYPE_DFID) { + fileName.clear(); + } else if (type == FAN_EVENT_INFO_TYPE_DFID_NAME) { + fileName = reinterpret_cast(fileHandle->f_handle + fileHandle->handle_bytes); + } else { + return false; + } + return true; +} + +string DiskUtils::GetFilePath(int32_t eventFd, const string &fileName) +{ + char eventFilePath[PATH_MAX + 1]; + string procFdPath = PROC_SELF_FD + to_string(eventFd); + ssize_t pathLen = readlink(procFdPath.c_str(), eventFilePath, sizeof(eventFilePath) - 1); + if (pathLen == -1 || pathLen > PATH_MAX) { + LOGI("readlink failed , errno: %{public}d", errno); + return ""; + } + eventFilePath[pathLen] = '\0'; + + string filePath(eventFilePath); + if (!fileName.empty() && fileName.compare(".") != 0) { + filePath += "/" + fileName; + } + return filePath; +} + +void DiskUtils::CloseFd(int &fd) +{ + if (fd != -1) { + close(fd); + fd = -1; + } +} + +void DiskUtils::CloseDir(DIR *&dir) +{ + if (dir != nullptr) { + closedir(dir); + dir = nullptr; + } +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/seccomp_policy/BUILD.gn b/services/clouddiskservice/seccomp_policy/BUILD.gn new file mode 100644 index 000000000..b1b3bef58 --- /dev/null +++ b/services/clouddiskservice/seccomp_policy/BUILD.gn @@ -0,0 +1,28 @@ +# 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/init/seccomp/scripts/seccomp_policy_fixer.gni") + +ohos_prebuilt_seccomp("disk_monitor_seccomp_filter") { + sources = [ "clouddiskservice.seccomp.policy" ] + + filtername = "clouddiskservice" + + process_type = "system" + + part_name = "dfs_service" + subsystem_name = "filemanagement" + + install_enable = true + install_images = [ "system" ] +} \ No newline at end of file diff --git a/services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy b/services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy new file mode 100644 index 000000000..ccb4fe499 --- /dev/null +++ b/services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy @@ -0,0 +1,341 @@ +# 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@allowList +io_setup;all +io_destroy;all +io_submit;all +io_cancel;all +io_getevents;all +setxattr;all +lsetxattr;all +fsetxattr;all +getxattr;all +lgetxattr;all +fgetxattr;all +listxattr;all +llistxattr;all +flistxattr;all +removexattr;all +lremovexattr;all +fremovexattr;all +getcwd;all +eventfd2;all +epoll_create1;all +epoll_ctl;all +epoll_pwait;all +dup;all +dup3;all +fcntl;arm64 +inotify_init1;all +inotify_add_watch;all +inotify_rm_watch;all +ioctl;all +ioprio_set;arm64 +ioprio_get;arm64 +flock;all +mknodat;all +mkdirat;all +unlinkat;all +symlinkat;all +linkat;all +renameat;arm +renameat;arm64 +umount2;all +mount;all +pivot_root;all +statfs;arm64 +fstatfs;arm64 +truncate;all +ftruncate;arm64 +fallocate;all +faccessat;all +faccessat2;all +chdir;all +fchdir;all +chroot;all +fchmod;all +fchmodat;all +fchownat;all +fchown;arm64 +openat;all +close;all +pipe2;all +quotactl;all +getdents64;all +lseek;all +read;all +write;all +readv;all +writev;all +pread64;all +pwrite64;all +preadv;all +pwritev;all +sendfile;all +pselect6;all +ppoll;all +signalfd4;all +vmsplice;all +splice;all +tee;all +readlinkat;all +newfstatat;arm64 +fstat;arm64 +sync;all +fsync;all +fdatasync;all +sync_file_range;arm64 +timerfd_create;all +timerfd_settime;all +timerfd_gettime;all +utimensat;all +acct;all +capget;all +capset;all +personality;all +exit;all +exit_group;all +waitid;all +set_tid_address;all +unshare;all +futex;all +set_robust_list;all +get_robust_list;all +nanosleep;all +getitimer;all +setitimer;all +init_module;all +delete_module;all +timer_create;all +timer_gettime;all +timer_getoverrun;all +timer_settime;all +timer_delete;all +clock_settime;all +clock_gettime;all +clock_getres;all +clock_nanosleep;all +syslog;all +ptrace;all +sched_setparam;all +sched_setscheduler;all +sched_getscheduler;all +sched_getparam;all +sched_setaffinity;all +sched_getaffinity;all +sched_yield;all +sched_get_priority_max;all +sched_get_priority_min;all +sched_rr_get_interval;all +restart_syscall;all +kill;all +tkill;all +tgkill;all +sigaltstack;all +rt_sigsuspend;all +rt_sigaction;all +rt_sigprocmask;all +rt_sigpending;all +rt_sigtimedwait;all +rt_sigqueueinfo;all +rt_sigreturn;all +setpriority;all +getpriority;all +reboot;all +setregid;arm64 +setgid;arm64 +setreuid;arm64 +setuid;arm64 +setresuid;arm64 +getresuid;arm64 +setresgid;arm64 +getresgid;arm64 +setfsuid;all +setfsgid;all +times;all +setpgid;all +getpgid;all +getsid;all +setsid;all +getgroups;arm64 +setgroups;arm64 +uname;all +sethostname;all +setdomainname;all +getrlimit;arm64 +setrlimit;all +getrusage;all +umask;all +prctl;all +getcpu;all +gettimeofday;all +settimeofday;all +adjtimex;all +getpid;all +getppid;all +getuid;arm64 +geteuid;arm64 +getgid;arm64 +getegid;arm64 +gettid;all +sysinfo;all +semget;all +shmget;all +shmctl;all +shmat;all +shmdt;all +socket;all +socketpair;all +bind;all +listen;all +accept;all +connect;all +getsockname;all +getpeername;all +sendto;all +recvfrom;all +setsockopt;all +getsockopt;all +shutdown;all +sendmsg;all +recvmsg;all +readahead;all +brk;all +munmap;all +mremap;all +add_key;all +keyctl;all +clone;all +execve;all +mmap;arm64 +fadvise64;arm64 +mprotect;all +msync;all +mlock;all +munlock;all +mlockall;all +munlockall;all +mincore;all +madvise;all +rt_tgsigqueueinfo;all +perf_event_open;all +accept4;all +recvmmsg;all +wait4;all +prlimit64;all +clock_adjtime;all +syncfs;all +setns;all +sendmmsg;all +process_vm_readv;all +process_vm_writev;all +finit_module;all +sched_setattr;all +sched_getattr;all +renameat2;all +seccomp;all +getrandom;all +memfd_create;all +bpf;all +execveat;all +userfaultfd;all +membarrier;all +mlock2;all +copy_file_range;all +preadv2;all +pwritev2;all +statx;all +pidfd_send_signal;all +pidfd_open;all +close_range;all +pidfd_getfd;all +process_madvise;all +fork;arm +open;arm +unlink;arm +mknod;arm +chmod;arm +access;arm +rename;arm +mkdir;arm +rmdir;arm +pipe;arm +dup2;arm +sigaction;arm +symlink;arm +readlink;arm +stat;arm +sigreturn;arm +_llseek;arm +_newselect;arm +poll;arm +vfork;arm +ugetrlimit;arm +mmap2;arm +truncate64;arm +ftruncate64;arm +stat64;arm +fstat64;arm +lchown32;arm +getuid32;arm +getgid32;arm +geteuid32;arm +getegid32;arm +setreuid32;arm +setregid32;arm +chown32;arm +getgroups32;arm +setgroups32;arm +fchown32;arm +setresuid32;arm +getresuid32;arm +setresgid32;arm +getresgid32;arm +setuid32;arm +setgid32;arm +fcntl64;arm +sendfile64;arm +statfs64;arm +fstatfs64;arm +fadvise64_64;arm +fstatat64;arm +sync_file_range2;arm +clock_gettime64;arm +clock_settime64;arm +clock_adjtime64;arm +clock_getres_time64;arm +clock_nanosleep_time64;arm +timer_gettime64;arm +timer_settime64;arm +timerfd_gettime64;arm +timerfd_settime64;arm +utimensat_time64;arm +pselect6_time64;arm +ppoll_time64;arm +recvmmsg_time64;arm +semtimedop_time64;arm +rt_sigtimedwait_time64;arm +futex_time64;arm +sched_rr_get_interval_time64;arm +cacheflush;arm +set_tls;arm +mbind;all +fanotify_init;arm64 +fanotify_mark;arm64 +open_by_handle_at;arm64 diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp new file mode 100644 index 000000000..8b7477244 --- /dev/null +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -0,0 +1,603 @@ +/* + * 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 +#include + +#include "disk_monitor.h" + +namespace OHOS::FileManagement::CloudDiskService::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DiskMonitorMock : public DiskMonitor { +public: + MOCK_METHOD0(InitFanotify, bool()); + MOCK_METHOD1(InitInner, void(int32_t)); + MOCK_METHOD0(CollectEvents, void()); + MOCK_METHOD1(HandleCreate, void(const string &filePath)); + MOCK_METHOD1(HandleDelete, void(const string &filePath)); + MOCK_METHOD1(HandleMoveFrom, void(const string &filePath)); + MOCK_METHOD1(HandleMoveTo, void(const string &filePath)); + MOCK_METHOD1(HandleCloseWrite, void(const string &filePath)); + MOCK_METHOD1(IsInBlackList, void(const string &filePath)); +}; + +class DiskMonitorTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + shared_ptr diskMonitor_; + int32_t userId = 100; + +}; + +void DiskMonitorTest::SetUpTestCase(void) { + GTEST_LOG_(INFO) << "SetUpTestCase"; + diskMonitor_ = make_shared(); +} + +void DiskMonitorTest::TearDownTestCase(void) { + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DiskMonitorTest::SetUp(void) { + +} + +void DiskMonitorTest::TearDown(void) { + +} + +/** +@tc.name: GetInstanceTest001 +@tc.desc: Verify the GetInstance function returns singleton instance +@tc.type: FUNC +*/ +HWTEST_F(DiskMonitorTest, GetInstanceTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetInstanceTest001 Begin"; + try { + DiskMonitor& instance = DiskMonitor::GetInstance(); + DiskMonitor& instance2 = DiskMonitor::GetInstance(); + EXPECT_EQ(&instance, &instance2); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetInstanceTest001 Error"; + } + GTEST_LOG_(INFO) << "GetInstanceTest001 End"; +} + +/** + * @tc.name: StartMonitorTest001 + * @tc.desc: Verify StartMonitor returns true when InitFanotify succeeds + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, StartMonitorTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StartMonitorTest001 Begin"; + try { + DiskMonitorMock mockMonitor; + + EXPECT_CALL(mockMonitor, InitFanotify()).WillOnce(Return(true)); + EXPECT_CALL(mockMonitor, InitInner(userId)).Times(1); + EXPECT_CALL(mockMonitor, CollectEvents()).Times(AtLeast(0)); + + bool ret = mockMonitor.StartMonitor(userId); + + EXPECT_TRUE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "StartMonitorTest001 Error"; + } + GTEST_LOG_(INFO) << "StartMonitorTest001 End"; +} + +/** + * @tc.name: StartMonitorTest002 + * @tc.desc: Verify StartMonitor returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, StartMonitorTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StartMonitorTest002 Begin"; + try { + DiskMonitorMock mockMonitor; + + EXPECT_CALL(mockMonitor, InitFanotify()).WillOnce(Return(false)); + EXPECT_CALL(mockMonitor, InitInner(_)).Times(0); + EXPECT_CALL(mockMonitor, CollectEvents()).Times(0); + + bool ret = mockMonitor.StartMonitor(userId); + + EXPECT_FALSE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "StartMonitorTest002 Error"; + } + GTEST_LOG_(INFO) << "StartMonitorTest002 End"; +} + +/** + * @tc.name: StopMonitorTest001 + * @tc.desc: Verify StopMonitor returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, StopMonitorTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StopMonitorTest001 Begin"; + try { + DiskMonitor Monitor; + Monitor.StopMonitor(); + + EXPECT_EQ(Monitor.userId_, -1); + EXPECT_EQ(Monitor.isRunning_, false); + EXPECT_EQ(Monitor.fanotifyFd_, -1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "StopMonitorTest001 Error"; + } + GTEST_LOG_(INFO) << "StopMonitorTest001 End"; +} + +/** + * @tc.name: InitInnerTest001 + * @tc.desc: Verify InitInner returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, InitInnerTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "InitInnerTest001 Begin"; + try { + DiskMonitor Monitor; + Monitor.InitInner(userId); + + EXPECT_EQ(Monitor.userId_, userId); + EXPECT_EQ(Monitor.isRunning_, true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "InitInnerTest001 Error"; + } + GTEST_LOG_(INFO) << "InitInnerTest001 End"; +} + +/** + * @tc.name: CollectEventsTest001 + * @tc.desc: Verify CollectEvents returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, CollectEventsTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CollectEventsTest001 Begin"; + try { + DiskMonitor Monitor; + Monitor.isRunning_ = false; + + Monitor.CollectEvents(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CollectEventsTest001 Error"; + } + GTEST_LOG_(INFO) << "CollectEventsTest001 End"; +} + +/** + * @tc.name: EventProcessTest001 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest001 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CREATE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCreate(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest001 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest001 End"; +} + +/** + * @tc.name: EventProcessTest002 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest002 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CREATE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCreate(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest002 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest002 End"; +} + +/** + * @tc.name: EventProcessTest003 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest003 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_DELETE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleDelete(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest003 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest003 End"; +} + +/** + * @tc.name: EventProcessTest004 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest004 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_DELETE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleDelete(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest004 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest004 End"; +} + +/** + * @tc.name: EventProcessTest005 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest005 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_FROM; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveFrom(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest005 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest005 End"; +} + +/** + * @tc.name: EventProcessTest006 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest006, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest006 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_FROM; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveFrom(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest006 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest006 End"; +} + +/** + * @tc.name: EventProcessTest007 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest007, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest007 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_TO; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveTo(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest007 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest007 End"; +} + +/** + * @tc.name: EventProcessTest008 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest008, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest008 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_TO; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveTo(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest008 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest008 End"; +} + +/** + * @tc.name: EventProcessTest009 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest009, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest009 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CLOSE_WRITE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCloseWrite(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest009 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest009 End"; +} + +/** + * @tc.name: EventProcessTest0010 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest0010, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest0010 Begin"; + try { + DiskMonitor Monitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CLOSE_WRITE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCloseWrite(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + Monitor.EventProcess(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest0010 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest0010 End"; +} + +/** + * @tc.name: IsInBlackListTest001 + * @tc.desc: Verify the IsInBlackList function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, IsInBlackListTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IsInBlackListTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + bool res = diskMonitor_->IsInBlackList(path); + EXPECT_TRUE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IsInBlackListTest001 Error"; + } + GTEST_LOG_(INFO) << "IsInBlackListTest001 End"; +} + +/** + * @tc.name: IsInBlackListTest002 + * @tc.desc: Verify the IsInBlackList function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, IsInBlackListTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IsInBlackListTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"a", "b"}; + bool res = diskMonitor_->IsInBlackList(path); + EXPECT_TRUE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IsInBlackListTest002 Error"; + } + GTEST_LOG_(INFO) << "IsInBlackListTest002 End"; +} + +/** + * @tc.name: IsInBlackListTest003 + * @tc.desc: Verify the IsInBlackList function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, IsInBlackListTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IsInBlackListTest003 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + bool res = diskMonitor_->IsInBlackList(path); + EXPECT_FALSE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IsInBlackListTest003 Error"; + } + GTEST_LOG_(INFO) << "IsInBlackListTest003 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest001 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, INVALID_SYNC_FOLDER); + EXPECT_FALSE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest001 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest001 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest002 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "a"}}); + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, 1); + EXPECT_FALSE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest002 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest002 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest003 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest003 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, 1); + EXPECT_TRUE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest003 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest003 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest004 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest004 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "b"}}); + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, INVALID_SYNC_FOLDER); + EXPECT_FALSE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest004 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest004 End"; +} +} \ No newline at end of file diff --git a/test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp b/test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp new file mode 100644 index 000000000..f945952e7 --- /dev/null +++ b/test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp @@ -0,0 +1,203 @@ +/* + * 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 +#include + +#include "disk_notifier.h" +#include "cloud_disk_service_syncfolder.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement::CloudDiskService { +namespace Test { +using namespace testing::ext; +using namespace std; + +class DiskNotifierTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DiskNotifierTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void DiskNotifierTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DiskNotifierTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void DiskNotifierTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: PostEventTest001 + * @tc.desc: Verify the PostEvent function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, PostEventTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "PostEventTest001 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + DiskNotifier& notifier = DiskNotifier::GetInstance(); + auto eventInfo = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + notifier.PostEvent(eventInfo); + EXPECT_EQ(notifier.eventList_.szie(), 1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "PostEventTest001 failed"; + } + GTEST_LOG_(INFO) << "PostEventTest001 end"; +} + +/** + * @tc.name: PostEventTest002 + * @tc.desc: Verify the PostEvent function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, PostEventTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "PostEventTest002 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + auto eventInfo_time1 = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + auto eventInfo_time2 = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.PostEvent(eventInfo_time1); + notifier.PostEvent(eventInfo_time2); + EXPECT_EQ(notifier.eventList_.szie(), 1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "PostEventTest002 failed"; + } + GTEST_LOG_(INFO) << "PostEventTest002 end"; +} + +/** + * @tc.name: NotifyEventFullTest001 + * @tc.desc: Verify the NotifyEventFull function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventFullTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventFullTest001 start"; + try { + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.NotifyEventFull(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventFullTest001 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventFullTest001 end"; +} + +/** + * @tc.name: NotifyEventFullTest002 + * @tc.desc: Verify the NotifyEventFull function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventFullTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventFullTest002 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + auto eventInfo = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.PostEvent(eventInfo); + notifier.NotifyEventFull(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventFullTest002 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventFullTest002 end"; +} + +/** + * @tc.name: NotifyEventAllTest001 + * @tc.desc: Verify the NotifyEventAll function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventAllTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventAllTest001 start"; + try { + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.NotifyEventAll(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventAllTest001 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventAllTest001 end"; +} + +/** + * @tc.name: NotifyEventAllTest002 + * @tc.desc: Verify the NotifyEventAll function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventAllTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventAllTest002 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + auto eventInfo = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.PostEvent(eventInfo); + notifier.NotifyEventAll(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventAllTest002 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventAllTest002 end"; +} +} // namespace Test +} // namespace FileManagement::CloudDiskService +} // namespace OHOS \ No newline at end of file diff --git a/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp new file mode 100644 index 000000000..1eee74125 --- /dev/null +++ b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp @@ -0,0 +1,194 @@ +/* + * 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 +#include + +#include "disk_utils.h" + +namespace OHOS::FileManagement::CloudDiskService::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DiskUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + shared_ptr diskUtils_; +}; + +void DiskUtilsTest::SetUpTestCase(void) { + GTEST_LOG_(INFO) << "SetUpTestCase"; + diskUtils_ = make_shared(); +} + +void DiskUtilsTest::TearDownTestCase(void) { + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DiskUtilsTest::SetUp(void) { + +} + +void DiskUtilsTest::TearDown(void) { + +} + +/** + * @tc.name: IExtractFileNameTest001 + * @tc.desc: Verify the ExtractFileName function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, IExtractFileNameTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IExtractFileNameTest001 Begin"; + try { + int type = FAN_EVENT_INFO_TYPE_FID; + string fileName = "fileName"; + struct file_handle file_handle_test; + bool res = diskUtils_->ExtractFileName(type, fileName, &file_handle_test); + EXPECT_TRUE(res); + EXPECT_EQ(fileName, ""); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IExtractFileNameTest001 Error"; + } + GTEST_LOG_(INFO) << "IExtractFileNameTest001 End"; +} + +/** + * @tc.name: IExtractFileNameTest002 + * @tc.desc: Verify the ExtractFileName function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, IExtractFileNameTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IExtractFileNameTest002 Begin"; + try { + int type = FAN_EVENT_INFO_TYPE_DFID_NAME; + string fileName = "fileName"; + struct file_handle file_handle_test; + file_handle_test.f_handle = "abc\0"; + file_handle_test.handle_bytes = 1; + bool res = diskUtils_->ExtractFileName(type, fileName, &file_handle_test); + EXPECT_TRUE(res); + EXPECT_EQ(fileName, "bc"); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IExtractFileNameTest002 Error"; + } + GTEST_LOG_(INFO) << "IExtractFileNameTest002 End"; +} + +/** + * @tc.name: IExtractFileNameTest003 + * @tc.desc: Verify the ExtractFileName function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, IExtractFileNameTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IExtractFileNameTest003 Begin"; + try { + int type = 4; + string fileName = "fileName"; + struct file_handle file_handle_test; + bool res = diskUtils_->ExtractFileName(type, fileName, &file_handle_test); + EXPECT_FALSE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IExtractFileNameTest003 Error"; + } + GTEST_LOG_(INFO) << "IExtractFileNameTest003 End"; +} + +/** + * @tc.name: CloseFdTest001 + * @tc.desc: Verify the CloseFd function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseFdTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseFdTest001 Begin"; + try { + int fd = 0; + diskUtils_->CloseFdTest001(fd); + EXPECT_EQ(fd, -1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseFdTest001 Error"; + } + GTEST_LOG_(INFO) << "CloseFdTest001 End"; +} + +/** + * @tc.name: CloseFdTest002 + * @tc.desc: Verify the CloseFd function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseFdTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseFdTest002 Begin"; + try { + int fd = -1; + diskUtils_->CloseFdTest001(fd); + EXPECT_EQ(fd, -1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseFdTest002 Error"; + } + GTEST_LOG_(INFO) << "CloseFdTest002 End"; +} + +/** + * @tc.name: CloseDirTest001 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseDirTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseDirTest001 Begin"; + try { + DIR* dir = opendir("/data"); + diskUtils_->CloseDir(dir); + EXPECT_EQ(dir, nullptr); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseDirTest001 Error"; + } + GTEST_LOG_(INFO) << "CloseDirTest001 End"; +} + +/** + * @tc.name: CloseDirTest002 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseDirTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseDirTest002 Begin"; + try { + DIR* dir = nullptr; + diskUtils_->CloseDir(dir); + EXPECT_EQ(dir, nullptr); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseDirTest002 Error"; + } + GTEST_LOG_(INFO) << "CloseDirTest002 End"; +} +} \ No newline at end of file diff --git a/utils/system/include/dfsu_access_token_helper.h b/utils/system/include/dfsu_access_token_helper.h index 3d7398930..f5697e320 100644 --- a/utils/system/include/dfsu_access_token_helper.h +++ b/utils/system/include/dfsu_access_token_helper.h @@ -19,6 +19,7 @@ #include namespace OHOS::FileManagement { +inline const std::string PERM_CLOUD_DISK_SERVICE = "ohos.permission.ACCESS_CLOUD_DISK_INFO"; inline const std::string PERM_CLOUD_SYNC_MANAGER = "ohos.permission.CLOUDFILE_SYNC_MANAGER"; inline const std::string PERM_CLOUD_SYNC = "ohos.permission.CLOUDFILE_SYNC"; inline const std::string PERM_AUTH_URI = "ohos.permission.PROXY_AUTHORIZATION_URI"; -- Gitee From 457a7e577c2130b67370840c21c8455cfebdfb36 Mon Sep 17 00:00:00 2001 From: fuletian Date: Sat, 6 Sep 2025 10:44:07 +0800 Subject: [PATCH 02/13] add tdd --- BUILD.gn | 13 + bundle.json | 67 +- distributedfile.gni | 1 + .../cloud_disk_service_callback_client.h | 68 ++ .../cloud_disk_service_callback_stub.h | 41 ++ .../include/cloud_disk_service_manager_impl.h | 49 ++ .../include/service_proxy.h | 45 ++ .../src/cloud_disk_common.cpp | 330 ++++++++++ .../cloud_disk_service_callback_client.cpp | 19 + .../src/cloud_disk_service_callback_stub.cpp | 118 ++++ .../src/cloud_disk_service_manager.cpp | 24 + .../src/cloud_disk_service_manager_impl.cpp | 208 ++++++ .../src/cloud_disk_service_task_manager.cpp | 152 +++++ .../src/service_proxy.cpp | 114 ++++ .../clouddiskservice_kit_inner/BUILD.gn | 101 +++ .../cloud_disk_common.h | 111 ++++ .../cloud_disk_service_callback.h | 32 + .../cloud_disk_service_manager.h | 39 ++ .../cloud_disk_service_task_manager.h | 71 +++ .../i_cloud_disk_service_callback.h | 38 ++ .../svc_death_recipient.h | 41 ++ services/5207.json | 12 + services/BUILD.gn | 12 + services/clouddiskservice.cfg | 12 + services/clouddiskservice/BUILD.gn | 134 ++++ .../clouddiskservice/ICloudDiskService.idl | 28 + .../ipc/include/account_status_listener.h | 45 ++ .../ipc/include/cloud_disk_service.h | 73 +++ .../cloud_disk_service_callback_manager.h | 45 ++ .../cloud_disk_service_callback_proxy.h | 38 ++ .../ipc/include/cloud_disk_sync_folder.h | 47 ++ .../ipc/src/account_status_listener.cpp | 85 +++ .../ipc/src/cloud_disk_service.cpp | 403 ++++++++++++ .../cloud_disk_service_callback_manager.cpp | 104 +++ .../src/cloud_disk_service_callback_proxy.cpp | 137 ++++ .../ipc/src/cloud_disk_sync_folder.cpp | 61 ++ .../monitor/include/disk_monitor.h | 63 ++ .../monitor/include/disk_notifier.h | 39 ++ .../monitor/include/disk_types.h | 65 ++ .../monitor/include/disk_utils.h | 33 + .../monitor/src/disk_monitor.cpp | 302 +++++++++ .../monitor/src/disk_notifier.cpp | 89 +++ .../monitor/src/disk_utils.cpp | 72 +++ .../clouddiskservice/seccomp_policy/BUILD.gn | 28 + .../clouddiskservice.seccomp.policy | 341 ++++++++++ .../monitor/disk_monitor_test.cpp | 603 ++++++++++++++++++ .../monitor/disk_notifier_test.cpp | 203 ++++++ .../monitor/disk_utils_test.cpp | 194 ++++++ .../system/include/dfsu_access_token_helper.h | 1 + 49 files changed, 4926 insertions(+), 25 deletions(-) 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 services/5207.json create mode 100644 services/clouddiskservice.cfg create mode 100644 services/clouddiskservice/BUILD.gn create mode 100644 services/clouddiskservice/ICloudDiskService.idl create mode 100644 services/clouddiskservice/ipc/include/account_status_listener.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_service.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h create mode 100644 services/clouddiskservice/ipc/include/cloud_disk_sync_folder.h create mode 100644 services/clouddiskservice/ipc/src/account_status_listener.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_service.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp create mode 100644 services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp create mode 100644 services/clouddiskservice/monitor/include/disk_monitor.h create mode 100644 services/clouddiskservice/monitor/include/disk_notifier.h create mode 100644 services/clouddiskservice/monitor/include/disk_types.h create mode 100644 services/clouddiskservice/monitor/include/disk_utils.h create mode 100644 services/clouddiskservice/monitor/src/disk_monitor.cpp create mode 100644 services/clouddiskservice/monitor/src/disk_notifier.cpp create mode 100644 services/clouddiskservice/monitor/src/disk_utils.cpp create mode 100644 services/clouddiskservice/seccomp_policy/BUILD.gn create mode 100644 services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy create mode 100644 test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp create mode 100644 test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp create mode 100644 test/unittests/clouddiskservice/monitor/disk_utils_test.cpp diff --git a/BUILD.gn b/BUILD.gn index e77869cad..117fb2d47 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -33,6 +33,14 @@ group("services_target") { if (dfs_service_feature_enable_cloud_adapter) { deps += [ "${services_path}:cloudfiledaemon_etc" ] } + if (dfs_service_feature_enable_cloud_disk) { + deps += [ + "${services_path}:clouddiskservice_sa_profile", + "${services_path}/clouddiskservice:clouddiskservice_sa", + "${services_path}:clouddiskservice_etc", + "${services_path}/clouddiskservice/seccomp_policy:disk_monitor_seccomp_filter", + ] + } } group("cloudsync_kit_inner_target") { @@ -50,6 +58,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..5c36e9712 100644 --- a/bundle.json +++ b/bundle.json @@ -17,12 +17,13 @@ "syscap": [ "SystemCapability.FileManagement.DistributedFileService.CloudSync.Core", "SystemCapability.FileManagement.DistributedFileService.CloudSyncManager" - ], - "features": [ - "dfs_service_feature_enable_cloud_adapter", - "dfs_service_feature_enable_dist_file_daemon" - ], - "adapted_system_type": [ + ], + "features": [ + "dfs_service_feature_enable_cloud_adapter", + "dfs_service_feature_enable_cloud_disk", + "dfs_service_feature_enable_dist_file_daemon" + ], + "adapted_system_type": [ "small", "standard" ], @@ -69,22 +70,24 @@ "samgr", "selinux_adapter", "thermal_manager", - "os_account", - "power_manager", - "libfuse", - "zlib" - ], - "third_party": [] - }, + "os_account", + "power_manager", + "libfuse", + "zlib", + "user_file_service" + ], + "third_party": [] + }, "build": { "group_type": { "base_group": [], - "fwk_group": [], - "service_group": [ - "//foundation/filemanagement/dfs_service:services_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", + "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", @@ -105,12 +108,26 @@ "cloud_sync_constants.h", "cloud_sync_common.h" ], - "header_base": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/cloudsync_kit_inner" - } - }, - { - "name": "//foundation/filemanagement/dfs_service/interfaces/inner_api/native/cloudsync_kit_inner:cloudsync_asset_kit_inner", - "header": { + "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": { "header_files": [ "cloud_sync_asset_manager.h" ], diff --git a/distributedfile.gni b/distributedfile.gni index 2e8d8a0c1..3dafabb3b 100644 --- a/distributedfile.gni +++ b/distributedfile.gni @@ -37,6 +37,7 @@ declare_args() { cloudsync_service_power = false } dfs_service_feature_enable_cloud_adapter = false + dfs_service_feature_enable_cloud_disk = true dfs_service_feature_enable_dist_file_daemon = true if (defined(global_parts_info) && 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..2149c09e1 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_client.h @@ -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. + */ + +#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) {} + + void OnChangeData(std::vector& changeData) override { + if (callback_ == nullptr) { + LOGE("callback_ is nullptr"); + return; + } + callback_->OnChangeData(changeData); + } + + void OnReturnSetFailedList(std::vector& failedList) override { + if (callback_ == nullptr) { + LOGE("callback_ is nullptr"); + return; + } + callback_->OnReturnSetFailedList(failedList); + } + + void OnReturnGetResult(std::vector& resultList) override { + if (callback_ == nullptr) { + LOGE("callback_ is nullptr"); + return; + } + callback_->OnReturnGetResult(resultList); + } +private: + std::shared_ptr callback_{ nullptr }; +}; + +// class CloudDiskServiceCallbackImpl final : public CloudDiskServiceCallback { +// public: +// void OnChangeData(std::vector& changeData) override { +// LOGE("start in client"); +// } + +// void OnReturnSetFailedList(vector& failedList) override { +// LOGE("start in client"); +// } +// }; +} // 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..00ee31581 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_callback_stub.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_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); + int32_t HandleOnReturnSetFailedList(MessageParcel &data, MessageParcel &reply); + int32_t HandleOnReturnGetResult(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..2b90c4ace --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/include/cloud_disk_service_manager_impl.h @@ -0,0 +1,49 @@ +/* + * 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 RegisterSyncFolderChanges(const std::string& syncFolder, const std::shared_ptr callback) override; + int32_t UnregisterSyncFolderChanges(const std::string& syncFolder) override; + int32_t GetSyncFolderChanges(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) override; + int32_t SetFileSyncStates(const std::string& syncFolder, const std::vector& fileSyncStates, const std::shared_ptr callback) override; + int32_t GetFileSyncStates(const std::string& syncFolder, const std::vector& pathArray, const std::shared_ptr callback) override; + int32_t RegisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) override; + int32_t UnregisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) 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..23b900812 --- /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..fd4d47481 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp @@ -0,0 +1,330 @@ +/* + * 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 { + +// CloudDiskCommon &CloudDiskCommon::GetInstance() +// { +// static CloudDiskCommon instance; +// return instance; +// } + + +bool FileSyncState::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(path)) { + LOGE("failed to write path"); + return false; + } + + if (!parcel.WriteInt32(static_cast(state))) { + LOGE("failed to write state"); + return false; + } + + return true; +} + +FileSyncState *FileSyncState::Unmarshalling(Parcel &parcel) +{ + FileSyncState *info = new (std::nothrow) FileSyncState(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool FileSyncState::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(path)) { + LOGE("failed to write path"); + return false; + } + + int32_t readState = 0; + if (!parcel.ReadInt32(readState)) { + LOGE("failed to write state"); + return false; + } + state = static_cast(readState); + + return true; +} + + +bool ChangeData::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteUint64(updateSequenceNumber)) { + LOGE("failed to write updateSequenceNumber"); + return false; + } + + if (!parcel.WriteString(fileId)) { + LOGE("failed to write fileId"); + return false; + } + + if (!parcel.WriteString(parentFileId)) { + LOGE("failed to write parentFileId"); + return false; + } + + if (!parcel.WriteString(relativePath)) { + LOGE("failed to write relativePath"); + return false; + } + + if (!parcel.WriteInt32(static_cast(operationType))) { + LOGE("failed to write operationType"); + return false; + } + + if (!parcel.WriteUint64(size)) { + LOGE("failed to write size"); + return false; + } + + if (!parcel.WriteUint64(mtime)) { + LOGE("failed to write mtime"); + return false; + } + + if (!parcel.WriteUint64(timeStamp)) { + LOGE("failed to write timeStamp"); + 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.ReadUint64(updateSequenceNumber)) { + LOGE("failed to read updateSequenceNumber"); + return false; + } + + if (!parcel.ReadString(fileId)) { + LOGE("failed to read fileId"); + return false; + } + + if (!parcel.ReadString(parentFileId)) { + LOGE("failed to read parentFileId"); + return false; + } + + if (!parcel.ReadString(relativePath)) { + LOGE("failed to read relativePath"); + return false; + } + + int32_t readType = 0; + if (!parcel.ReadInt32(readType)) { + LOGE("failed to write operationType"); + return false; + } + operationType = static_cast(readType); + + if (!parcel.ReadUint64(size)) { + LOGE("failed to read size"); + return false; + } + + if (!parcel.ReadUint64(mtime)) { + LOGE("failed to read mtime"); + return false; + } + + if (!parcel.ReadUint64(timeStamp)) { + LOGE("failed to read timeStamp"); + return false; + } + + return true; +} + +bool ChangesResult::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteUint64(nextUsn)) { + LOGE("failed to write nextUsn"); + return false; + } + + if (!parcel.WriteInt32(static_cast(isEof))) { + LOGE("failed to write isEof"); + return false; + } + + if (!parcel.WriteInt32(static_cast(changesData.size()))) { + LOGE("failed to write changeData"); + return false; + } + + for(auto& item : changesData) { + item.Marshalling(parcel); + } + + return true; +} + +ChangesResult *ChangesResult::Unmarshalling(Parcel &parcel) +{ + ChangesResult *info = new (std::nothrow) ChangesResult(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool ChangesResult::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadUint64(nextUsn)) { + LOGE("failed to read nextUSN"); + return false; + } + + int32_t readIsEof = 0; + if (!parcel.ReadInt32(readIsEof)) { + LOGE("failed to read isEof"); + return false; + } + isEof = readIsEof; + + int32_t size = 0; + if (!parcel.ReadInt32(size)) { + LOGE("failed to read changeData size"); + return false; + } + for(int32_t i = 0; i < size; ++i) { + ChangeData changeData; + changeData.ReadFromParcel(parcel); + changesData.push_back(changeData); + } + + return true; +} + +bool FailedList::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(path)) { + LOGE("failed to write path"); + return false; + } + + if (!parcel.WriteInt32(static_cast(error))) { + LOGE("failed to write error"); + return false; + } + + return true; +} + +FailedList *FailedList::Unmarshalling(Parcel &parcel) +{ + FailedList *info = new (std::nothrow) FailedList(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool FailedList::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(path)) { + LOGE("failed to read path"); + return false; + } + + int32_t readError = 0; + if (!parcel.ReadInt32(readError)) { + LOGE("failed to write errno"); + return false; + } + error = static_cast(readError); + + return true; +} + +bool ResultList::Marshalling(Parcel &parcel) const +{ + + if (!parcel.WriteInt32(static_cast(isSuccess))) { + LOGE("failed to write isSuccess"); + return false; + } + + if (!parcel.WriteInt32(static_cast(state))) { + LOGE("failed to write state"); + return false; + } + + return true; +} + +ResultList *ResultList::Unmarshalling(Parcel &parcel) +{ + ResultList *info = new (std::nothrow) ResultList(); + if ((info != nullptr) && (!info->ReadFromParcel(parcel))) { + LOGW("read from parcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool ResultList::ReadFromParcel(Parcel &parcel) +{ + int32_t readIsSuccess = 0; + if (!parcel.ReadInt32(readIsSuccess)) { + LOGE("failed to write isSuccess"); + return false; + } + isSuccess= readIsSuccess; + + int32_t readState = 0; + if (!parcel.ReadInt32(readState)) { + LOGE("failed to write state"); + return false; + } + state = static_cast(readState); + + 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..e4f533e7b --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_callback_stub.cpp @@ -0,0 +1,118 @@ +/* + * 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_CHANGE_DATA] = [this](MessageParcel &data, MessageParcel &reply) { + return this->HandleOnChangeData(data, reply); + }; + opToInterfaceMap_[SERVICE_CMD_ON_RETURN_SET_FAILED_LIST] = [this](MessageParcel &data, MessageParcel &reply) { + return this->HandleOnReturnSetFailedList(data, reply); + }; + opToInterfaceMap_[SERVICE_CMD_ON_RETURN_GET_RESULT] = [this](MessageParcel &data, MessageParcel &reply) { + return this->HandleOnReturnGetResult(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) +{ + std::vector changesData; + + auto size = data.ReadInt32(); + if (size > static_cast(VECTOR_MAX_SIZE)) { + return ERR_INVALID_DATA; + } + for (int i = 0; i < size; ++i) { + std::unique_ptr value(data.ReadParcelable()); + if(!value) { + LOGE("object of ChangeData is nullptr"); + return E_INVAL_ARG; + } + changesData.push_back(*value); + } + + OnChangeData(changesData); + LOGI("HandleOnChangeData end"); + return E_OK; +} + +int32_t CloudDiskServiceCallbackStub::HandleOnReturnSetFailedList(MessageParcel &data, MessageParcel &reply) +{ + std::vector failedList; + + auto size = data.ReadInt32(); + if (size > static_cast(VECTOR_MAX_SIZE)) { + return ERR_INVALID_DATA; + } + for (int i = 0; i < size; ++i) { + std::unique_ptr value(data.ReadParcelable()); + if(!value) { + LOGE("object of failedList is nullptr"); + return E_INVAL_ARG; + } + failedList.push_back(*value); + } + + OnReturnSetFailedList(failedList); + LOGI("HandleOnReturnSetFailedList end"); + return E_OK; +} + +int32_t CloudDiskServiceCallbackStub::HandleOnReturnGetResult(MessageParcel &data, MessageParcel &reply) +{ + std::vector resultList; + + auto size = data.ReadInt32(); + if (size > static_cast(VECTOR_MAX_SIZE)) { + return ERR_INVALID_DATA; + } + for (int i = 0; i < size; ++i) { + std::unique_ptr value(data.ReadParcelable()); + if(!value) { + LOGE("object of resultList is nullptr"); + return E_INVAL_ARG; + } + resultList.push_back(*value); + } + + OnReturnGetResult(resultList); + LOGI("HandleOnReturnGetResult end"); + 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..1f9cb668f --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_service_manager_impl.cpp @@ -0,0 +1,208 @@ +/* + * 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 "dfsu_access_token_helper.h" +#include "cloud_disk_service_callback_client.h" +#include "cloud_file_utils.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; +} + +int32_t CloudDiskServiceManagerImpl::RegisterSyncFolderChanges(const std::string& syncFolder, + const std::shared_ptr callback) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + if (!callback) { + LOGE("callback is null"); + return E_INVAL_ARG; + } + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + auto ret = serviceProxy->RegisterSyncFolderChangesInner(syncFolder, + sptr(new (std::nothrow) CloudDiskServiceCallbackClient(callback))); + { + unique_lock lock(callbackMutex_); + callback_ = callback; + } + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("RegisterSyncFolderChanges ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::UnregisterSyncFolderChanges(const std::string& syncFolder) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->UnregisterSyncFolderChangesInner(syncFolder); + { + unique_lock lock(callbackMutex_); + callback_ = nullptr; + } + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("UnregisterSyncFolderChanges ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::GetSyncFolderChanges(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->GetSyncFolderChangesInner(syncFolder, count, startUsn, changesResult); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("GetSyncFolderChangesInner ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::SetFileSyncStates(const std::string& syncFolder, const std::vector& fileSyncStates, + const std::shared_ptr callback) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("start SetXattr in impl"); + + if (!callback) { + LOGE("callback is null"); + return E_INVAL_ARG; + } + + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->SetFileSyncStatesInner(syncFolder, fileSyncStates, sptr(new (std::nothrow) CloudDiskServiceCallbackClient(callback))); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("SetFileSyncState, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::GetFileSyncStates(const std::string& syncFolder, const std::vector& pathArray, const std::shared_ptr callback) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("start GetXattr in impl"); + + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->GetFileSyncStatesInner(syncFolder, pathArray, sptr(new (std::nothrow) CloudDiskServiceCallbackClient(callback))); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("GetFileSyncState, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::RegisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + LOGI("start RegisterSyncFolder in impl"); + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->RegisterSyncFolderInner(userId, bundleName, path); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("RegisterSyncFolder, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +int32_t CloudDiskServiceManagerImpl::UnregisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + LOGI("start UnregisterSyncFolder in impl"); + auto serviceProxy = ServiceProxy::GetInstance(); + if (!serviceProxy) { + LOGE("proxy is null"); + return E_SA_LOAD_FAILED; + } + + auto ret = serviceProxy->UnregisterSyncFolderInner(userId, bundleName, path); + SetDeathRecipient(serviceProxy->AsObject()); + LOGI("UnregisterSyncFolder, ret %{public}d", ret); + return ret; +#else + return 0; +#endif +} + +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(); + } + } +} + +} // 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..145c3a0b0 --- /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..9fa81d389 --- /dev/null +++ b/frameworks/native/clouddiskservice_kit_inner/src/service_proxy.cpp @@ -0,0 +1,114 @@ +/* + * 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; + } + + auto object = samgr->CheckSystemAbility(FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID); + if (object == nullptr) { + LOGE("CloudDiskService::Connect object == nullptr"); + return nullptr; + } + + serviceProxy_ = iface_cast(object); + if (serviceProxy_ == nullptr) { + LOGE("CloudDiskService::Connect service == 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..8094983b2 --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/BUILD.gn @@ -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. + +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\"", + ] + + if (dfs_service_feature_enable_cloud_disk) { + defines += [ "SUPPORT_CLOUD_DISK_SERVICE "] + } + + 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", + ] + + 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..454ef967e --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_common.h @@ -0,0 +1,111 @@ +/* + * 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 { + +/* +When adding new enumeration values, pay attention to the maximum enumeration value judgment of the getxattr method in clouddiskservice.cpp +*/ +enum class SyncState { + IDLE = 0, + SYNCING, + SYNC_SUCCESSED, + SYNC_FAILED, + SYNC_CANCELED, + SYNC_CONFLICTED, +}; + +enum class OperationType : uint8_t { + NONE = 0, + CREATE, + DELETE, + MOVE_FROM, + MOVE_TO, + CLOSE_WRITE, + SYNC_FOLDER_INVALID, + OPERATION_MAX, +}; + +struct FileSyncState : public Parcelable{ + std::string path; + SyncState state; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static FileSyncState *Unmarshalling(Parcel &parcel); +}; + +struct ChangeData : public Parcelable { + uint64_t updateSequenceNumber; + std::string fileId; + std::string parentFileId; + std::string relativePath; + OperationType operationType; + uint64_t size; + uint64_t mtime; + uint64_t timeStamp; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static ChangeData *Unmarshalling(Parcel &parcel); +}; + +struct ChangesResult : public Parcelable { + uint64_t nextUsn; + bool isEof; + std::vector changesData; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static ChangesResult *Unmarshalling(Parcel &parcel); +}; + +enum class ErrorReason { + INVALID_ARGUMENT = 0, + NO_SUCH_FILE, + NO_SPACE_LEFT, + OUT_OF_RANGE, +}; + +struct FailedList : public Parcelable { + std::string path; + ErrorReason error; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static FailedList *Unmarshalling(Parcel &parcel); +}; + +struct ResultList : public FailedList { + bool isSuccess; + SyncState state; + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static ResultList *Unmarshalling(Parcel &parcel); +}; + +#define RETURN_ON_ERR(ret) \ + do { \ + int32_t res = ret; \ + if ((res) != E_OK) { \ + return res; \ + } \ + } while (0) +} // 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..254134a9d --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_callback.h @@ -0,0 +1,32 @@ +/* + * 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 void OnChangeData(std::vector &changeData) = 0; + virtual void OnReturnSetFailedList(std::vector &FailedList) = 0; + virtual void OnReturnGetResult(std::vector &resultList) = 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..c7cb36bcb --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/cloud_disk_service_manager.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_MANAGER_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_MANAGER_H + +#include + +#include "cloud_disk_service_callback.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceManager { +public: + static CloudDiskServiceManager &GetInstance(); + + virtual int32_t RegisterSyncFolderChanges(const std::string& syncFolder, + const std::shared_ptr callback) = 0; + virtual int32_t UnregisterSyncFolderChanges(const std::string& syncFolder) = 0; + virtual int32_t GetSyncFolderChanges(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) = 0; + virtual int32_t SetFileSyncStates(const std::string& syncFolder, const std::vector& fileSyncStates, const std::shared_ptr callback) = 0; + virtual int32_t GetFileSyncStates(const std::string& syncFolder, const std::vector& pathArray, const std::shared_ptr callback) = 0; + virtual int32_t RegisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) = 0; + virtual int32_t UnregisterSyncFolder(int32_t userId, const std::string& bundleName, const std::string& path) = 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..97f4aa30c --- /dev/null +++ b/interfaces/inner_api/native/clouddiskservice_kit_inner/i_cloud_disk_service_callback.h @@ -0,0 +1,38 @@ +/* + * 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_CHANGE_DATA = 0, + SERVICE_CMD_ON_RETURN_SET_FAILED_LIST = 1, + SERVICE_CMD_ON_RETURN_GET_RESULT = 2, + }; + + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Filemanagement.Dfs.ICloudDiskServiceCallback") + +protected : + const int VECTOR_MAX_SIZE = 102400; +}; +} // 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/services/5207.json b/services/5207.json new file mode 100644 index 000000000..62f22ff23 --- /dev/null +++ b/services/5207.json @@ -0,0 +1,12 @@ +{ + "process": "clouddiskservice", + "systemability": [ + { + "name": 5207, + "libpath": "libclouddiskservice_sa.z.so", + "run-on-create": true, + "distributed": false, + "dump-level": 1 + } + ] +} \ No newline at end of file diff --git a/services/BUILD.gn b/services/BUILD.gn index 0eec280de..01f49084f 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" @@ -32,6 +37,13 @@ ohos_prebuilt_etc("distributedfile_etc") { subsystem_name = "filemanagement" } +ohos_prebuilt_etc("clouddiskservice_etc") { + source = "clouddiskservice.cfg" + relative_install_dir = "init" + part_name = "dfs_service" + subsystem_name = "filemanagement" +} + ohos_prebuilt_etc("cloudfiledaemon_etc") { source = "cloudfiledaemon.cfg" relative_install_dir = "init" diff --git a/services/clouddiskservice.cfg b/services/clouddiskservice.cfg new file mode 100644 index 000000000..cb0d09c6f --- /dev/null +++ b/services/clouddiskservice.cfg @@ -0,0 +1,12 @@ +{ + "services": [ { + "name": "clouddiskservice", + "path": ["/system/bin/sa_main", "/system/profile/clouddiskservice.json"], + "uid": "6161", + "gid": ["6161", "dfs", "1006"], + "sandbox": 0, + "secon": "u:r:clouddiskservice:s0", + "caps": ["CAP_SYS_ADMIN", "CAP_DAC_READ_SEARCH"], + "apl": "system_basic" + }] +} \ No newline at end of file diff --git a/services/clouddiskservice/BUILD.gn b/services/clouddiskservice/BUILD.gn new file mode 100644 index 000000000..22851541e --- /dev/null +++ b/services/clouddiskservice/BUILD.gn @@ -0,0 +1,134 @@ +# 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 = [ + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", + ] + sub_include = [ + "${distributedfile_path}/utils/log/include", + "${innerkits_native_path}/clouddiskservice_kit_inner", + ] + configs = [] + + sequenceable_ext_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + + 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 = [ + "ipc/include", + "monitor/include", + # "${innerkits_native_path}/clouddiskservice_kit_inner", + ] + + sources = [ + "ipc/src/cloud_disk_service.cpp", + "ipc/src/cloud_disk_service_callback_manager.cpp", + "ipc/src/cloud_disk_service_callback_proxy.cpp", + "ipc/src/cloud_disk_sync_folder.cpp", + "ipc/src/account_status_listener.cpp", + "monitor/src/disk_monitor.cpp", + "monitor/src/disk_notifier.cpp", + "monitor/src/disk_utils.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.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", + ] + + if (build_seccomp) { + deps += [ "${services_path}/clouddiskservice/seccomp_policy:disk_monitor_seccomp_filter" ] + } + + external_deps = [ + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "ffrt:libffrt", + "e2fsprogs:libext2_uuid", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_single", + "samgr:samgr_proxy", + "safwk:system_ability_fwk", + "user_file_service:cloud_disk_manager_kit" + ] + + 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..a2b40a18b --- /dev/null +++ b/services/clouddiskservice/ICloudDiskService.idl @@ -0,0 +1,28 @@ +/* + * 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; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.ChangesResult; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.FileSyncState; + +interface OHOS.FileManagement.CloudDiskService.ICloudDiskService +{ + void RegisterSyncFolderChangesInner([in] String syncFolder, [in] IRemoteObject remoteobject); + void UnregisterSyncFolderChangesInner([in] String syncFolder); + ChangesResult GetSyncFolderChangesInner([in] String syncFolder, [in] unsigned long count, [in] unsigned long startUSN); + void SetFileSyncStatesInner([in] String syncFolder, [in] List fileSyncStates, [in] IRemoteObject remoteobject); + void GetFileSyncStatesInner([in] String syncFolder, [in] List pathArray, [in] IRemoteObject remoteobject); + void RegisterSyncFolderInner([in] int userId, [in] String bundleName, [in] String path); + void UnregisterSyncFolderInner([in] int userId, [in] String bundleName, [in] String path); +} diff --git a/services/clouddiskservice/ipc/include/account_status_listener.h b/services/clouddiskservice/ipc/include/account_status_listener.h new file mode 100644 index 000000000..198d513e4 --- /dev/null +++ b/services/clouddiskservice/ipc/include/account_status_listener.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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_ACCOUNT_STATUS_LISTENER_H +#define CLOUD_DISK_SERVICE_ACCOUNT_STATUS_LISTENER_H + +#include "cloud_file_utils.h" +#include "common_event_subscriber.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +class AccountStatusListener { +public: + explicit AccountStatusListener() = default; + ~AccountStatusListener(); + void Start(); + void Stop(); + +private: + std::shared_ptr commonEventSubscriber_ = nullptr; +}; + +class AccountStatusSubscriber : public EventFwk::CommonEventSubscriber { +public: + AccountStatusSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo); + ~AccountStatusSubscriber() override {} + void OnReceiveEvent(const EventFwk::CommonEventData &eventData) override; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SERVICE_ACCOUNT_STATUS_LISTENER_H \ No newline at end of file diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service.h b/services/clouddiskservice/ipc/include/cloud_disk_service.h new file mode 100644 index 000000000..f8fee675a --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service.h @@ -0,0 +1,73 @@ +/* + * 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 "account_status_listener.h" +#include "cloud_disk_service_stub.h" +#include "dfsu_access_token_helper.h" +#include "icloud_disk_service.h" +#include "i_cloud_disk_service_callback.h" +#include "iremote_stub.h" +#include "nocopyable.h" +#include "refbase.h" +#include "system_ability.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; + static CloudDiskService &GetInstance(); + + void OnStart() override; + void OnStop() override; + ErrCode RegisterSyncFolderChangesInner(const std::string& syncFolder, + const sptr& remoteObject) override; + ErrCode UnregisterSyncFolderChangesInner(const std::string& syncFolder) override; + ErrCode GetSyncFolderChangesInner(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) override; + ErrCode SetFileSyncStatesInner(const std::string& syncFolder, const std::vector& fileSyncStates, const sptr& remoteObject) override; + ErrCode GetFileSyncStatesInner(const std::string& syncFolder, const std::vector& pathArray, const sptr& remoteObject) override; + ErrCode RegisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) override; + ErrCode UnregisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) override; + + bool CheckSyncFolder(const uint32_t syncFolderIndex); + +private: + CloudDiskService(); + ServiceRunningState state_ { ServiceRunningState::STATE_NOT_START }; + static sptr instance_; + static std::mutex instanceLock_; + bool registerToService_ { false }; + std::mutex callbackMutex_; + void PublishSA(); + void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; + std::shared_ptr accountStatusListener_ = nullptr; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SERVICE_H diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h new file mode 100644 index 000000000..c50ffffc0 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.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_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 RigisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex, const sptr &callback); + void UnregisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex); + void AddCallback(const std::string bundleName, const sptr &callback); + void OnChangeData(const uint32_t syncFolderIndex, std::vector &changeData); + + struct CallbackValue { + sptr callback; + std::vector syncFolderIndexs; + }; + std::map callbackAppMap_; // map -> callback + std::map> callbackIndexMap_; + std::mutex callbackAppMutex_; + std::mutex callbackIndexMutex_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H \ No newline at end of file diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h new file mode 100644 index 000000000..fb84354f7 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h @@ -0,0 +1,38 @@ +/* + * 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_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 {} + + void OnChangeData(std::vector &changeData) override; + void OnReturnSetFailedList(std::vector &FailedList) override; + void OnReturnGetResult(std::vector &resultList) 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/ipc/include/cloud_disk_sync_folder.h b/services/clouddiskservice/ipc/include/cloud_disk_sync_folder.h new file mode 100644 index 000000000..a6bd32c75 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_sync_folder.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 CLOUD_DISK_SYNC_FOLDER_H +#define CLOUD_DISK_SYNC_FOLDER_H + +#include +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +struct SyncFolderValue { + std::string bundleName; + std::string path; +}; + +class CloudDiskSyncFolder { + +public: + static CloudDiskSyncFolder &GetInstance(); + void AddSyncFolder(const uint32_t syncFolderIndex, SyncFolderValue syncFolderValue); + void DeleteSyncFolder(const uint32_t syncFolderIndex); + int32_t GetSyncFolderSize(); + bool CheckSyncFolder(const uint32_t syncFolderIndex); + +private: + std::unordered_map syncFolderMap; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SYNC_FOLDER_H diff --git a/services/clouddiskservice/ipc/src/account_status_listener.cpp b/services/clouddiskservice/ipc/src/account_status_listener.cpp new file mode 100644 index 000000000..03cf83dcf --- /dev/null +++ b/services/clouddiskservice/ipc/src/account_status_listener.cpp @@ -0,0 +1,85 @@ +/* + * 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 "account_status_listener.h" + +#include + +#include "common_event_manager.h" +#include "common_event_support.h" +#include "cloud_disk_sync_folder.h" +#include "cloud_disk_comm.h" +#include "cloud_disk_manager.h" + +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +AccountStatusSubscriber::AccountStatusSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) + : EventFwk::CommonEventSubscriber(subscribeInfo) +{ +} + +void AccountStatusSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + auto action = eventData.GetWant().GetAction(); + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_STARTED) { + LOGI("OnStartUser!"); + + std::vector syncFolders = + OHOS::FileManagement::CloudDiskManager::GetInstance().GetAllSyncFoldersForSa(); + for (auto item : syncFolders) { + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = item.bundleName_; + syncFolderValue.path = item.uri_; + uint32_t syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(item.uri_); + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + } + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 0) { + // 启动监听 + // DiskMonitor::GetInstance().StartMonitor(DfsuAccessTokenHelper::GetUserId()); + } + } +} + +AccountStatusListener::~AccountStatusListener() +{ + Stop(); +} + +void AccountStatusListener::Start() +{ + /* subscribe Account login, logout, Package remove and Datashare ready */ + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_HWID_LOGIN); + EventFwk::CommonEventSubscribeInfo info(matchingSkills); + commonEventSubscriber_ = std::make_shared(info); + auto subRet = EventFwk::CommonEventManager::SubscribeCommonEvent(commonEventSubscriber_); + LOGI("Subscriber end, SubscribeResult = %{public}d", subRet); +} + +void AccountStatusListener::Stop() +{ + if (commonEventSubscriber_ != nullptr) { + EventFwk::CommonEventManager::UnSubscribeCommonEvent(commonEventSubscriber_); + commonEventSubscriber_ = nullptr; + } +} + +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service.cpp new file mode 100644 index 000000000..fdafe5da0 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service.cpp @@ -0,0 +1,403 @@ +/* + * 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 + +#include "cloud_disk_service_callback_manager.h" +#include "cloud_disk_service_task_manager.h" +// #include "cloud_disk_service_syncroot.h" +#include "cloud_disk_sync_folder.h" +#include "dfs_error.h" +// #include "disk_monitor.h" +#include "ffrt_inner.h" +#include "iremote_object.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; + +const int32_t GET_FILE_SYNC_MAX = 100; +constexpr const char* FILE_SYNC_STATE = "user.clouddisk.filesyncstate"; + +namespace { +} +REGISTER_SYSTEM_ABILITY_BY_ID(CloudDiskService, FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID, true); + +CloudDiskService::CloudDiskService(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate) +{ + accountStatusListener_ = make_shared(); +} + +CloudDiskService::CloudDiskService() +{ +} + +CloudDiskService &CloudDiskService::GetInstance() +{ + static CloudDiskService instance; + return instance; +} + +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()); + } + + CloudDiskServiceTaskManager::GetInstance().StartTask(); + DiskMonitor::GetInstance().StartMonitor(100); + 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"); +} + +static int32_t CheckPermissions(const string &permission, bool isSystemApp) +{ + if (!permission.empty() && !DfsuAccessTokenHelper::CheckCallerPermission(permission)) { + LOGE("permission denied"); + return E_PERMISSION_DENIED; + } + return E_OK; +} + +int32_t CloudDiskService::RegisterSyncFolderChangesInner(const std::string& syncFolder, + const sptr& remoteObject) +{ + LOGI("Begin RegisterSyncFolderChangesInner"); + LOGI("RegisterSyncFolderChangesInner start uri:%{public}s", syncFolder.c_str()); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + if (remoteObject == nullptr) { + LOGE("remoteObject is nullptr"); + return E_INVAL_ARG; + } + + std::string bundleName = ""; + int ret = DfsuAccessTokenHelper::GetCallerBundleName(bundleName); + if (ret != E_OK) { + LOGE("Get bundleName failed, ret:%{public}d", ret); + return ret; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + if (CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("SyncFolder is exist"); + return E_PARAMS_; + } + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = bundleName; + syncFolderValue.path = syncFolder; + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = syncFolder; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + // int32_t userId = DfsuAccessTokenHelper::GetUserId(); + // CloudDiskServiceSyncFolder::RegisterSyncFolder(userId, syncFolderIndex, syncFolder); + + auto callback = iface_cast(remoteObject); + LOGI("callback is null : %{public}s", callback == nullptr? "true" : "false"); + + CloudDiskServiceCallbackManager::GetInstance().RigisSyncFolderMap(bundleName, syncFolderIndex, callback); + + CloudDiskServiceCallbackManager::GetInstance().AddCallback(bundleName, callback); + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("RegisterSyncFolderChangesInner end syncFolderIndex:%{public}u", syncFolderIndex); + LOGI("End RegisterSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::UnregisterSyncFolderChangesInner(const std::string& syncFolder) +{ + LOGI("Begin UnregisterSyncFolderChangesInner"); + LOGI("UnregisterSyncFolderChangesInner start syncFolder:%{public}s", syncFolder.c_str()); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + std::string bundleName = ""; + int ret = DfsuAccessTokenHelper::GetCallerBundleName(bundleName); + if (ret != E_OK) { + LOGE("Get bundleName failed, ret:%{public}d", ret); + return ret; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + CloudDiskSyncFolder::GetInstance().DeleteSyncFolder(syncFolderIndex); + + CloudDiskServiceCallbackManager::GetInstance().UnregisSyncFolderMap(bundleName, syncFolderIndex); + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = syncFolder; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + // int32_t userId = DfsuAccessTokenHelper::GetUserId(); + // CloudDiskServiceSyncFolder::UnRegisterSyncFolder(userId, syncFolderIndex); + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End UnregisterSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::GetSyncFolderChangesInner(const std::string &syncFolder, uint64_t count, uint64_t startUsn, ChangesResult& changesResult) +{ + LOGI("Begin GetSyncFolderChangesInner"); + LOGI("GetSyncFolderChangesInner start syncFolder:%{public}s", syncFolder.c_str()); + LOGI("GetSyncFolderChangesInner start count:%{public}ld", count); + LOGI("GetSyncFolderChangesInner start startUSN:%{public}ld", startUsn); + LOGI("GetSyncFolderChangesInner start changesResult.nextUsn:%{public}ld", changesResult.nextUsn); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + return E_PARAMS_; + } + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + + TaskKey taskKey; + taskKey.bundleName = "test"; + taskKey.syncChronousRootPath = "test"; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + // CloudDiskServiceSyncFolder::UnRegisterSyncFolder(userId, syncFolderIndex); + + ChangeData changeData; + changeData.updateSequenceNumber = 1; + changeData.fileId = "1"; + changeData.parentFileId = "1"; + changeData.relativePath = "test"; + changeData.operationType = OperationType::CREATE; + changeData.size = 1; + changeData.mtime = 1; + changeData.timeStamp = 1; + changeData.timeStamp = 1; + changesResult.nextUsn = 1; + changesResult.isEof = true; + changesResult.changesData.push_back(changeData); + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("GetSyncFolderChangesInner end changesResult.nextUsn:%{public}ld", changesResult.nextUsn); + LOGI("End GetSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::SetFileSyncStatesInner(const std::string& syncFolder, const std::vector& fileSyncStates, const sptr& remoteObject) +{ + LOGI("Begin SetXattrInner"); + FailedList failed; + std::vector failedList; + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex) || fileSyncStates.empty() || fileSyncStates.size() > GET_FILE_SYNC_MAX) { + LOGE("Invalid parameter"); + return E_PARAMS_; + } + + auto callback = iface_cast(remoteObject); + for (auto& item : fileSyncStates) { + uint8_t state = static_cast(item.state); + if (state > static_cast(SyncState::SYNC_CONFLICTED)) { + LOGE("Invalid state for %{public}s", item.path.c_str()); + failed.path = item.path; + failed.error = ErrorReason::INVALID_ARGUMENT; // 待定 + failedList.push_back(failed); + continue; + } + if (setxattr(item.path.c_str(), FILE_SYNC_STATE, &state, sizeof(state), 0) != 0) { + LOGE("Failed to set xattr for file:%{public}s, err: %{public}d", item.path.c_str(), errno); + failed.path = item.path; + failed.error = ErrorReason::NO_SUCH_FILE; // 待定 + failedList.push_back(failed); + } + } + + callback->OnReturnSetFailedList(failedList); + + if (!failedList.empty()) { + return E_IPCSS; + } + + LOGI("End SetXattrInner"); + return 0; +} + +int32_t CloudDiskService::GetFileSyncStatesInner(const std::string& syncFolder, const std::vector& pathArray, const sptr& remoteObject) +{ + LOGI("Begin GetXattrInner"); + + // auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(syncFolder); + // if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex) || pathArray.empty() || pathArray.size() > GET_FILE_SYNC_MAX) { + // LOGE("Invalid parameter"); + // return E_PARAMS_; + // } + + // auto callback = iface_cast(remoteObject); + // FailedList failed; + // std::vector failedList; + // std::vector resultList; + + // for (auto& item : pathArray) { + // auto xattrValueSize = getxattr(item.c_str(), FILE_SYNC_STATE, nullptr, 0); + // if (xattrValueSize < 0) { + // LOGE("getxattr failed, errno : %{public}d", errno); + // failed.path = item; + // failed.error = ErrorReason::NO_SUCH_FILE; // 待定 + // failedList.push_back(failed); + // continue; + // } + // std::unique_ptr xattrValue = std::make_unique((long)xattrValueSize + 1); + // if (xattrValue == nullptr) { + // LOGE("Failed to allocate memory for xattrValue, errno : %{public}d", errno); + // failed.path = item; + // failed.error = ErrorReason::NO_SPACE_LEFT; // 待定 + // failedList.push_back(failed); + // continue; + // } + // xattrValueSize = getxattr(item.c_str(), FILE_SYNC_STATE, xattrValue.get(), xattrValueSize); + // if (xattrValueSize <= 0) { + // LOGE("getxattr failed, errno : %{public}d", errno); + // failed.path = item; + // failed.error = ErrorReason::NO_SUCH_FILE; // 待定 + // failedList.push_back(failed); + // continue; + // } + // uint8_t rawState = static_cast(xattrValue[0]); + // if (rawState > static_cast(SyncState::SYNC_CONFLICTED)) { + // LOGE("get invalid number"); + // failed.path = item; + // failed.error = ErrorReason::INVALID_ARGUMENT; // 待定 + // failedList.push_back(failed); + // continue; + // } + // FileSyncState fileSyncState; + // fileSyncState.path = syncFolder; + // fileSyncState.state = static_cast(rawState); + // resultList.push_back(fileSyncState); + // } + + // callback->OnReturnGetResult(resultList); + + LOGI("End GetXattrInner"); + return 0; +} + +int32_t CloudDiskService::RegisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) +{ + LOGI("Begin GetSyncFolderChangesInner"); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + return E_PARAMS_; + } + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = path; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = bundleName; + syncFolderValue.path = path; + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 1) { + // DiskMonitor::GetInstance().StartMonitor(userId); + } + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End GetSyncFolderChangesInner"); + return 0; +} + +int32_t CloudDiskService::UnregisterSyncFolderInner(int32_t userId, const std::string& bundleName, const std::string& path) +{ + LOGI("Begin GetSyncFolderChangesInner"); + // RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + // URI校验 + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + return E_PARAMS_; + } + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = path; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + CloudDiskSyncFolder::GetInstance().DeleteSyncFolder(syncFolderIndex); + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 0) { + // DiskMonitor::GetInstance().StopMonitor(); + } + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End GetSyncFolderChangesInner"); + return 0; +} + +void CloudDiskService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + LOGI("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId); + accountStatusListener_->Start(); +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp new file mode 100644 index 000000000..5280d08c8 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp @@ -0,0 +1,104 @@ +/* + * 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_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 std::string bundleName, const sptr &callback) +{ + if (callbackAppMap_[bundleName].callback != nullptr) { + return; + } + if (callback == nullptr) { + LOGE("callback is nullptr"); + return; + } + callbackAppMap_[bundleName].callback = callback; + auto remoteObject = callback->AsObject(); + auto deathCb = [this, bundleName](const wptr &obj) { + LOGE("client died"); + std::vector syncFolderIndex; + auto it = callbackAppMap_.find(bundleName); + if (it != callbackAppMap_.end()) { + syncFolderIndex = it->second.syncFolderIndexs; + callbackAppMap_.erase(it); + } + for (auto item : syncFolderIndex) { + callbackIndexMap_.erase(item); + } + }; + auto death = sptr(new SvcDeathRecipient(deathCb)); + remoteObject->AddDeathRecipient(death); +} + +void CloudDiskServiceCallbackManager::OnChangeData(const uint32_t syncFolderIndex, std::vector &changeData) +{ + auto item = callbackIndexMap_.find(syncFolderIndex); + if (item == callbackIndexMap_.end() || !item->second) { + LOGE("callback is nullptr"); + return; + } + item->second->OnChangeData(changeData); +} + +void CloudDiskServiceCallbackManager::RigisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex, const sptr &callback) +{ + unique_lock lockApp(callbackAppMutex_); + unique_lock lockIndex(callbackIndexMutex_); + auto it = callbackAppMap_.find(bundleName); + if (it == callbackAppMap_.end()) { + CallbackValue callbackValue; + callbackValue.syncFolderIndexs.push_back(syncFolderIndex); + callbackAppMap_[bundleName] = callbackValue; + } else { + it->second.syncFolderIndexs.push_back(syncFolderIndex); + } + + auto item = callbackIndexMap_.find(syncFolderIndex); + if (item == callbackIndexMap_.end()) { + callbackIndexMap_[syncFolderIndex] = callback; + } +} + +void CloudDiskServiceCallbackManager::UnregisSyncFolderMap(std::string bundleName, uint32_t syncFolderIndex) +{ + unique_lock lock(callbackIndexMutex_); + auto it = callbackIndexMap_.find(syncFolderIndex); + if(it != callbackIndexMap_.end()) callbackIndexMap_.erase(it); + + auto item = callbackAppMap_.find(bundleName); + if (item == callbackAppMap_.end()) { + LOGE("no such app in callback"); + return; + } + auto& vec = item->second.syncFolderIndexs; + auto pos = std::find(vec.begin(), vec.end(), syncFolderIndex); + if (pos != vec.end()) { + vec.erase(pos); + } +} + +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp new file mode 100644 index 000000000..00ff74835 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp @@ -0,0 +1,137 @@ +/* + * 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_proxy.h" + +#include "cloud_file_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +void CloudDiskServiceCallbackProxy::OnChangeData(std::vector &changeData) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return; + } + + if (changeData.size() > static_cast(VECTOR_MAX_SIZE)) { + return; + } + + data.WriteInt32(changeData.size()); + for (auto item = changeData.begin(); item != changeData.end(); ++item) { + if (!data.WriteParcelable(&(*item))) { + return; + } + } + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_CHANGE_DATA, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return; + } + LOGI("End"); + return; +} + +void CloudDiskServiceCallbackProxy::OnReturnSetFailedList(std::vector &failedList) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return; + } + + if (failedList.size() > static_cast(VECTOR_MAX_SIZE)) { + return; + } + data.WriteInt32(failedList.size()); + for (auto item = failedList.begin(); item != failedList.end(); ++item) { + if (!data.WriteParcelable(&(*item))) { + return; + } + } + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_RETURN_SET_FAILED_LIST, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return; + } + LOGI("End"); + return; +} + +void CloudDiskServiceCallbackProxy::OnReturnGetResult(std::vector &resultList) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return; + } + + // if (resultList.size() > static_cast(VECTOR_MAX_SIZE) || failedList.size() > static_cast(VECTOR_MAX_SIZE)) { + if (resultList.size() > static_cast(VECTOR_MAX_SIZE)) { + return; + } + + data.WriteInt32(resultList.size()); + for (auto item = resultList.begin(); item != resultList.end(); ++item) { + if (!data.WriteParcelable(&(*item))) { + return; + } + } + // data.WriteInt32(failedList.size()); + // for (auto item = failedList.begin(); item != failedList.end(); ++item) { + // if (!data.WriteParcelable(&(*item))) { + // return; + // } + // } + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_RETURN_GET_RESULT, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return; + } + LOGI("End"); + return; +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp b/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp new file mode 100644 index 000000000..011f1f7d4 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp @@ -0,0 +1,61 @@ +/* + * 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_sync_folder.h" + +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +CloudDiskSyncFolder &CloudDiskSyncFolder::GetInstance() +{ + static CloudDiskSyncFolder instance; + return instance; +} + +void CloudDiskSyncFolder::AddSyncFolder(const uint32_t syncFolderIndex, SyncFolderValue syncFolderValue) +{ + auto item = syncFolderMap.find(syncFolderIndex); + if (item == syncFolderMap.end()) { + syncFolderMap[syncFolderIndex] = syncFolderValue; + } +} + +void CloudDiskSyncFolder::DeleteSyncFolder(const uint32_t syncFolderIndex) +{ + auto item = syncFolderMap.find(syncFolderIndex); + if (item == syncFolderMap.end()) { + syncFolderMap.erase(syncFolderIndex); + } +} + +int32_t CloudDiskSyncFolder::GetSyncFolderSize() +{ + return syncFolderMap.size(); +} + +bool CloudDiskSyncFolder::CheckSyncFolder(const uint32_t syncFolderIndex) { + auto it = syncFolderMap.find(syncFolderIndex); + if (it == syncFolderMap.end()) { + LOGE("no such syncFolder"); + return false; + } + return true; +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/clouddiskservice/monitor/include/disk_monitor.h b/services/clouddiskservice/monitor/include/disk_monitor.h new file mode 100644 index 000000000..63aee0990 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_monitor.h @@ -0,0 +1,63 @@ +/* + * 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_FILEMANAGEMENT_DISK_MONITOR_H +#define OHOS_FILEMANAGEMENT_DISK_MONITOR_H + +#include +#include +#include + +#include "disk_types.h" + +namespace OHOS::FileManagement::CloudDiskService { +class DiskMonitor { +public: + static DiskMonitor &GetInstance(); + bool StartMonitor(int32_t userId); + void StopMonitor(); + +private: + bool InitFanotify(); + void InitInner(int32_t userId); + void CollectEvents(); + void HandleEvents(int32_t mountFd, char eventsBuf[], size_t dataLen); + void EventProcess(struct fanotify_event_metadata *metaData, const std::string &filePath); + // events handle + void HandleCreate(const std::string &filePath); + void HandleDelete(const std::string &filePath); + void HandleMoveFrom(const std::string &filePath); + void HandleMoveTo(const std::string &filePath); + void HandleCloseWrite(const std::string &filePath); + // events filter + std::pair GetSyncFolderIndex(const std::string &filePath); + bool IsInBlackList(const std::string &path); + +private: + // monitor status + int32_t userId_{-1}; + int32_t fanotifyFd_{-1}; + DIR *mountFp_{nullptr}; + int32_t mountFd_{-1}; // will be closed automatically after close(DIR*) + bool isRunning_{true}; + // events handle + EventInfo oldEventInfo_; + bool oldIsSyncFolder_{false}; + // events filter + std::string syncFolderPrefix_; + std::vector blackList_; +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/include/disk_notifier.h b/services/clouddiskservice/monitor/include/disk_notifier.h new file mode 100644 index 000000000..1c34e2740 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_notifier.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_FILEMANAGEMENT_DISK_NOTIFIER_H +#define OHOS_FILEMANAGEMENT_DISK_NOTIFIER_H + +#include + +#include "disk_types.h" +#include "ffrt_inner.h" + +namespace OHOS::FileManagement::CloudDiskService { +class DiskNotifier { +public: + static DiskNotifier &GetInstance(); + void PostEvent(const EventInfo &eventInfo); + +private: + void NotifyEventFull(); + void NotifyEventAll(); + static void CallBack(void *data); +private: + std::vector eventList_; + ffrt_timer_t handle_{-1}; + ffrt::mutex mutex_; +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/include/disk_types.h b/services/clouddiskservice/monitor/include/disk_types.h new file mode 100644 index 000000000..8b2c982e6 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_types.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 OHOS_FILEMANAGEMENT_DISK_TYPES_H +#define OHOS_FILEMANAGEMENT_DISK_TYPES_H +#include +#include +#include + +#include "cloud_disk_common.h" + +namespace OHOS::FileManagement::CloudDiskService { +constexpr int64_t SECOND_TO_MILLISECOND = 1e3; +constexpr int64_t MILLISECOND_TO_NANOSECOND = 1e6; + +static uint64_t UTCTimeMilliSeconds() +{ + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return t.tv_sec * SECOND_TO_MILLISECOND + t.tv_nsec / MILLISECOND_TO_NANOSECOND; +} + +struct EventInfo { + int32_t userId{-1}; + uint32_t syncFolderIndex{0}; + std::string path{""}; + std::string name{""}; + uint8_t operateType{static_cast(OperationType::OPERATION_MAX)}; + uint64_t timestamp{0}; + int32_t moveOptId{0}; + + EventInfo() {} + EventInfo(int32_t uid, int32_t syncFolder, OperationType type, const std::string &filePath) + : userId(uid), syncFolderIndex(syncFolder), operateType(static_cast(type)) + { + path = std::filesystem::path(filePath).parent_path().string(); + name = std::filesystem::path(filePath).filename().string(); + timestamp = UTCTimeMilliSeconds(); + } + + void Reset() + { + userId = -1; + syncFolderIndex = 0; + path = ""; + name = ""; + operateType = static_cast(OperationType::OPERATION_MAX); + timestamp = 0; + moveOptId = 0; + } +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/include/disk_utils.h b/services/clouddiskservice/monitor/include/disk_utils.h new file mode 100644 index 000000000..b196bfbc4 --- /dev/null +++ b/services/clouddiskservice/monitor/include/disk_utils.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_FILEMANAGEMENT_DISK_UTILS_H +#define OHOS_FILEMANAGEMENT_DISK_UTILS_H + +#include +#include +#include +#include + +namespace OHOS::FileManagement::CloudDiskService { +class DiskUtils { +public: + static bool ExtractFileName(int type, std::string &fileName, struct file_handle *fileHandle); + static std::string GetFilePath(int32_t eventFd, const std::string &fileName); + static void CloseFd(int &fd); + static void CloseDir(DIR *&dir); +}; +} // namespace OHOS::FileManagement::CloudDiskService +#endif diff --git a/services/clouddiskservice/monitor/src/disk_monitor.cpp b/services/clouddiskservice/monitor/src/disk_monitor.cpp new file mode 100644 index 000000000..4bf0c3702 --- /dev/null +++ b/services/clouddiskservice/monitor/src/disk_monitor.cpp @@ -0,0 +1,302 @@ +/* + * 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 "disk_monitor.h" + +#include +#include +#include + +#include "cloud_disk_sync_folder.h" +#include "disk_notifier.h" +#include "disk_utils.h" +#include "ffrt_inner.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +namespace{ +constexpr uint32_t INIT_FLAGS = FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME | FAN_UNLIMITED_QUEUE; +constexpr uint32_t INIT_EVENT_FLAGS = O_RDONLY | O_LARGEFILE; +constexpr uint32_t MARK_FLAGS = FAN_MARK_ADD | FAN_MARK_FILESYSTEM; +constexpr uint64_t MARK_MASK = FAN_CREATE | FAN_DELETE | FAN_MOVED_FROM | FAN_MOVED_TO | FAN_ONDIR | FAN_CLOSE_WRITE; +constexpr int32_t INVALID_SYNC_FOLDER = 0; +const string MOUNT_PATH = "/data/service"; +const string DATA_SERVICE_EL2 = "/data/service/el2/"; +const string HMDFS_DOCS = "/hmdfs/account/files/Docs"; +const vector BLACK_DIRS = {"/.Trash", "/.Recent", "/.thumbs", "/HO_DATA_EXT_MISC"}; +} + +DiskMonitor &DiskMonitor::GetInstance() +{ + static DiskMonitor instance_; + return instance_; +} + +bool DiskMonitor::StartMonitor(int32_t userId) +{ + LOGI("Start monitor: %{public}d", userId); + if(!InitFanotify()){ + return false; + } + + InitInner(userId); + ffrt::submit([this] { this->CollectEvents(); }); + LOGI("Start monitor finished"); + return true; +} + +void DiskMonitor::StopMonitor() +{ + userId_ = -1; + isRunning_ = false; + syncFolderPrefix_.clear(); + blackList_.clear(); + // clean fd + DiskUtils::CloseFd(fanotifyFd_); + DiskUtils::CloseDir(mountFp_); +} + +void DiskMonitor::InitInner(int32_t userId) +{ + userId_ = userId; + isRunning_ = true; + syncFolderPrefix_ = DATA_SERVICE_EL2 + to_string(userId) + HMDFS_DOCS; + for (auto &it : BLACK_DIRS) { + blackList_.push_back(DATA_SERVICE_EL2 + to_string(userId) + HMDFS_DOCS + it); + } + LOGI("debugonly: syncFolderPrefix-> %{public}s", syncFolderPrefix_.c_str()); + for (auto &it : blackList_) { + LOGI("debugonly: black-> %{public}s", it.c_str()); + } +} + +bool DiskMonitor::InitFanotify() +{ + LOGI("init start"); + fanotifyFd_ = fanotify_init(INIT_FLAGS, INIT_EVENT_FLAGS); + if (fanotifyFd_ == -1) { + LOGE("disk monitor init failed, errno: %{public}d", errno); + return false; + } + if (fanotify_mark(fanotifyFd_, MARK_FLAGS, MARK_MASK, AT_FDCWD, MOUNT_PATH.c_str()) == -1) { + LOGE("fanotify_mark failed, errno: %{public}d", errno); + DiskUtils::CloseFd(fanotifyFd_); + return false; + } + mountFp_ = opendir(MOUNT_PATH.c_str()); + if (mountFp_ == nullptr) { + LOGE("open dir failed, errno: %{public}d", errno); + DiskUtils::CloseFd(fanotifyFd_); + return false; + } + mountFd_ = dirfd(mountFp_); + if (mountFd_ == -1) { + LOGE("get dirfd failed, errno: %{public}d", errno); + DiskUtils::CloseFd(fanotifyFd_); + DiskUtils::CloseDir(mountFp_); + return false; + } + LOGI("Init end"); + return true; +} + +void DiskMonitor::CollectEvents() +{ + while (isRunning_) { + char eventsBuf[4096]{}; + ssize_t dataLen = read(fanotifyFd_, eventsBuf, sizeof(eventsBuf)); + if (dataLen == -1 && errno != EAGAIN) { + LOGE("read failed, errno: %{public}d", errno); + continue; + } + if (dataLen == 0) { + LOGI("no data to read"); + continue; + } + // TODO: check current user is active(unlock) + HandleEvents(mountFd_, eventsBuf, dataLen); + } +} + +void DiskMonitor::HandleEvents(int32_t mountFd, char eventsBuf[], size_t dataLen) +{ + for (struct fanotify_event_metadata *metaData = reinterpret_cast(eventsBuf); + FAN_EVENT_OK(metaData, dataLen); metaData = FAN_EVENT_NEXT(metaData, dataLen)) { + struct fanotify_event_info_fid *fID = reinterpret_cast(metaData + 1); + struct file_handle *fileHandle = reinterpret_cast(fID->handle); + if (fileHandle == nullptr) { + LOGE("fileHandle is null"); + continue; + } + + // get file name + string fileName; + if (!DiskUtils::ExtractFileName(fID->hdr.info_type, fileName, fileHandle)) { + continue; + } + bool isDir = metaData->mask & FAN_ONDIR; + // other info + int eventFd = open_by_handle_at(mountFd, fileHandle, O_RDONLY); + if (eventFd == -1) { + LOGE("open_by_handle_at, errno: %{public}d", errno); + continue; + } + + string filePath = DiskUtils::GetFilePath(eventFd, fileName); + if (filePath.empty()) { + close(eventFd); + continue; + } + + EventProcess(metaData, filePath); + + close(eventFd); + } +} + +void DiskMonitor::EventProcess(struct fanotify_event_metadata *metaData, const string &filePath) +{ + if (metaData->mask & FAN_CREATE) { + HandleCreate(filePath); + } else if (metaData->mask & FAN_DELETE) { + HandleDelete(filePath); + } else if (metaData->mask & FAN_MOVED_FROM) { + HandleMoveFrom(filePath); + } else if (metaData->mask & FAN_MOVED_TO) { + HandleMoveTo(filePath); + } else if (metaData->mask & FAN_CLOSE_WRITE) { + HandleCloseWrite(filePath); + } + if (!IsInBlackList(filePath)) { + LOGD("mask: %{public}llu, path: %{public}s", metaData->mask, filePath.c_str()); + } +} + +void DiskMonitor::HandleCreate(const string &filePath) +{ + auto [syncFolderIndex, _] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + auto eventInfo = EventInfo(userId_, syncFolderIndex, OperationType::CREATE, filePath); + DiskNotifier::GetInstance().PostEvent(eventInfo); +} + +void DiskMonitor::HandleDelete(const string &filePath) +{ + auto [syncFolderIndex, isSyncFolder] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + OperationType type = isSyncFolder ? OperationType::SYNC_FOLDER_INVALID : OperationType::DELETE; + auto eventInfo = EventInfo(userId_, syncFolderIndex, type, filePath); + DiskNotifier::GetInstance().PostEvent(eventInfo); +} + +void DiskMonitor::HandleMoveFrom(const string &filePath) +{ + auto [syncFolderIndex, isSyncFolder] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + oldEventInfo_ = EventInfo(userId_, syncFolderIndex, OperationType::MOVE_FROM, filePath); + oldIsSyncFolder_ = isSyncFolder; +} + +/* + * old is not in sync folder, new is not in sync folder, skip + * old is not in sync folder, new is in sync folder, create->new + * old is in sync folder, new is not in sync folder: + * 1. old is sync folder, sync_folder_invalid->old + * 2. old is not sync folder, delete->old + * old is in sync folder, new is in sync folder, sync root is the same, move_from->old + move_to->new + * old is in sync folder, new is in sync folder, sync root is not the same + * 1. old is sync folder, sync_folder_invalid->old + create->new + * 2. old is not sync folder, delete->old + create->new + */ +void DiskMonitor::HandleMoveTo(const string &filePath) +{ + auto [syncFolderIndex, _] = GetSyncFolderIndex(filePath); + auto eventInfo = EventInfo(userId_, syncFolderIndex, OperationType::MOVE_TO, filePath); + do { + // old is not in sync folder + if (oldEventInfo_.syncFolderIndex == INVALID_SYNC_FOLDER) { + if (eventInfo.syncFolderIndex == INVALID_SYNC_FOLDER) { + break; + } + eventInfo.operateType = static_cast(OperationType::CREATE); + DiskNotifier::GetInstance().PostEvent(eventInfo); + break; + } + // old is in sync folder + if (eventInfo.syncFolderIndex == INVALID_SYNC_FOLDER) { + OperationType type = oldIsSyncFolder_ ? OperationType::SYNC_FOLDER_INVALID : OperationType::DELETE; + oldEventInfo_.operateType = static_cast(type); + DiskNotifier::GetInstance().PostEvent(oldEventInfo_); + break; + } + if (oldEventInfo_.syncFolderIndex == eventInfo.syncFolderIndex) { + oldEventInfo_.operateType = static_cast(OperationType::MOVE_FROM); + eventInfo.operateType = static_cast(OperationType::MOVE_TO); + DiskNotifier::GetInstance().PostEvent(oldEventInfo_); + DiskNotifier::GetInstance().PostEvent(eventInfo); + break; + } + OperationType type = oldIsSyncFolder_ ? OperationType::SYNC_FOLDER_INVALID : OperationType::DELETE; + oldEventInfo_.operateType = static_cast(type); + eventInfo.operateType = static_cast(OperationType::CREATE); + DiskNotifier::GetInstance().PostEvent(oldEventInfo_); + DiskNotifier::GetInstance().PostEvent(eventInfo); + } while (0); + + oldEventInfo_.Reset(); +} + +void DiskMonitor::HandleCloseWrite(const string &filePath) +{ + auto [syncFolderIndex, _] = GetSyncFolderIndex(filePath); + if (syncFolderIndex == INVALID_SYNC_FOLDER) { + return; + } + auto eventInfo = EventInfo(userId_, syncFolderIndex, OperationType::CLOSE_WRITE, filePath); + DiskNotifier::GetInstance().PostEvent(eventInfo); +} + +pair DiskMonitor::GetSyncFolderIndex(const string &filePath) +{ + if (IsInBlackList(filePath)) { + return {INVALID_SYNC_FOLDER, false}; + } + for (auto &it : CloudDiskSyncFolder::GetInstance().GetSyncFolderMap()) { + if (filePath.find(it.second.path) == 0) { + return {it.first, filePath == it.second.path}; + } + } + return {INVALID_SYNC_FOLDER, false}; +} + +bool DiskMonitor::IsInBlackList(const string &path) +{ + if (path.find(syncFolderPrefix_) != 0) { + return true; + } + for (auto &it : blackList_) { + if (path.find(it) == 0) { + return true; + } + } + return false; +} +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/services/clouddiskservice/monitor/src/disk_notifier.cpp b/services/clouddiskservice/monitor/src/disk_notifier.cpp new file mode 100644 index 000000000..13b1c8e1c --- /dev/null +++ b/services/clouddiskservice/monitor/src/disk_notifier.cpp @@ -0,0 +1,89 @@ +/* + * 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 "disk_notifier.h" + +#include "cloud_disk_service_syncfolder.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +namespace { +constexpr uint32_t MAX_EVENT_NUM = 500; +constexpr uint64_t NOTIFY_TIMEOUT_MS = 200; +} // namespace +DiskNotifier &DiskNotifier::GetInstance() +{ + static DiskNotifier instance_; + return instance_; +} + +void DiskNotifier::PostEvent(const EventInfo &eventInfo) +{ + lock_guard lock(mutex_); + LOGD("opt: %{public}d path: %{public}s name: %{public}s", eventInfo.operateType, eventInfo.path.c_str(), + eventInfo.name.c_str()); + // 1. list is empty, firt run, setup timer + // 2. list has reached the max, notify and reset timer + if (eventList_.empty()) { + ffrt_timer_stop(ffrt_qos_default, handle_); + handle_ = ffrt_timer_start(ffrt_qos_default, NOTIFY_TIMEOUT_MS, nullptr, CallBack, false); + } else if (eventList_.size() >= MAX_EVENT_NUM) { + ffrt_timer_stop(ffrt_qos_default, handle_); + NotifyEventFull(); + handle_ = ffrt_timer_start(ffrt_qos_default, NOTIFY_TIMEOUT_MS, nullptr, CallBack, false); + } + // when recv the same eventInfo, just update timestamp + if (!eventList_.empty() && eventList_.back().operateType == eventInfo.operateType && + eventList_.back().path == eventInfo.path && eventList_.back().name == eventInfo.name) { + eventList_.back().timestamp = eventInfo.timestamp; + return; + } + eventList_.push_back(eventInfo); +} + +void DiskNotifier::NotifyEventFull() +{ + vector tempEventList; + if (eventList_.empty()) { + return; + } + eventList_.swap(tempEventList); + eventList_.clear(); + + CloudDiskServiceSyncFolder::SetSyncFolderChanges(tempEventList); + LOGI("NOTIFY_FULL: size: %{public}zu", tempEventList.size()); +} + +void DiskNotifier::NotifyEventAll() +{ + vector tempEventList; + { + lock_guard lock(mutex_); + if (eventList_.empty()) { + return; + } + eventList_.swap(tempEventList); + eventList_.clear(); + } + + CloudDiskServiceSyncFolder::SetSyncFolderChanges(tempEventList); + LOGI("NOTIFY_ALL: size: %{public}zu", tempEventList.size()); +} + +void DiskNotifier::CallBack(void *) +{ + DiskNotifier::GetInstance().NotifyEventAll(); +} +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/services/clouddiskservice/monitor/src/disk_utils.cpp b/services/clouddiskservice/monitor/src/disk_utils.cpp new file mode 100644 index 000000000..fa9995f25 --- /dev/null +++ b/services/clouddiskservice/monitor/src/disk_utils.cpp @@ -0,0 +1,72 @@ +/* + * 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 "disk_utils.h" + +#include +#include + +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +const string PROC_SELF_FD = "/proc/self/fd/"; + +bool DiskUtils::ExtractFileName(int type, string &fileName, struct file_handle *fileHandle) +{ + if (type == FAN_EVENT_INFO_TYPE_FID || type == FAN_EVENT_INFO_TYPE_DFID) { + fileName.clear(); + } else if (type == FAN_EVENT_INFO_TYPE_DFID_NAME) { + fileName = reinterpret_cast(fileHandle->f_handle + fileHandle->handle_bytes); + } else { + return false; + } + return true; +} + +string DiskUtils::GetFilePath(int32_t eventFd, const string &fileName) +{ + char eventFilePath[PATH_MAX + 1]; + string procFdPath = PROC_SELF_FD + to_string(eventFd); + ssize_t pathLen = readlink(procFdPath.c_str(), eventFilePath, sizeof(eventFilePath) - 1); + if (pathLen == -1 || pathLen > PATH_MAX) { + LOGI("readlink failed , errno: %{public}d", errno); + return ""; + } + eventFilePath[pathLen] = '\0'; + + string filePath(eventFilePath); + if (!fileName.empty() && fileName.compare(".") != 0) { + filePath += "/" + fileName; + } + return filePath; +} + +void DiskUtils::CloseFd(int &fd) +{ + if (fd != -1) { + close(fd); + fd = -1; + } +} + +void DiskUtils::CloseDir(DIR *&dir) +{ + if (dir != nullptr) { + closedir(dir); + dir = nullptr; + } +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/seccomp_policy/BUILD.gn b/services/clouddiskservice/seccomp_policy/BUILD.gn new file mode 100644 index 000000000..b1b3bef58 --- /dev/null +++ b/services/clouddiskservice/seccomp_policy/BUILD.gn @@ -0,0 +1,28 @@ +# 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/init/seccomp/scripts/seccomp_policy_fixer.gni") + +ohos_prebuilt_seccomp("disk_monitor_seccomp_filter") { + sources = [ "clouddiskservice.seccomp.policy" ] + + filtername = "clouddiskservice" + + process_type = "system" + + part_name = "dfs_service" + subsystem_name = "filemanagement" + + install_enable = true + install_images = [ "system" ] +} \ No newline at end of file diff --git a/services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy b/services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy new file mode 100644 index 000000000..ccb4fe499 --- /dev/null +++ b/services/clouddiskservice/seccomp_policy/clouddiskservice.seccomp.policy @@ -0,0 +1,341 @@ +# 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@allowList +io_setup;all +io_destroy;all +io_submit;all +io_cancel;all +io_getevents;all +setxattr;all +lsetxattr;all +fsetxattr;all +getxattr;all +lgetxattr;all +fgetxattr;all +listxattr;all +llistxattr;all +flistxattr;all +removexattr;all +lremovexattr;all +fremovexattr;all +getcwd;all +eventfd2;all +epoll_create1;all +epoll_ctl;all +epoll_pwait;all +dup;all +dup3;all +fcntl;arm64 +inotify_init1;all +inotify_add_watch;all +inotify_rm_watch;all +ioctl;all +ioprio_set;arm64 +ioprio_get;arm64 +flock;all +mknodat;all +mkdirat;all +unlinkat;all +symlinkat;all +linkat;all +renameat;arm +renameat;arm64 +umount2;all +mount;all +pivot_root;all +statfs;arm64 +fstatfs;arm64 +truncate;all +ftruncate;arm64 +fallocate;all +faccessat;all +faccessat2;all +chdir;all +fchdir;all +chroot;all +fchmod;all +fchmodat;all +fchownat;all +fchown;arm64 +openat;all +close;all +pipe2;all +quotactl;all +getdents64;all +lseek;all +read;all +write;all +readv;all +writev;all +pread64;all +pwrite64;all +preadv;all +pwritev;all +sendfile;all +pselect6;all +ppoll;all +signalfd4;all +vmsplice;all +splice;all +tee;all +readlinkat;all +newfstatat;arm64 +fstat;arm64 +sync;all +fsync;all +fdatasync;all +sync_file_range;arm64 +timerfd_create;all +timerfd_settime;all +timerfd_gettime;all +utimensat;all +acct;all +capget;all +capset;all +personality;all +exit;all +exit_group;all +waitid;all +set_tid_address;all +unshare;all +futex;all +set_robust_list;all +get_robust_list;all +nanosleep;all +getitimer;all +setitimer;all +init_module;all +delete_module;all +timer_create;all +timer_gettime;all +timer_getoverrun;all +timer_settime;all +timer_delete;all +clock_settime;all +clock_gettime;all +clock_getres;all +clock_nanosleep;all +syslog;all +ptrace;all +sched_setparam;all +sched_setscheduler;all +sched_getscheduler;all +sched_getparam;all +sched_setaffinity;all +sched_getaffinity;all +sched_yield;all +sched_get_priority_max;all +sched_get_priority_min;all +sched_rr_get_interval;all +restart_syscall;all +kill;all +tkill;all +tgkill;all +sigaltstack;all +rt_sigsuspend;all +rt_sigaction;all +rt_sigprocmask;all +rt_sigpending;all +rt_sigtimedwait;all +rt_sigqueueinfo;all +rt_sigreturn;all +setpriority;all +getpriority;all +reboot;all +setregid;arm64 +setgid;arm64 +setreuid;arm64 +setuid;arm64 +setresuid;arm64 +getresuid;arm64 +setresgid;arm64 +getresgid;arm64 +setfsuid;all +setfsgid;all +times;all +setpgid;all +getpgid;all +getsid;all +setsid;all +getgroups;arm64 +setgroups;arm64 +uname;all +sethostname;all +setdomainname;all +getrlimit;arm64 +setrlimit;all +getrusage;all +umask;all +prctl;all +getcpu;all +gettimeofday;all +settimeofday;all +adjtimex;all +getpid;all +getppid;all +getuid;arm64 +geteuid;arm64 +getgid;arm64 +getegid;arm64 +gettid;all +sysinfo;all +semget;all +shmget;all +shmctl;all +shmat;all +shmdt;all +socket;all +socketpair;all +bind;all +listen;all +accept;all +connect;all +getsockname;all +getpeername;all +sendto;all +recvfrom;all +setsockopt;all +getsockopt;all +shutdown;all +sendmsg;all +recvmsg;all +readahead;all +brk;all +munmap;all +mremap;all +add_key;all +keyctl;all +clone;all +execve;all +mmap;arm64 +fadvise64;arm64 +mprotect;all +msync;all +mlock;all +munlock;all +mlockall;all +munlockall;all +mincore;all +madvise;all +rt_tgsigqueueinfo;all +perf_event_open;all +accept4;all +recvmmsg;all +wait4;all +prlimit64;all +clock_adjtime;all +syncfs;all +setns;all +sendmmsg;all +process_vm_readv;all +process_vm_writev;all +finit_module;all +sched_setattr;all +sched_getattr;all +renameat2;all +seccomp;all +getrandom;all +memfd_create;all +bpf;all +execveat;all +userfaultfd;all +membarrier;all +mlock2;all +copy_file_range;all +preadv2;all +pwritev2;all +statx;all +pidfd_send_signal;all +pidfd_open;all +close_range;all +pidfd_getfd;all +process_madvise;all +fork;arm +open;arm +unlink;arm +mknod;arm +chmod;arm +access;arm +rename;arm +mkdir;arm +rmdir;arm +pipe;arm +dup2;arm +sigaction;arm +symlink;arm +readlink;arm +stat;arm +sigreturn;arm +_llseek;arm +_newselect;arm +poll;arm +vfork;arm +ugetrlimit;arm +mmap2;arm +truncate64;arm +ftruncate64;arm +stat64;arm +fstat64;arm +lchown32;arm +getuid32;arm +getgid32;arm +geteuid32;arm +getegid32;arm +setreuid32;arm +setregid32;arm +chown32;arm +getgroups32;arm +setgroups32;arm +fchown32;arm +setresuid32;arm +getresuid32;arm +setresgid32;arm +getresgid32;arm +setuid32;arm +setgid32;arm +fcntl64;arm +sendfile64;arm +statfs64;arm +fstatfs64;arm +fadvise64_64;arm +fstatat64;arm +sync_file_range2;arm +clock_gettime64;arm +clock_settime64;arm +clock_adjtime64;arm +clock_getres_time64;arm +clock_nanosleep_time64;arm +timer_gettime64;arm +timer_settime64;arm +timerfd_gettime64;arm +timerfd_settime64;arm +utimensat_time64;arm +pselect6_time64;arm +ppoll_time64;arm +recvmmsg_time64;arm +semtimedop_time64;arm +rt_sigtimedwait_time64;arm +futex_time64;arm +sched_rr_get_interval_time64;arm +cacheflush;arm +set_tls;arm +mbind;all +fanotify_init;arm64 +fanotify_mark;arm64 +open_by_handle_at;arm64 diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp new file mode 100644 index 000000000..d15d5e18e --- /dev/null +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -0,0 +1,603 @@ +/* + * 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 +#include + +#include "disk_monitor.h" + +namespace OHOS::FileManagement::CloudDiskService::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DiskMonitorMock : public DiskMonitor { +public: + MOCK_METHOD0(InitFanotify, bool()); + MOCK_METHOD1(InitInner, void(int32_t)); + MOCK_METHOD0(CollectEvents, void()); + MOCK_METHOD1(HandleCreate, void(const string &filePath)); + MOCK_METHOD1(HandleDelete, void(const string &filePath)); + MOCK_METHOD1(HandleMoveFrom, void(const string &filePath)); + MOCK_METHOD1(HandleMoveTo, void(const string &filePath)); + MOCK_METHOD1(HandleCloseWrite, void(const string &filePath)); + MOCK_METHOD1(IsInBlackList, void(const string &filePath)); +}; + +class DiskMonitorTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + shared_ptr diskMonitor_; + int32_t userId = 100; + +}; + +void DiskMonitorTest::SetUpTestCase(void) { + GTEST_LOG_(INFO) << "SetUpTestCase"; + diskMonitor_ = make_shared(); +} + +void DiskMonitorTest::TearDownTestCase(void) { + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DiskMonitorTest::SetUp(void) { + +} + +void DiskMonitorTest::TearDown(void) { + +} + +/** +@tc.name: GetInstanceTest001 +@tc.desc: Verify the GetInstance function returns singleton instance +@tc.type: FUNC +*/ +HWTEST_F(DiskMonitorTest, GetInstanceTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetInstanceTest001 Begin"; + try { + DiskMonitor& instance = DiskMonitor::GetInstance(); + DiskMonitor& instance2 = DiskMonitor::GetInstance(); + EXPECT_EQ(&instance, &instance2); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetInstanceTest001 Error"; + } + GTEST_LOG_(INFO) << "GetInstanceTest001 End"; +} + +/** + * @tc.name: StartMonitorTest001 + * @tc.desc: Verify StartMonitor returns true when InitFanotify succeeds + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, StartMonitorTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StartMonitorTest001 Begin"; + try { + DiskMonitorMock mockMonitor; + + EXPECT_CALL(mockMonitor, InitFanotify()).WillOnce(Return(true)); + EXPECT_CALL(mockMonitor, InitInner(userId)).Times(1); + EXPECT_CALL(mockMonitor, CollectEvents()).Times(AtLeast(0)); + + bool ret = mockMonitor.StartMonitor(userId); + + EXPECT_TRUE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "StartMonitorTest001 Error"; + } + GTEST_LOG_(INFO) << "StartMonitorTest001 End"; +} + +/** + * @tc.name: StartMonitorTest002 + * @tc.desc: Verify StartMonitor returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, StartMonitorTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StartMonitorTest002 Begin"; + try { + DiskMonitorMock mockMonitor; + + EXPECT_CALL(mockMonitor, InitFanotify()).WillOnce(Return(false)); + EXPECT_CALL(mockMonitor, InitInner(_)).Times(0); + EXPECT_CALL(mockMonitor, CollectEvents()).Times(0); + + bool ret = mockMonitor.StartMonitor(userId); + + EXPECT_FALSE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "StartMonitorTest002 Error"; + } + GTEST_LOG_(INFO) << "StartMonitorTest002 End"; +} + +/** + * @tc.name: StopMonitorTest001 + * @tc.desc: Verify StopMonitor returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, StopMonitorTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StopMonitorTest001 Begin"; + try { + DiskMonitor Monitor; + Monitor.StopMonitor(); + + EXPECT_EQ(Monitor.userId_, -1); + EXPECT_EQ(Monitor.isRunning_, false); + EXPECT_EQ(Monitor.fanotifyFd_, -1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "StopMonitorTest001 Error"; + } + GTEST_LOG_(INFO) << "StopMonitorTest001 End"; +} + +/** + * @tc.name: InitInnerTest001 + * @tc.desc: Verify InitInner returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, InitInnerTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "InitInnerTest001 Begin"; + try { + DiskMonitor Monitor; + Monitor.InitInner(userId); + + EXPECT_EQ(Monitor.userId_, userId); + EXPECT_EQ(Monitor.isRunning_, true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "InitInnerTest001 Error"; + } + GTEST_LOG_(INFO) << "InitInnerTest001 End"; +} + +/** + * @tc.name: CollectEventsTest001 + * @tc.desc: Verify CollectEvents returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, CollectEventsTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CollectEventsTest001 Begin"; + try { + DiskMonitor Monitor; + Monitor.isRunning_ = false; + + Monitor.CollectEvents(); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CollectEventsTest001 Error"; + } + GTEST_LOG_(INFO) << "CollectEventsTest001 End"; +} + +/** + * @tc.name: EventProcessTest001 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest001 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CREATE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCreate(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest001 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest001 End"; +} + +/** + * @tc.name: EventProcessTest002 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest002 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CREATE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCreate(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest002 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest002 End"; +} + +/** + * @tc.name: EventProcessTest003 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest003 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_DELETE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleDelete(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest003 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest003 End"; +} + +/** + * @tc.name: EventProcessTest004 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest004 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_DELETE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleDelete(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest004 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest004 End"; +} + +/** + * @tc.name: EventProcessTest005 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest005 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_FROM; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveFrom(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest005 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest005 End"; +} + +/** + * @tc.name: EventProcessTest006 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest006, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest006 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_FROM; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveFrom(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest006 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest006 End"; +} + +/** + * @tc.name: EventProcessTest007 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest007, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest007 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_TO; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveTo(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest007 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest007 End"; +} + +/** + * @tc.name: EventProcessTest008 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest008, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest008 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_TO; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleMoveTo(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest008 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest008 End"; +} + +/** + * @tc.name: EventProcessTest009 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest009, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest009 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CLOSE_WRITE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCloseWrite(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest009 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest009 End"; +} + +/** + * @tc.name: EventProcessTest0010 + * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest0010, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest0010 Begin"; + try { + DiskMonitorMock mockMonitor; + fanotify_event_metadata metaData; + metaData.mask = FAN_CLOSE_WRITE; + std::string filePath = "test/file/path"; + + EXPECT_CALL(mockMonitor, HandleCloseWrite(filePath)).Times(1); + EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); + + mockMonitor.EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest0010 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest0010 End"; +} + +/** + * @tc.name: IsInBlackListTest001 + * @tc.desc: Verify the IsInBlackList function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, IsInBlackListTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IsInBlackListTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + bool res = diskMonitor_->IsInBlackList(path); + EXPECT_TRUE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IsInBlackListTest001 Error"; + } + GTEST_LOG_(INFO) << "IsInBlackListTest001 End"; +} + +/** + * @tc.name: IsInBlackListTest002 + * @tc.desc: Verify the IsInBlackList function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, IsInBlackListTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IsInBlackListTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"a", "b"}; + bool res = diskMonitor_->IsInBlackList(path); + EXPECT_TRUE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IsInBlackListTest002 Error"; + } + GTEST_LOG_(INFO) << "IsInBlackListTest002 End"; +} + +/** + * @tc.name: IsInBlackListTest003 + * @tc.desc: Verify the IsInBlackList function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, IsInBlackListTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IsInBlackListTest003 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + bool res = diskMonitor_->IsInBlackList(path); + EXPECT_FALSE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IsInBlackListTest003 Error"; + } + GTEST_LOG_(INFO) << "IsInBlackListTest003 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest001 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, INVALID_SYNC_FOLDER); + EXPECT_FALSE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest001 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest001 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest002 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "a"}}); + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, 1); + EXPECT_FALSE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest002 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest002 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest003 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest003 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, 1); + EXPECT_TRUE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest003 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest003 End"; +} + +/** + * @tc.name: GetSyncFolderIndexTest004 + * @tc.desc: Verify the GetSyncFolderIndex function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, GetSyncFolderIndexTest004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest004 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "b"}}); + pair res = diskMonitor_->GetSyncFolderIndex(path); + EXPECT_EQ(res.first, INVALID_SYNC_FOLDER); + EXPECT_FALSE(res.second); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest004 Error"; + } + GTEST_LOG_(INFO) << "GetSyncFolderIndexTest004 End"; +} +} \ No newline at end of file diff --git a/test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp b/test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp new file mode 100644 index 000000000..f945952e7 --- /dev/null +++ b/test/unittests/clouddiskservice/monitor/disk_notifier_test.cpp @@ -0,0 +1,203 @@ +/* + * 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 +#include + +#include "disk_notifier.h" +#include "cloud_disk_service_syncfolder.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement::CloudDiskService { +namespace Test { +using namespace testing::ext; +using namespace std; + +class DiskNotifierTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DiskNotifierTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void DiskNotifierTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DiskNotifierTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void DiskNotifierTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: PostEventTest001 + * @tc.desc: Verify the PostEvent function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, PostEventTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "PostEventTest001 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + DiskNotifier& notifier = DiskNotifier::GetInstance(); + auto eventInfo = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + notifier.PostEvent(eventInfo); + EXPECT_EQ(notifier.eventList_.szie(), 1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "PostEventTest001 failed"; + } + GTEST_LOG_(INFO) << "PostEventTest001 end"; +} + +/** + * @tc.name: PostEventTest002 + * @tc.desc: Verify the PostEvent function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, PostEventTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "PostEventTest002 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + auto eventInfo_time1 = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + auto eventInfo_time2 = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.PostEvent(eventInfo_time1); + notifier.PostEvent(eventInfo_time2); + EXPECT_EQ(notifier.eventList_.szie(), 1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "PostEventTest002 failed"; + } + GTEST_LOG_(INFO) << "PostEventTest002 end"; +} + +/** + * @tc.name: NotifyEventFullTest001 + * @tc.desc: Verify the NotifyEventFull function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventFullTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventFullTest001 start"; + try { + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.NotifyEventFull(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventFullTest001 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventFullTest001 end"; +} + +/** + * @tc.name: NotifyEventFullTest002 + * @tc.desc: Verify the NotifyEventFull function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventFullTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventFullTest002 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + auto eventInfo = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.PostEvent(eventInfo); + notifier.NotifyEventFull(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventFullTest002 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventFullTest002 end"; +} + +/** + * @tc.name: NotifyEventAllTest001 + * @tc.desc: Verify the NotifyEventAll function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventAllTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventAllTest001 start"; + try { + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.NotifyEventAll(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventAllTest001 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventAllTest001 end"; +} + +/** + * @tc.name: NotifyEventAllTest002 + * @tc.desc: Verify the NotifyEventAll function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(DiskNotifierTest, NotifyEventAllTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyEventAllTest002 start"; + try { + int32_t userId = 100; + int32_t syncFolderIndex = 1; + auto filePath = "/test/1.txt"; + auto eventInfo = EventInfo(userId, syncFolderIndex, OperationType::MOVE_TO, filePath); + DiskNotifier& notifier = DiskNotifier::GetInstance(); + + notifier.PostEvent(eventInfo); + notifier.NotifyEventAll(); + EXPECT_EQ(notifier.eventList_.empty(), true); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "NotifyEventAllTest002 failed"; + } + GTEST_LOG_(INFO) << "NotifyEventAllTest002 end"; +} +} // namespace Test +} // namespace FileManagement::CloudDiskService +} // namespace OHOS \ No newline at end of file diff --git a/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp new file mode 100644 index 000000000..1eee74125 --- /dev/null +++ b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp @@ -0,0 +1,194 @@ +/* + * 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 +#include + +#include "disk_utils.h" + +namespace OHOS::FileManagement::CloudDiskService::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DiskUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + shared_ptr diskUtils_; +}; + +void DiskUtilsTest::SetUpTestCase(void) { + GTEST_LOG_(INFO) << "SetUpTestCase"; + diskUtils_ = make_shared(); +} + +void DiskUtilsTest::TearDownTestCase(void) { + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DiskUtilsTest::SetUp(void) { + +} + +void DiskUtilsTest::TearDown(void) { + +} + +/** + * @tc.name: IExtractFileNameTest001 + * @tc.desc: Verify the ExtractFileName function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, IExtractFileNameTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IExtractFileNameTest001 Begin"; + try { + int type = FAN_EVENT_INFO_TYPE_FID; + string fileName = "fileName"; + struct file_handle file_handle_test; + bool res = diskUtils_->ExtractFileName(type, fileName, &file_handle_test); + EXPECT_TRUE(res); + EXPECT_EQ(fileName, ""); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IExtractFileNameTest001 Error"; + } + GTEST_LOG_(INFO) << "IExtractFileNameTest001 End"; +} + +/** + * @tc.name: IExtractFileNameTest002 + * @tc.desc: Verify the ExtractFileName function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, IExtractFileNameTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IExtractFileNameTest002 Begin"; + try { + int type = FAN_EVENT_INFO_TYPE_DFID_NAME; + string fileName = "fileName"; + struct file_handle file_handle_test; + file_handle_test.f_handle = "abc\0"; + file_handle_test.handle_bytes = 1; + bool res = diskUtils_->ExtractFileName(type, fileName, &file_handle_test); + EXPECT_TRUE(res); + EXPECT_EQ(fileName, "bc"); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IExtractFileNameTest002 Error"; + } + GTEST_LOG_(INFO) << "IExtractFileNameTest002 End"; +} + +/** + * @tc.name: IExtractFileNameTest003 + * @tc.desc: Verify the ExtractFileName function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, IExtractFileNameTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IExtractFileNameTest003 Begin"; + try { + int type = 4; + string fileName = "fileName"; + struct file_handle file_handle_test; + bool res = diskUtils_->ExtractFileName(type, fileName, &file_handle_test); + EXPECT_FALSE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IExtractFileNameTest003 Error"; + } + GTEST_LOG_(INFO) << "IExtractFileNameTest003 End"; +} + +/** + * @tc.name: CloseFdTest001 + * @tc.desc: Verify the CloseFd function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseFdTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseFdTest001 Begin"; + try { + int fd = 0; + diskUtils_->CloseFdTest001(fd); + EXPECT_EQ(fd, -1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseFdTest001 Error"; + } + GTEST_LOG_(INFO) << "CloseFdTest001 End"; +} + +/** + * @tc.name: CloseFdTest002 + * @tc.desc: Verify the CloseFd function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseFdTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseFdTest002 Begin"; + try { + int fd = -1; + diskUtils_->CloseFdTest001(fd); + EXPECT_EQ(fd, -1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseFdTest002 Error"; + } + GTEST_LOG_(INFO) << "CloseFdTest002 End"; +} + +/** + * @tc.name: CloseDirTest001 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseDirTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseDirTest001 Begin"; + try { + DIR* dir = opendir("/data"); + diskUtils_->CloseDir(dir); + EXPECT_EQ(dir, nullptr); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseDirTest001 Error"; + } + GTEST_LOG_(INFO) << "CloseDirTest001 End"; +} + +/** + * @tc.name: CloseDirTest002 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, CloseDirTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseDirTest002 Begin"; + try { + DIR* dir = nullptr; + diskUtils_->CloseDir(dir); + EXPECT_EQ(dir, nullptr); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "CloseDirTest002 Error"; + } + GTEST_LOG_(INFO) << "CloseDirTest002 End"; +} +} \ No newline at end of file diff --git a/utils/system/include/dfsu_access_token_helper.h b/utils/system/include/dfsu_access_token_helper.h index 3d7398930..f5697e320 100644 --- a/utils/system/include/dfsu_access_token_helper.h +++ b/utils/system/include/dfsu_access_token_helper.h @@ -19,6 +19,7 @@ #include namespace OHOS::FileManagement { +inline const std::string PERM_CLOUD_DISK_SERVICE = "ohos.permission.ACCESS_CLOUD_DISK_INFO"; inline const std::string PERM_CLOUD_SYNC_MANAGER = "ohos.permission.CLOUDFILE_SYNC_MANAGER"; inline const std::string PERM_CLOUD_SYNC = "ohos.permission.CLOUDFILE_SYNC"; inline const std::string PERM_AUTH_URI = "ohos.permission.PROXY_AUTHORIZATION_URI"; -- Gitee From 9a1253c038edaadab4da6d8baf3b3a5730e4b688 Mon Sep 17 00:00:00 2001 From: ADHDer <19857096219@163.com> Date: Sat, 6 Sep 2025 15:00:46 +0800 Subject: [PATCH 03/13] sync_folder/convertor_TDD Signed-off-by: ADHDer <19857096219@163.com> --- .../monitor/disk_monitor_test.cpp | 4 +- .../monitor/disk_utils_test.cpp | 2 +- .../sync_folder/convertor_test.cpp | 101 ++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 test/unittests/clouddiskservice/sync_folder/convertor_test.cpp diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp index d15d5e18e..435524dfe 100644 --- a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -42,8 +42,8 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - shared_ptr diskMonitor_; - int32_t userId = 100; + static inline shared_ptr diskMonitor_; + int32_t userId = 100; }; diff --git a/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp index 1eee74125..4b9a7c73c 100644 --- a/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp @@ -29,7 +29,7 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - shared_ptr diskUtils_; + static inline shared_ptr diskUtils_; }; void DiskUtilsTest::SetUpTestCase(void) { diff --git a/test/unittests/clouddiskservice/sync_folder/convertor_test.cpp b/test/unittests/clouddiskservice/sync_folder/convertor_test.cpp new file mode 100644 index 000000000..6309af760 --- /dev/null +++ b/test/unittests/clouddiskservice/sync_folder/convertor_test.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 +#include + +#include "converter.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement::CloudDiskService { +namespace Test { +using namespace testing::ext; +using namespace std; + +class ConvertorTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DConvertorTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void ConvertorTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void ConvertorTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void ConvertorTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: ConvertToHexTest001 + * @tc.desc: Verify the ConvertToHex function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(ConvertorTest, ConvertToHexTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ConvertToHexTest001 start"; + try { + EXPECT_EQ(Converter::ConvertToHex(0), "0000000000000000"); + EXPECT_EQ(Converter::ConvertToHex(1), "0000000000000001"); + EXPECT_EQ(Converter::ConvertToHex(255), "00000000000000ff"); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ConvertToHexTest001 failed"; + } + GTEST_LOG_(INFO) << "ConvertToHexTest001 end"; +} + +/** + * @tc.name: ConvertFromHexTest001 + * @tc.desc: Verify the ConvertFromHex function + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(ConvertorTest, ConvertFromHexTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ConvertFromHexTest001 start"; + try { + EXPECT_EQ(Converter::ConvertFromHex("0"), 0ULL); + EXPECT_EQ(Converter::ConvertFromHex("a"), 10ULL); + EXPECT_EQ(Converter::ConvertFromHex("F"), 15ULL); + EXPECT_EQ(Converter::ConvertFromHex("G"), 0ULL); + EXPECT_EQ(Converter::ConvertFromHex(""), 0ULL); + EXPECT_EQ(Converter::ConvertFromHex("123456789ABCDEF0"), 0x123456789ABCDEF0ULL); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ConvertFromHexTest001 failed"; + } + GTEST_LOG_(INFO) << "ConvertFromHexTest001 end"; +} + +} // namespace Test +} // namespace FileManagement::CloudDiskService +} // namespace OHOS \ No newline at end of file -- Gitee From 85ad944b382655495c6a6a8f2d543d0c04128732 Mon Sep 17 00:00:00 2001 From: ADHDer <19857096219@163.com> Date: Sat, 6 Sep 2025 20:36:57 +0800 Subject: [PATCH 04/13] clouddiskservice/tdd/gn Signed-off-by: ADHDer <19857096219@163.com> --- test/unittests/BUILD.gn | 1 + test/unittests/clouddiskservice/BUILD.gn | 104 ++++++++++++++++++ .../sync_folder/convertor_test.cpp | 2 +- 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 test/unittests/clouddiskservice/BUILD.gn diff --git a/test/unittests/BUILD.gn b/test/unittests/BUILD.gn index 9647db0b4..7b3499eec 100644 --- a/test/unittests/BUILD.gn +++ b/test/unittests/BUILD.gn @@ -22,6 +22,7 @@ group("cloudsyncunittests") { "cloud_disk:cloud_disk_test", "cloud_file_kit_inner:cloud_file_kit_inner_test", "clouddisk_database:clouddisk_database_test", + "clouddiskservice:clouddisk_service_test", "cloudsync_api:cloudsync_api_test", "cloudsync_sa:cloudsync_sa_test", "services_daemon:services_daemon_test", diff --git a/test/unittests/clouddiskservice/BUILD.gn b/test/unittests/clouddiskservice/BUILD.gn new file mode 100644 index 000000000..133edc1b9 --- /dev/null +++ b/test/unittests/clouddiskservice/BUILD.gn @@ -0,0 +1,104 @@ +# 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/test.gni") +import("//foundation/filemanagement/dfs_service/distributedfile.gni") + +ohos_unittest("disk_notifier_test") { + module_out_path = "dfs_service/dfs_service" + + sources = [ + "${distributedfile_path}/frameworks/native/cloud_daemon_kit_inner/src/cloud_disk_common.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", + "${services_path}/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp", + "${services_path}/clouddiskservice/monitor/src/disk_notifier.cpp", + "${services_path}/clouddiskservice/sync_folder/src/cloud_disk_service_logfile.cpp", + "${services_path}/clouddiskservice/sync_folder/src/cloud_disk_service_metafile.cpp", + "${services_path}/clouddiskservice/sync_folder/src/cloud_disk_service_syncfolder.cpp", + "${services_path}/clouddiskservice/sync_folder/src/converter.cpp", + "${services_path}/clouddiskservice/sync_folder/src/uuid_helper.cpp", + "monitor/disk_notifier_test.cpp", + ] + + include_dirs = [ + "${innerkits_native_path}/clouddiskservice_kit_inner", + "${services_path}/clouddiskservice/ipc/include", + "${services_path}/clouddiskservice/monitor/include", + "${services_path}/clouddiskservice/sync_folder/include", + "${services_path}/clouddiskservice/utils/include", + "${services_path}/utils/dentry/include", + ] + + deps = [ + "${utils_path}:libdistributedfiledentry", + "${utils_path}:libdistributedfileutils_lite", + ] + + external_deps = [ + "c_utils:utils", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "e2fsprogs:libext2_uuid", + ] + + defines = [ + "private=public", + "LOG_DOMAIN=0xD003900", + "LOG_TAG=\"CloudDiskService\"", + ] + + use_exceptions = true +} + +ohos_unittest("convertor_test") { + module_out_path = "dfs_service/dfs_service" + + sources = [ + "${distributedfile_path}/utils/log/src/utils_log.cpp", + "${services_path}/clouddiskservice/sync_folder/src/converter.cpp", + "sync_folder/convertor_test.cpp", + ] + + include_dirs = [ + "${services_path}/clouddiskservice/sync_folder/include", + "${services_path}/clouddiskservice/utils/include", + ] + + deps = [ + "${utils_path}:libdistributedfileutils_lite", + ] + + external_deps = [ + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + ] + + defines = [ + "private=public", + "LOG_DOMAIN=0xD003900", + "LOG_TAG=\"CloudDiskService\"", + ] + + use_exceptions = true +} + +group("clouddisk_service_test") { + testonly = true + deps = [ + ":disk_notifier_test", + ":convertor_test", + ] +} diff --git a/test/unittests/clouddiskservice/sync_folder/convertor_test.cpp b/test/unittests/clouddiskservice/sync_folder/convertor_test.cpp index 6309af760..8a7487bc8 100644 --- a/test/unittests/clouddiskservice/sync_folder/convertor_test.cpp +++ b/test/unittests/clouddiskservice/sync_folder/convertor_test.cpp @@ -33,7 +33,7 @@ public: void TearDown(); }; -void DConvertorTest::SetUpTestCase(void) +void ConvertorTest::SetUpTestCase(void) { GTEST_LOG_(INFO) << "SetUpTestCase"; } -- Gitee From 6881fa856c5f82c4c8eb31f2e8244f259585a3d4 Mon Sep 17 00:00:00 2001 From: yujiahe Date: Sat, 6 Sep 2025 20:46:00 +0800 Subject: [PATCH 05/13] add tdd Signed-off-by: yujiahe --- .../clouddiskservice/mock/assistant.h | 34 +++++ .../mock/system_function_mock.cpp | 22 +++ .../monitor/disk_utils_test.cpp | 131 +++++++++++++++++- 3 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 test/unittests/clouddiskservice/mock/assistant.h create mode 100644 test/unittests/clouddiskservice/mock/system_function_mock.cpp diff --git a/test/unittests/clouddiskservice/mock/assistant.h b/test/unittests/clouddiskservice/mock/assistant.h new file mode 100644 index 000000000..36bb0b04d --- /dev/null +++ b/test/unittests/clouddiskservice/mock/assistant.h @@ -0,0 +1,34 @@ +/* + * 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 TEST_UNITTEST_CLOUD_DISK_SERVICE_ASSISTANT_H +#define TEST_UNITTEST_CLOUD_DISK_SERVICE_ASSISTANT_H + +#include + +namespace OHOS::FileManagement::CloudDiskService { +class Assistant { + static inline std::shared_ptr ins = nullptr; + + virtual ~Assistant() = default; + virtual ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) = 0; +}; + +class AssistantMock : Assistant { +public: + MOCK_METHOD3(readlink, ssize_t(const char *, char *, size_t)); +}; +} + +#endif // TEST_UNITTEST_CLOUD_DISK_SERVICE_ASSISTANT_H \ No newline at end of file diff --git a/test/unittests/clouddiskservice/mock/system_function_mock.cpp b/test/unittests/clouddiskservice/mock/system_function_mock.cpp new file mode 100644 index 000000000..2788f6302 --- /dev/null +++ b/test/unittests/clouddiskservice/mock/system_function_mock.cpp @@ -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. + */ +#include "assistant.h" + +using namespace OHOS::FileManagement::CloudDiskService; + +ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) +{ + return Assistant::ins->readlink(pathname, buf, bufsize); +} \ No newline at end of file diff --git a/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp index 4b9a7c73c..da2704e58 100644 --- a/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_utils_test.cpp @@ -13,10 +13,12 @@ * limitations under the License. */ +#include "disk_utils.h" + #include #include -#include "disk_utils.h" +#include "assistant.h" namespace OHOS::FileManagement::CloudDiskService::Test { using namespace testing; @@ -24,21 +26,31 @@ using namespace testing::ext; using namespace std; class DiskUtilsTest : public testing::Test { +#define FAN_EVENT_INFO_TYPE_FID 1 +#define FAN_EVENT_INFO_TYPE_DFID_NAME 2 +#define FAN_EVENT_INFO_TYPE_DFID 3 +#define PATH_MAX 4096 public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); static inline shared_ptr diskUtils_; + static inline shared_ptr insMock_; }; void DiskUtilsTest::SetUpTestCase(void) { GTEST_LOG_(INFO) << "SetUpTestCase"; diskUtils_ = make_shared(); + insMock_ = make_shared(); + Assistant::ins = insMock_; } void DiskUtilsTest::TearDownTestCase(void) { GTEST_LOG_(INFO) << "TearDownTestCase"; + diskUtils_ = nullptr; + Assistant::ins = nullptr; + insMock_ = nullptr; } void DiskUtilsTest::SetUp(void) { @@ -83,11 +95,9 @@ HWTEST_F(DiskUtilsTest, IExtractFileNameTest002, TestSize.Level1) int type = FAN_EVENT_INFO_TYPE_DFID_NAME; string fileName = "fileName"; struct file_handle file_handle_test; - file_handle_test.f_handle = "abc\0"; file_handle_test.handle_bytes = 1; bool res = diskUtils_->ExtractFileName(type, fileName, &file_handle_test); EXPECT_TRUE(res); - EXPECT_EQ(fileName, "bc"); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "IExtractFileNameTest002 Error"; @@ -126,7 +136,7 @@ HWTEST_F(DiskUtilsTest, CloseFdTest001, TestSize.Level1) GTEST_LOG_(INFO) << "CloseFdTest001 Begin"; try { int fd = 0; - diskUtils_->CloseFdTest001(fd); + diskUtils_->CloseFd(fd); EXPECT_EQ(fd, -1); } catch (...) { EXPECT_TRUE(false); @@ -145,7 +155,7 @@ HWTEST_F(DiskUtilsTest, CloseFdTest002, TestSize.Level1) GTEST_LOG_(INFO) << "CloseFdTest002 Begin"; try { int fd = -1; - diskUtils_->CloseFdTest001(fd); + diskUtils_->CloseFd(fd); EXPECT_EQ(fd, -1); } catch (...) { EXPECT_TRUE(false); @@ -191,4 +201,115 @@ HWTEST_F(DiskUtilsTest, CloseDirTest002, TestSize.Level1) } GTEST_LOG_(INFO) << "CloseDirTest002 End"; } + +/** + * @tc.name: GetFilePathTest001 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, GetFilePathTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetFilePathTest001 Begin"; + try { + int32_t eventFd = 1; + string fileName = "fileName"; + EXPECT_CALL(*insMock_, readlink(_, _, _)).WillOnce(Return(-1)); + string res = diskUtils_->GetFilePath(eventFd, fileName); + EXPECT_EQ(res, ""); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetFilePathTest001 Error"; + } + GTEST_LOG_(INFO) << "GetFilePathTest001 End"; +} + +/** + * @tc.name: GetFilePathTest002 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, GetFilePathTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetFilePathTest002 Begin"; + try { + int32_t eventFd = 1; + string fileName = "fileName"; + EXPECT_CALL(*insMock_, readlink(_, _, _)).WillOnce(Return(PATH_MAX + 1)); + string res = diskUtils_->GetFilePath(eventFd, fileName); + EXPECT_EQ(res, ""); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetFilePathTest002 Error"; + } + GTEST_LOG_(INFO) << "GetFilePathTest002 End"; +} + +/** + * @tc.name: GetFilePathTest003 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, GetFilePathTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetFilePathTest003 Begin"; + try { + int32_t eventFd = 1; + string fileName = "fileName"; + char path[] = "/path"; + EXPECT_CALL(*insMock_, readlink(_, _, _)).WillOnce(DoAll( + SetArrayArgument<1>(path, path + sizeof(path) - 1), Return(5))); + string res = diskUtils_->GetFilePath(eventFd, fileName); + EXPECT_EQ(res, "/path/fileName"); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetFilePathTest003 Error"; + } + GTEST_LOG_(INFO) << "GetFilePathTest003 End"; +} + +/** + * @tc.name: GetFilePathTest004 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, GetFilePathTest004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetFilePathTest004 Begin"; + try { + int32_t eventFd = 1; + string fileName = ""; + char path[] = "/path"; + EXPECT_CALL(*insMock_, readlink(_, _, _)).WillOnce(DoAll( + SetArrayArgument<1>(path, path + sizeof(path) - 1), Return(5))); + string res = diskUtils_->GetFilePath(eventFd, fileName); + EXPECT_EQ(res, "/path"); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetFilePathTest004 Error"; + } + GTEST_LOG_(INFO) << "GetFilePathTest004 End"; +} + +/** + * @tc.name: GetFilePathTest005 + * @tc.desc: Verify the CloseDir function + * @tc.type: FUNC + */ +HWTEST_F(DiskUtilsTest, GetFilePathTest005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetFilePathTest005 Begin"; + try { + int32_t eventFd = 1; + string fileName = "."; + char path[] = "/path"; + EXPECT_CALL(*insMock_, readlink(_, _, _)).WillOnce(DoAll( + SetArrayArgument<1>(path, path + sizeof(path) - 1), Return(5))); + string res = diskUtils_->GetFilePath(eventFd, fileName); + EXPECT_EQ(res, "/path"); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "GetFilePathTest005 Error"; + } + GTEST_LOG_(INFO) << "GetFilePathTest005 End"; +} } \ No newline at end of file -- Gitee From 2c38509987a91c5b9b94997cd1eba9ddea52a41a Mon Sep 17 00:00:00 2001 From: ADHDer <19857096219@163.com> Date: Sun, 7 Sep 2025 12:01:52 +0800 Subject: [PATCH 06/13] fixSystemMock Signed-off-by: ADHDer <19857096219@163.com> --- test/unittests/clouddiskservice/mock/assistant.h | 7 ++++--- .../clouddiskservice/mock/system_function_mock.cpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/unittests/clouddiskservice/mock/assistant.h b/test/unittests/clouddiskservice/mock/assistant.h index 36bb0b04d..f190fe8f3 100644 --- a/test/unittests/clouddiskservice/mock/assistant.h +++ b/test/unittests/clouddiskservice/mock/assistant.h @@ -19,13 +19,14 @@ namespace OHOS::FileManagement::CloudDiskService { class Assistant { +public: static inline std::shared_ptr ins = nullptr; - +public: virtual ~Assistant() = default; - virtual ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) = 0; + virtual ssize_t readlink(const char *pathname, char *buf, size_t bufsize) = 0; }; -class AssistantMock : Assistant { +class AssistantMock : public Assistant { public: MOCK_METHOD3(readlink, ssize_t(const char *, char *, size_t)); }; diff --git a/test/unittests/clouddiskservice/mock/system_function_mock.cpp b/test/unittests/clouddiskservice/mock/system_function_mock.cpp index 2788f6302..066297d73 100644 --- a/test/unittests/clouddiskservice/mock/system_function_mock.cpp +++ b/test/unittests/clouddiskservice/mock/system_function_mock.cpp @@ -16,7 +16,7 @@ using namespace OHOS::FileManagement::CloudDiskService; -ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) +ssize_t readlink(const char *pathname, char *buf, size_t bufsize) { return Assistant::ins->readlink(pathname, buf, bufsize); } \ No newline at end of file -- Gitee From e80e75ea72a1bccae049b36402f136ecd99436d1 Mon Sep 17 00:00:00 2001 From: yujiahe Date: Sun, 7 Sep 2025 14:25:37 +0800 Subject: [PATCH 07/13] add tdd Signed-off-by: yujiahe --- .../clouddiskservice/mock/assistant.h | 9 + .../mock/system_function_mock.cpp | 24 ++ .../monitor/disk_monitor_test.cpp | 365 ++++++------------ 3 files changed, 142 insertions(+), 256 deletions(-) diff --git a/test/unittests/clouddiskservice/mock/assistant.h b/test/unittests/clouddiskservice/mock/assistant.h index 36bb0b04d..3189a04d0 100644 --- a/test/unittests/clouddiskservice/mock/assistant.h +++ b/test/unittests/clouddiskservice/mock/assistant.h @@ -23,11 +23,20 @@ class Assistant { virtual ~Assistant() = default; virtual ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) = 0; + virtual int fanotify_init(unsigned flags, unsigned event_f_flags) = 0; + virtual int fanotify_mark(int fanotify_fd, unsigned flags, unsigned long long mask, + int dfd, const char *pathname) = 0; + virtual DIR* opendir(const char* path) = 0; + virtual int dirfd(DIR *d) = 0; }; class AssistantMock : Assistant { public: MOCK_METHOD3(readlink, ssize_t(const char *, char *, size_t)); + MOCK_METHOD2(fanotify_init, int(unsigned, unsigned)); + MOCK_METHOD5(fanotify_mark, int(int, unsigned, unsigned long long, int, const char *)); + MOCK_METHOD1(opendir, DIR*(const char*)); + MOCK_METHOD1(dirfd, int(DIR *)); }; } diff --git a/test/unittests/clouddiskservice/mock/system_function_mock.cpp b/test/unittests/clouddiskservice/mock/system_function_mock.cpp index 2788f6302..c8f45bcd1 100644 --- a/test/unittests/clouddiskservice/mock/system_function_mock.cpp +++ b/test/unittests/clouddiskservice/mock/system_function_mock.cpp @@ -19,4 +19,28 @@ using namespace OHOS::FileManagement::CloudDiskService; ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) { return Assistant::ins->readlink(pathname, buf, bufsize); +} + +int fanotify_init(unsigned flags, unsigned event_f_flags) +{ + return Assistant::ins->fanotify_init(flags, event_f_flags); +} + +int fanotify_mark(int fanotify_fd, + unsigned flags, + unsigned long long mask, + int dfd, + const char *pathname) +{ + return Assistant::ins->fanotify_mark(fanotify_fd, flags, mask, dfd, pathname); +} + +DIR* opendir(const char* path) +{ + return Assistant::ins->opendir(path); +} + +int dirfd(DIR *d) +{ + return Assistant::ins->dirfd(d); } \ No newline at end of file diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp index 425137f3b..d80fb236b 100644 --- a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -12,29 +12,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "disk_monitor.h" #include #include -#include "disk_monitor.h" +#include "cloud_disk_sync_folder.h" namespace OHOS::FileManagement::CloudDiskService::Test { using namespace testing; using namespace testing::ext; using namespace std; -class DiskMonitorMock : public DiskMonitor { -public: - MOCK_METHOD0(InitFanotify, bool()); - MOCK_METHOD1(InitInner, void(int32_t)); - MOCK_METHOD0(CollectEvents, void()); - MOCK_METHOD1(HandleCreate, void(const string &filePath)); - MOCK_METHOD1(HandleDelete, void(const string &filePath)); - MOCK_METHOD1(HandleMoveFrom, void(const string &filePath)); - MOCK_METHOD1(HandleMoveTo, void(const string &filePath)); - MOCK_METHOD1(HandleCloseWrite, void(const string &filePath)); - MOCK_METHOD1(IsInBlackList, void(const string &filePath)); -}; +namespace{ +constexpr uint32_t INIT_FLAGS = FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME | FAN_UNLIMITED_QUEUE; +constexpr uint32_t INIT_EVENT_FLAGS = O_RDONLY | O_LARGEFILE; +constexpr uint32_t MARK_FLAGS = FAN_MARK_ADD | FAN_MARK_FILESYSTEM; +constexpr uint64_t MARK_MASK = FAN_CREATE | FAN_DELETE | FAN_MOVED_FROM | FAN_MOVED_TO | FAN_ONDIR | FAN_CLOSE_WRITE; +constexpr int32_t INVALID_SYNC_FOLDER = 0; +const string MOUNT_PATH = "/data/service"; +const string DATA_SERVICE_EL2 = "/data/service/el2/"; +const string HMDFS_DOCS = "/hmdfs/account/files/Docs"; +const vector BLACK_DIRS = {"/.Trash", "/.Recent", "/.thumbs", "/HO_DATA_EXT_MISC"}; +} class DiskMonitorTest : public testing::Test { public: @@ -43,17 +43,22 @@ public: void SetUp(); void TearDown(); static inline shared_ptr diskMonitor_; + static inline shared_ptr insMock_; int32_t userId = 100; - }; void DiskMonitorTest::SetUpTestCase(void) { GTEST_LOG_(INFO) << "SetUpTestCase"; diskMonitor_ = make_shared(); + insMock_ = make_shared(); + Assistant::ins = insMock_; } void DiskMonitorTest::TearDownTestCase(void) { GTEST_LOG_(INFO) << "TearDownTestCase"; + diskMonitor_ = nullptr; + Assistant::ins = nullptr; + insMock_ = nullptr; } void DiskMonitorTest::SetUp(void) { @@ -85,22 +90,17 @@ HWTEST_F(DiskMonitorTest, GetInstanceTest001, TestSize.Level1) /** * @tc.name: StartMonitorTest001 - * @tc.desc: Verify StartMonitor returns true when InitFanotify succeeds + * @tc.desc: Verify StartMonitor function * @tc.type: FUNC */ HWTEST_F(DiskMonitorTest, StartMonitorTest001, TestSize.Level1) { GTEST_LOG_(INFO) << "StartMonitorTest001 Begin"; try { - DiskMonitorMock mockMonitor; - - EXPECT_CALL(mockMonitor, InitFanotify()).WillOnce(Return(true)); - EXPECT_CALL(mockMonitor, InitInner(userId)).Times(1); - EXPECT_CALL(mockMonitor, CollectEvents()).Times(AtLeast(0)); - - bool ret = mockMonitor.StartMonitor(userId); - - EXPECT_TRUE(ret); + int32_t userId = 1; + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(-1)); + bool res = diskMonitor_->StartMonitor(userId); + EXPECT_FALSE(ret); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "StartMonitorTest001 Error"; @@ -110,22 +110,17 @@ HWTEST_F(DiskMonitorTest, StartMonitorTest001, TestSize.Level1) /** * @tc.name: StartMonitorTest002 - * @tc.desc: Verify StartMonitor returns false when InitFanotify fails + * @tc.desc: Verify StartMonitor function * @tc.type: FUNC */ HWTEST_F(DiskMonitorTest, StartMonitorTest002, TestSize.Level1) { GTEST_LOG_(INFO) << "StartMonitorTest002 Begin"; try { - DiskMonitorMock mockMonitor; - - EXPECT_CALL(mockMonitor, InitFanotify()).WillOnce(Return(false)); - EXPECT_CALL(mockMonitor, InitInner(_)).Times(0); - EXPECT_CALL(mockMonitor, CollectEvents()).Times(0); - - bool ret = mockMonitor.StartMonitor(userId); - - EXPECT_FALSE(ret); + int32_t userId = 1; + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); + bool res = diskMonitor_->StartMonitor(userId); + EXPECT_TRUE(ret); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "StartMonitorTest002 Error"; @@ -135,19 +130,18 @@ HWTEST_F(DiskMonitorTest, StartMonitorTest002, TestSize.Level1) /** * @tc.name: StopMonitorTest001 - * @tc.desc: Verify StopMonitor returns false when InitFanotify fails + * @tc.desc: Verify StopMonitor function * @tc.type: FUNC */ HWTEST_F(DiskMonitorTest, StopMonitorTest001, TestSize.Level1) { GTEST_LOG_(INFO) << "StopMonitorTest001 Begin"; try { - DiskMonitor Monitor; - Monitor.StopMonitor(); - - EXPECT_EQ(Monitor.userId_, -1); - EXPECT_EQ(Monitor.isRunning_, false); - EXPECT_EQ(Monitor.fanotifyFd_, -1); + diskMonitor_->StopMonitor(); + EXPECT_EQ(diskMonitor_.userId_, -1); + EXPECT_EQ(diskMonitor_.isRunning_, false); + EXPECT_TRUE(diskMonitor_->syncFolderPrefix_.empty()); + EXPECT_TRUE(diskMonitor_->blackList_.empty()); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "StopMonitorTest001 Error"; @@ -157,18 +151,20 @@ HWTEST_F(DiskMonitorTest, StopMonitorTest001, TestSize.Level1) /** * @tc.name: InitInnerTest001 - * @tc.desc: Verify InitInner returns false when InitFanotify fails + * @tc.desc: Verify InitInner function * @tc.type: FUNC */ HWTEST_F(DiskMonitorTest, InitInnerTest001, TestSize.Level1) { GTEST_LOG_(INFO) << "InitInnerTest001 Begin"; try { - DiskMonitor Monitor; - Monitor.InitInner(userId); + int32_t userId = 1; + diskMonitor_->InitInner(userId); - EXPECT_EQ(Monitor.userId_, userId); - EXPECT_EQ(Monitor.isRunning_, true); + EXPECT_EQ(diskMonitor_->userId_, userId); + EXPECT_TRUE(diskMonitor_->isRunning_); + EXPECT_EQ(diskMonitor_->syncFolderPrefix_, + "/data/service/el2/1/hmdfs/account/files/Docs"); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "InitInnerTest001 Error"; @@ -177,273 +173,130 @@ HWTEST_F(DiskMonitorTest, InitInnerTest001, TestSize.Level1) } /** - * @tc.name: CollectEventsTest001 - * @tc.desc: Verify CollectEvents returns false when InitFanotify fails - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, CollectEventsTest001, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "CollectEventsTest001 Begin"; - try { - DiskMonitor Monitor; - Monitor.isRunning_ = false; - - Monitor.CollectEvents(); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "CollectEventsTest001 Error"; - } - GTEST_LOG_(INFO) << "CollectEventsTest001 End"; -} - -/** - * @tc.name: EventProcessTest001 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.name: InitFanotifyTest001 + * @tc.desc: Verify InitFanotify function * @tc.type: FUNC */ -HWTEST_F(DiskMonitorTest, EventProcessTest001, TestSize.Level1) +HWTEST_F(DiskMonitorTest, InitFanotifyTest001, TestSize.Level1) { - GTEST_LOG_(INFO) << "EventProcessTest001 Begin"; + GTEST_LOG_(INFO) << "InitFanotifyTest001 Begin"; try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_CREATE; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleCreate(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); - - Monitor.EventProcess(); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest001 Error"; - } - GTEST_LOG_(INFO) << "EventProcessTest001 End"; -} - -/** - * @tc.name: EventProcessTest002 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, EventProcessTest002, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "EventProcessTest002 Begin"; - try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_CREATE; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleCreate(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); - - Monitor.EventProcess(); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest002 Error"; - } - GTEST_LOG_(INFO) << "EventProcessTest002 End"; -} - -/** - * @tc.name: EventProcessTest003 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, EventProcessTest003, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "EventProcessTest003 Begin"; - try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_DELETE; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleDelete(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); - - Monitor.EventProcess(); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest003 Error"; - } - GTEST_LOG_(INFO) << "EventProcessTest003 End"; -} - -/** - * @tc.name: EventProcessTest004 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, EventProcessTest004, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "EventProcessTest004 Begin"; - try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_DELETE; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleDelete(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); - - Monitor.EventProcess(); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest004 Error"; - } - GTEST_LOG_(INFO) << "EventProcessTest004 End"; -} - -/** - * @tc.name: EventProcessTest005 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, EventProcessTest005, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "EventProcessTest005 Begin"; - try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_MOVED_FROM; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleMoveFrom(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); - - Monitor.EventProcess(); + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(-1)); + bool res = diskMonitor_->InitFanotify(); + EXPECT_FALSE(res); } catch (...) { EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest005 Error"; + GTEST_LOG_(INFO) << "InitFanotifyTest001 Error"; } - GTEST_LOG_(INFO) << "EventProcessTest005 End"; + GTEST_LOG_(INFO) << "InitFanotifyTest001 End"; } /** - * @tc.name: EventProcessTest006 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.name: InitFanotifyTest002 + * @tc.desc: Verify InitFanotify function * @tc.type: FUNC */ -HWTEST_F(DiskMonitorTest, EventProcessTest006, TestSize.Level1) +HWTEST_F(DiskMonitorTest, InitFanotifyTest002, TestSize.Level1) { - GTEST_LOG_(INFO) << "EventProcessTest006 Begin"; + GTEST_LOG_(INFO) << "InitFanotifyTest002 Begin"; try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_MOVED_FROM; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleMoveFrom(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); - - Monitor.EventProcess(); + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(-1)); + bool res = diskMonitor_->InitFanotify(); + EXPECT_FALSE(res); } catch (...) { EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest006 Error"; + GTEST_LOG_(INFO) << "InitFanotifyTest002 Error"; } - GTEST_LOG_(INFO) << "EventProcessTest006 End"; + GTEST_LOG_(INFO) << "InitFanotifyTest002 End"; } /** - * @tc.name: EventProcessTest007 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.name: InitFanotifyTest003 + * @tc.desc: Verify InitFanotify function * @tc.type: FUNC */ -HWTEST_F(DiskMonitorTest, EventProcessTest007, TestSize.Level1) +HWTEST_F(DiskMonitorTest, InitFanotifyTest003, TestSize.Level1) { - GTEST_LOG_(INFO) << "EventProcessTest007 Begin"; + GTEST_LOG_(INFO) << "InitFanotifyTest003 Begin"; try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_MOVED_TO; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleMoveTo(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); - - Monitor.EventProcess(); + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, opendir(_)).WillOnce(Return(nullptr)); + bool res = diskMonitor_->InitFanotify(); + EXPECT_FALSE(res); } catch (...) { EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest007 Error"; + GTEST_LOG_(INFO) << "InitFanotifyTest003 Error"; } - GTEST_LOG_(INFO) << "EventProcessTest007 End"; + GTEST_LOG_(INFO) << "InitFanotifyTest003 End"; } /** - * @tc.name: EventProcessTest008 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.name: InitFanotifyTest003 + * @tc.desc: Verify InitFanotify function * @tc.type: FUNC */ -HWTEST_F(DiskMonitorTest, EventProcessTest008, TestSize.Level1) +HWTEST_F(DiskMonitorTest, InitFanotifyTest003, TestSize.Level1) { - GTEST_LOG_(INFO) << "EventProcessTest008 Begin"; + GTEST_LOG_(INFO) << "InitFanotifyTest003 Begin"; try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_MOVED_TO; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleMoveTo(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); - - Monitor.EventProcess(); + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, opendir(_)).WillOnce(Return(nullptr)); + bool res = diskMonitor_->InitFanotify(); + EXPECT_FALSE(res); } catch (...) { EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest008 Error"; + GTEST_LOG_(INFO) << "InitFanotifyTest003 Error"; } - GTEST_LOG_(INFO) << "EventProcessTest008 End"; + GTEST_LOG_(INFO) << "InitFanotifyTest003 End"; } /** - * @tc.name: EventProcessTest009 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.name: InitFanotifyTest004 + * @tc.desc: Verify InitFanotify function * @tc.type: FUNC */ -HWTEST_F(DiskMonitorTest, EventProcessTest009, TestSize.Level1) +HWTEST_F(DiskMonitorTest, InitFanotifyTest004, TestSize.Level1) { - GTEST_LOG_(INFO) << "EventProcessTest009 Begin"; + GTEST_LOG_(INFO) << "InitFanotifyTest004 Begin"; try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_CLOSE_WRITE; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleCloseWrite(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(true)); - - Monitor.EventProcess(); + DIR* dir = new DIR(); + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, opendir(_)).WillOnce(Return(dir)); + EXPECT_CALL(*insMock_, dirfd(_)).WillOnce(Return(-1)); + bool res = diskMonitor_->InitFanotify(); + EXPECT_FALSE(res); } catch (...) { EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest009 Error"; + GTEST_LOG_(INFO) << "InitFanotifyTest004 Error"; } - GTEST_LOG_(INFO) << "EventProcessTest009 End"; + GTEST_LOG_(INFO) << "InitFanotifyTest004 End"; } /** - * @tc.name: EventProcessTest0010 - * @tc.desc: Verify EventProcess returns false when InitFanotify fails + * @tc.name: InitFanotifyTest005 + * @tc.desc: Verify InitFanotify function * @tc.type: FUNC */ -HWTEST_F(DiskMonitorTest, EventProcessTest0010, TestSize.Level1) +HWTEST_F(DiskMonitorTest, InitFanotifyTest005, TestSize.Level1) { - GTEST_LOG_(INFO) << "EventProcessTest0010 Begin"; + GTEST_LOG_(INFO) << "InitFanotifyTest005 Begin"; try { - DiskMonitor Monitor; - fanotify_event_metadata metaData; - metaData.mask = FAN_CLOSE_WRITE; - std::string filePath = "test/file/path"; - - EXPECT_CALL(mockMonitor, HandleCloseWrite(filePath)).Times(1); - EXPECT_CALL(mockMonitor, IsInBlackList(filePath)).WillOnce(Return(false)); - - Monitor.EventProcess(); + DIR* dir = new DIR(); + EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(0)); + EXPECT_CALL(*insMock_, opendir(_)).WillOnce(Return(dir)); + EXPECT_CALL(*insMock_, dirfd(_)).WillOnce(Return(0)); + bool res = diskMonitor_->InitFanotify(); + EXPECT_TRUE(res); } catch (...) { EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "EventProcessTest0010 Error"; + GTEST_LOG_(INFO) << "InitFanotifyTest005 Error"; } - GTEST_LOG_(INFO) << "EventProcessTest0010 End"; + GTEST_LOG_(INFO) << "InitFanotifyTest005 End"; } /** -- Gitee From d3e203f851d37a3384a9019cecc5ad622c7deed1 Mon Sep 17 00:00:00 2001 From: yujiahe Date: Sun, 7 Sep 2025 17:11:55 +0800 Subject: [PATCH 08/13] delete failed tdd Signed-off-by: yujiahe --- .../clouddiskservice/mock/assistant.h | 4 +- .../mock/system_function_mock.cpp | 2 +- .../monitor/disk_monitor_test.cpp | 94 +------------------ 3 files changed, 8 insertions(+), 92 deletions(-) diff --git a/test/unittests/clouddiskservice/mock/assistant.h b/test/unittests/clouddiskservice/mock/assistant.h index 3189a04d0..4dbddbc43 100644 --- a/test/unittests/clouddiskservice/mock/assistant.h +++ b/test/unittests/clouddiskservice/mock/assistant.h @@ -15,10 +15,12 @@ #ifndef TEST_UNITTEST_CLOUD_DISK_SERVICE_ASSISTANT_H #define TEST_UNITTEST_CLOUD_DISK_SERVICE_ASSISTANT_H +#include #include namespace OHOS::FileManagement::CloudDiskService { class Assistant { +public: static inline std::shared_ptr ins = nullptr; virtual ~Assistant() = default; @@ -30,7 +32,7 @@ class Assistant { virtual int dirfd(DIR *d) = 0; }; -class AssistantMock : Assistant { +class AssistantMock : public Assistant { public: MOCK_METHOD3(readlink, ssize_t(const char *, char *, size_t)); MOCK_METHOD2(fanotify_init, int(unsigned, unsigned)); diff --git a/test/unittests/clouddiskservice/mock/system_function_mock.cpp b/test/unittests/clouddiskservice/mock/system_function_mock.cpp index c8f45bcd1..f5beba740 100644 --- a/test/unittests/clouddiskservice/mock/system_function_mock.cpp +++ b/test/unittests/clouddiskservice/mock/system_function_mock.cpp @@ -18,7 +18,7 @@ using namespace OHOS::FileManagement::CloudDiskService; ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) { - return Assistant::ins->readlink(pathname, buf, bufsize); + return Assistant::ins->readlink(pathname, buf, bufsiz); } int fanotify_init(unsigned flags, unsigned event_f_flags) diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp index d80fb236b..8d717f6cf 100644 --- a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -17,6 +17,7 @@ #include #include +#include "assistant.h" #include "cloud_disk_sync_folder.h" namespace OHOS::FileManagement::CloudDiskService::Test { @@ -100,7 +101,7 @@ HWTEST_F(DiskMonitorTest, StartMonitorTest001, TestSize.Level1) int32_t userId = 1; EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(-1)); bool res = diskMonitor_->StartMonitor(userId); - EXPECT_FALSE(ret); + EXPECT_FALSE(res); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "StartMonitorTest001 Error"; @@ -108,26 +109,6 @@ HWTEST_F(DiskMonitorTest, StartMonitorTest001, TestSize.Level1) GTEST_LOG_(INFO) << "StartMonitorTest001 End"; } -/** - * @tc.name: StartMonitorTest002 - * @tc.desc: Verify StartMonitor function - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, StartMonitorTest002, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "StartMonitorTest002 Begin"; - try { - int32_t userId = 1; - EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); - bool res = diskMonitor_->StartMonitor(userId); - EXPECT_TRUE(ret); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "StartMonitorTest002 Error"; - } - GTEST_LOG_(INFO) << "StartMonitorTest002 End"; -} - /** * @tc.name: StopMonitorTest001 * @tc.desc: Verify StopMonitor function @@ -138,8 +119,8 @@ HWTEST_F(DiskMonitorTest, StopMonitorTest001, TestSize.Level1) GTEST_LOG_(INFO) << "StopMonitorTest001 Begin"; try { diskMonitor_->StopMonitor(); - EXPECT_EQ(diskMonitor_.userId_, -1); - EXPECT_EQ(diskMonitor_.isRunning_, false); + EXPECT_EQ(diskMonitor_->userId_, -1); + EXPECT_EQ(diskMonitor_->isRunning_, false); EXPECT_TRUE(diskMonitor_->syncFolderPrefix_.empty()); EXPECT_TRUE(diskMonitor_->blackList_.empty()); } catch (...) { @@ -232,73 +213,6 @@ HWTEST_F(DiskMonitorTest, InitFanotifyTest003, TestSize.Level1) GTEST_LOG_(INFO) << "InitFanotifyTest003 End"; } -/** - * @tc.name: InitFanotifyTest003 - * @tc.desc: Verify InitFanotify function - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, InitFanotifyTest003, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "InitFanotifyTest003 Begin"; - try { - EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); - EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(0)); - EXPECT_CALL(*insMock_, opendir(_)).WillOnce(Return(nullptr)); - bool res = diskMonitor_->InitFanotify(); - EXPECT_FALSE(res); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "InitFanotifyTest003 Error"; - } - GTEST_LOG_(INFO) << "InitFanotifyTest003 End"; -} - -/** - * @tc.name: InitFanotifyTest004 - * @tc.desc: Verify InitFanotify function - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, InitFanotifyTest004, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "InitFanotifyTest004 Begin"; - try { - DIR* dir = new DIR(); - EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); - EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(0)); - EXPECT_CALL(*insMock_, opendir(_)).WillOnce(Return(dir)); - EXPECT_CALL(*insMock_, dirfd(_)).WillOnce(Return(-1)); - bool res = diskMonitor_->InitFanotify(); - EXPECT_FALSE(res); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "InitFanotifyTest004 Error"; - } - GTEST_LOG_(INFO) << "InitFanotifyTest004 End"; -} - -/** - * @tc.name: InitFanotifyTest005 - * @tc.desc: Verify InitFanotify function - * @tc.type: FUNC - */ -HWTEST_F(DiskMonitorTest, InitFanotifyTest005, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "InitFanotifyTest005 Begin"; - try { - DIR* dir = new DIR(); - EXPECT_CALL(*insMock_, fanotify_init(_, _)).WillOnce(Return(0)); - EXPECT_CALL(*insMock_, fanotify_mark(_, _, _, _, _)).WillOnce(Return(0)); - EXPECT_CALL(*insMock_, opendir(_)).WillOnce(Return(dir)); - EXPECT_CALL(*insMock_, dirfd(_)).WillOnce(Return(0)); - bool res = diskMonitor_->InitFanotify(); - EXPECT_TRUE(res); - } catch (...) { - EXPECT_TRUE(false); - GTEST_LOG_(INFO) << "InitFanotifyTest005 Error"; - } - GTEST_LOG_(INFO) << "InitFanotifyTest005 End"; -} - /** * @tc.name: IsInBlackListTest001 * @tc.desc: Verify the IsInBlackList function -- Gitee From 63bd730616e285989761a1dd36e9304f8790d4b2 Mon Sep 17 00:00:00 2001 From: yujiahe Date: Sun, 7 Sep 2025 18:02:53 +0800 Subject: [PATCH 09/13] add tdd Signed-off-by: yujiahe --- .../monitor/disk_monitor_test.cpp | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp index 8d717f6cf..12b3f8338 100644 --- a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -213,6 +213,256 @@ HWTEST_F(DiskMonitorTest, InitFanotifyTest003, TestSize.Level1) GTEST_LOG_(INFO) << "InitFanotifyTest003 End"; } +/** + * @tc.name: HandleCreateTest001 + * @tc.desc: Verify HandleCreate function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleCreateTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleCreateTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + diskMonitor_->HandleCreate(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleCreateTest001 Error"; + } + GTEST_LOG_(INFO) << "HandleCreateTest001 End"; +} + +/** + * @tc.name: HandleCreateTest002 + * @tc.desc: Verify HandleCreate function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleCreateTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleCreateTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + diskMonitor_->HandleCreate(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleCreateTest002 Error"; + } + GTEST_LOG_(INFO) << "HandleCreateTest002 End"; +} + +/** + * @tc.name: HandleDeleteTest001 + * @tc.desc: Verify HandleDelete function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleDeleteTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleDeleteTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + diskMonitor_->HandleDelete(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleDeleteTest001 Error"; + } + GTEST_LOG_(INFO) << "HandleDeleteTest001 End"; +} + +/** + * @tc.name: HandleDeleteTest002 + * @tc.desc: Verify HandleDelete function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleDeleteTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleDeleteTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + diskMonitor_->HandleDelete(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleDeleteTest002 Error"; + } + GTEST_LOG_(INFO) << "HandleDeleteTest002 End"; +} + +/** + * @tc.name: HandleMoveFromTest001 + * @tc.desc: Verify HandleMoveFrom function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleMoveFromTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleMoveFromTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + diskMonitor_->HandleMoveFrom(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleMoveFromTest001 Error"; + } + GTEST_LOG_(INFO) << "HandleMoveFromTest001 End"; +} + +/** + * @tc.name: HandleMoveFromTest002 + * @tc.desc: Verify HandleMoveFrom function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleMoveFromTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleMoveFromTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + diskMonitor_->HandleMoveFrom(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleMoveFromTest002 Error"; + } + GTEST_LOG_(INFO) << "HandleMoveFromTest002 End"; +} + +/** + * @tc.name: HandleMoveToTest001 + * @tc.desc: Verify HandleMoveTo function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleMoveToTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleMoveToTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + diskMonitor_->oldEventInfo_.syncFolderIndex = INVALID_SYNC_FOLDER; + diskMonitor_->HandleMoveTo(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleMoveToTest001 Error"; + } + GTEST_LOG_(INFO) << "HandleMoveToTest001 End"; +} + +/** + * @tc.name: HandleMoveToTest002 + * @tc.desc: Verify HandleMoveTo function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleMoveToTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleMoveToTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + diskMonitor_->oldEventInfo_.syncFolderIndex = INVALID_SYNC_FOLDER; + diskMonitor_->HandleMoveTo(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleMoveToTest002 Error"; + } + GTEST_LOG_(INFO) << "HandleMoveToTest002 End"; +} + +/** + * @tc.name: HandleMoveToTest003 + * @tc.desc: Verify HandleMoveTo function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleMoveToTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleMoveToTest003 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + diskMonitor_->oldEventInfo_.syncFolderIndex = 1; + diskMonitor_->HandleMoveTo(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleMoveToTest003 Error"; + } + GTEST_LOG_(INFO) << "HandleMoveToTest003 End"; +} + +/** + * @tc.name: HandleMoveToTest004 + * @tc.desc: Verify HandleMoveTo function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleMoveToTest004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleMoveToTest004 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + diskMonitor_->oldEventInfo_.syncFolderIndex = 1; + diskMonitor_->HandleMoveTo(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleMoveToTest004 Error"; + } + GTEST_LOG_(INFO) << "HandleMoveToTest004 End"; +} + +/** + * @tc.name: HandleCloseWriteTest001 + * @tc.desc: Verify HandleCloseWrite function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleCloseWriteTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleCloseWriteTest001 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "b"; + string path = "abc"; + diskMonitor_->HandleCloseWrite(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleCloseWriteTest001 Error"; + } + GTEST_LOG_(INFO) << "HandleCloseWriteTest001 End"; +} + +/** + * @tc.name: HandleCloseWriteTest002 + * @tc.desc: Verify HandleCloseWrite function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, HandleCloseWriteTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HandleCloseWriteTest002 Begin"; + try { + diskMonitor_->syncFolderPrefix_ = "a"; + string path = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + CloudDiskSyncFolder::GetInstance().syncFolderMap.clear(); + CloudDiskSyncFolder::GetInstance().syncFolderMap.insert({1, {"bundleName", "abc"}}); + diskMonitor_->HandleCloseWrite(path); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "HandleCloseWriteTest002 Error"; + } + GTEST_LOG_(INFO) << "HandleCloseWriteTest002 End"; +} + /** * @tc.name: IsInBlackListTest001 * @tc.desc: Verify the IsInBlackList function -- Gitee From 7a8770313e8bb640766240932a9b07f325588db5 Mon Sep 17 00:00:00 2001 From: yujiahe Date: Sun, 7 Sep 2025 18:18:43 +0800 Subject: [PATCH 10/13] add tdd Signed-off-by: yujiahe --- .../monitor/disk_monitor_test.cpp | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp index 12b3f8338..92b3b3d90 100644 --- a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -213,6 +213,106 @@ HWTEST_F(DiskMonitorTest, InitFanotifyTest003, TestSize.Level1) GTEST_LOG_(INFO) << "InitFanotifyTest003 End"; } +/** + * @tc.name: EventProcessTest001 + * @tc.desc: Verify EventProcess function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest001 Begin"; + try { + fanotify_event_metadata *metaData; + metaData->mask = FAN_CREATE; + string fileName = "fileName"; + diskMonitor_->EventProcess(metaData, fileName); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest001 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest001 End"; +} + +/** + * @tc.name: EventProcessTest002 + * @tc.desc: Verify EventProcess function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest002 Begin"; + try { + fanotify_event_metadata *metaData; + metaData->mask = FAN_DELETE; + string fileName = "fileName"; + diskMonitor_->EventProcess(metaData, fileName); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest002 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest002 End"; +} + +/** + * @tc.name: EventProcessTest003 + * @tc.desc: Verify EventProcess function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest003 Begin"; + try { + fanotify_event_metadata *metaData; + metaData->mask = FAN_MOVED_FROM; + string fileName = "fileName"; + diskMonitor_->EventProcess(metaData, fileName); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest003 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest003 End"; +} + +/** + * @tc.name: EventProcessTest004 + * @tc.desc: Verify EventProcess function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest004 Begin"; + try { + fanotify_event_metadata *metaData; + metaData->mask = FAN_MOVED_TO; + string fileName = "fileName"; + diskMonitor_->EventProcess(metaData, fileName); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest004 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest004 End"; +} + +/** + * @tc.name: EventProcessTest005 + * @tc.desc: Verify EventProcess function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest005 Begin"; + try { + fanotify_event_metadata *metaData; + metaData->mask = FAN_CLOSE_WRITE; + string fileName = "fileName"; + diskMonitor_->EventProcess(metaData, fileName); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest005 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest005 End"; +} + /** * @tc.name: HandleCreateTest001 * @tc.desc: Verify HandleCreate function -- Gitee From af45c4c85e0ad190b5f94ad2c82f2d6cc4a9fa2d Mon Sep 17 00:00:00 2001 From: yujiahe Date: Sun, 7 Sep 2025 19:25:07 +0800 Subject: [PATCH 11/13] add tdd Signed-off-by: yujiahe --- .../monitor/disk_monitor_test.cpp | 62 +++++++++++++------ 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp index 92b3b3d90..fcb64ed6b 100644 --- a/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp +++ b/test/unittests/clouddiskservice/monitor/disk_monitor_test.cpp @@ -222,10 +222,10 @@ HWTEST_F(DiskMonitorTest, EventProcessTest001, TestSize.Level1) { GTEST_LOG_(INFO) << "EventProcessTest001 Begin"; try { - fanotify_event_metadata *metaData; - metaData->mask = FAN_CREATE; - string fileName = "fileName"; - diskMonitor_->EventProcess(metaData, fileName); + fanotify_event_metadata metaData; + metaData.mask = FAN_CREATE; + string filePath = "filePath"; + diskMonitor_->EventProcess(&metaData, filePath); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "EventProcessTest001 Error"; @@ -242,10 +242,10 @@ HWTEST_F(DiskMonitorTest, EventProcessTest002, TestSize.Level1) { GTEST_LOG_(INFO) << "EventProcessTest002 Begin"; try { - fanotify_event_metadata *metaData; - metaData->mask = FAN_DELETE; - string fileName = "fileName"; - diskMonitor_->EventProcess(metaData, fileName); + fanotify_event_metadata metaData; + metaData.mask = FAN_DELETE; + string filePath = "filePath"; + diskMonitor_->EventProcess(&metaData, filePath); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "EventProcessTest002 Error"; @@ -262,10 +262,10 @@ HWTEST_F(DiskMonitorTest, EventProcessTest003, TestSize.Level1) { GTEST_LOG_(INFO) << "EventProcessTest003 Begin"; try { - fanotify_event_metadata *metaData; - metaData->mask = FAN_MOVED_FROM; - string fileName = "fileName"; - diskMonitor_->EventProcess(metaData, fileName); + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_FROM; + string filePath = "filePath"; + diskMonitor_->EventProcess(&metaData, filePath); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "EventProcessTest003 Error"; @@ -282,10 +282,10 @@ HWTEST_F(DiskMonitorTest, EventProcessTest004, TestSize.Level1) { GTEST_LOG_(INFO) << "EventProcessTest004 Begin"; try { - fanotify_event_metadata *metaData; - metaData->mask = FAN_MOVED_TO; - string fileName = "fileName"; - diskMonitor_->EventProcess(metaData, fileName); + fanotify_event_metadata metaData; + metaData.mask = FAN_MOVED_TO; + string filePath = "filePath"; + diskMonitor_->EventProcess(&metaData, filePath); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "EventProcessTest004 Error"; @@ -302,10 +302,10 @@ HWTEST_F(DiskMonitorTest, EventProcessTest005, TestSize.Level1) { GTEST_LOG_(INFO) << "EventProcessTest005 Begin"; try { - fanotify_event_metadata *metaData; - metaData->mask = FAN_CLOSE_WRITE; - string fileName = "fileName"; - diskMonitor_->EventProcess(metaData, fileName); + fanotify_event_metadata metaData; + metaData.mask = FAN_CLOSE_WRITE; + string filePath = "filePath"; + diskMonitor_->EventProcess(&metaData, filePath); } catch (...) { EXPECT_TRUE(false); GTEST_LOG_(INFO) << "EventProcessTest005 Error"; @@ -313,6 +313,28 @@ HWTEST_F(DiskMonitorTest, EventProcessTest005, TestSize.Level1) GTEST_LOG_(INFO) << "EventProcessTest005 End"; } +/** + * @tc.name: EventProcessTest006 + * @tc.desc: Verify EventProcess function + * @tc.type: FUNC + */ +HWTEST_F(DiskMonitorTest, EventProcessTest006, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EventProcessTest006 Begin"; + try { + fanotify_event_metadata metaData; + metaData.mask = FAN_CLOSE_WRITE; + diskMonitor_->syncFolderPrefix_ = "a"; + string filePath = "abc"; + diskMonitor_->blackList_ = {"b", "c"}; + diskMonitor_->EventProcess(&metaData, filePath); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "EventProcessTest006 Error"; + } + GTEST_LOG_(INFO) << "EventProcessTest006 End"; +} + /** * @tc.name: HandleCreateTest001 * @tc.desc: Verify HandleCreate function -- Gitee From d3b387ebb7aede877cb3d4593143e55dfc3d14fb Mon Sep 17 00:00:00 2001 From: yujiahe Date: Mon, 8 Sep 2025 10:39:24 +0800 Subject: [PATCH 12/13] add gn Signed-off-by: yujiahe --- test/unittests/clouddiskservice/BUILD.gn | 95 ++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/test/unittests/clouddiskservice/BUILD.gn b/test/unittests/clouddiskservice/BUILD.gn index 133edc1b9..745758c98 100644 --- a/test/unittests/clouddiskservice/BUILD.gn +++ b/test/unittests/clouddiskservice/BUILD.gn @@ -14,6 +14,61 @@ import("//build/test.gni") import("//foundation/filemanagement/dfs_service/distributedfile.gni") +ohos_unittest("disk_monitor_test") { + module_out_path = "dfs_service/dfs_service" + + sources = [ + "${services_path}/clouddiskservice/monitor/src/disk_monitor.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp", + "${distributedfile_path}/log/src/utils_log.cpp", + "${services_path}/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp", + "${distributedfile_path}/test/unittests/clouddiskservice/mock/system_function_mock.cpp", + "${services_path}/clouddiskservice/monitor/src/disk_utils.cpp", + "${services_path}/clouddiskservice/monitor/src/disk_notifier.cpp", + "${services_path}/clouddiskservice/sync_folder/src/cloud_disk_service_syncfolder.cpp", + "${services_path}/clouddiskservice/sync_folder/src/cloud_disk_service_logfile.cpp", + "${services_path}/clouddiskservice/sync_folder/src/cloud_disk_service_metafile.cpp", + "${services_path}/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp", + "${services_path}/clouddiskservice/sync_folder/src/converter.cpp", + "${services_path}/clouddiskservice/sync_folder/src/uuid_helper.cpp", + "monitor/disk_monitor_test.cpp" + ] + + include_dirs = [ + "${services_path}/clouddiskservice/monitor/include", + "${innerkits_native_path}/clouddiskservice_kit_inner", + "${services_path}/clouddiskservice/ipc/include", + "${distributedfile_path}/test/unittests/clouddiskservice/mock", + "${services_path}/clouddiskservice/sync_folder/include", + "${services_path}/clouddiskservice/utils/include", + ] + + deps = [ + "${innerkits_native_path}/cloud_file_kit_inner:cloudfile_kit", + "${services_path}/distributedfiledaemon:libdistributedfiledaemon", + "${utils_path}:libdistributedfiledentry", + "${utils_path}:libdistributedfileutils", + "${utils_path}:libdistributedfileutils_lite", + ] + + external_deps = [ + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ffrt:libffrt", + "e2fsprogs:libext2_uuid", + "c_utils:utils", + ] + + defines = [ + "private=public", + "LOG_DOMAIN=0xD003900", + "LOG_TAG=\"CloudDiskService\"", + ] + + use_exceptions = true +} + ohos_unittest("disk_notifier_test") { module_out_path = "dfs_service/dfs_service" @@ -95,10 +150,50 @@ ohos_unittest("convertor_test") { use_exceptions = true } +ohos_unittest("disk_utils_test") { + module_out_path = "dfs_service/dfs_service" + + sources = [ + "${services_path}/clouddiskservice/monitor/src/disk_utils.cpp", + "${distributedfile_path}/test/unittests/clouddiskservice/mock/system_function_mock.cpp", + "monitor/disk_utils_test.cpp" + ] + + include_dirs = [ + "${services_path}/clouddiskservice/monitor/include", + "${distributedfile_path}/test/unittests/clouddiskservice/mock", + ] + + deps = [ + "${innerkits_native_path}/cloud_file_kit_inner:cloufile_kit", + "${services_path}/distributedfiledaemon:libdistributedfiledaemon", + "${utils_path}:libdistributedfiledentry", + "${utils_path}:libdistributedfileutils", + "${utils_path}:libdistributedfileutils_lite", + ] + + external_deps = [ + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ffrt:libffrt", + ] + + defines = [ + "private=public", + "LOG_DOMAIN=0xD003900", + "LOG_TAG=\"CloudDiskService\"", + ] + + use_exceptions = true +} + group("clouddisk_service_test") { testonly = true deps = [ + ":disk_monitor_test", ":disk_notifier_test", + ":disk_utils_test", ":convertor_test", ] } -- Gitee From 185f69c3362c8cf781bbc228c9fc12a0a3a55590 Mon Sep 17 00:00:00 2001 From: yujiahe Date: Mon, 8 Sep 2025 11:05:11 +0800 Subject: [PATCH 13/13] fix gn Signed-off-by: yujiahe --- test/unittests/clouddiskservice/BUILD.gn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittests/clouddiskservice/BUILD.gn b/test/unittests/clouddiskservice/BUILD.gn index 745758c98..eadf85293 100644 --- a/test/unittests/clouddiskservice/BUILD.gn +++ b/test/unittests/clouddiskservice/BUILD.gn @@ -20,7 +20,7 @@ ohos_unittest("disk_monitor_test") { sources = [ "${services_path}/clouddiskservice/monitor/src/disk_monitor.cpp", "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp", - "${distributedfile_path}/log/src/utils_log.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", "${services_path}/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp", "${distributedfile_path}/test/unittests/clouddiskservice/mock/system_function_mock.cpp", "${services_path}/clouddiskservice/monitor/src/disk_utils.cpp", @@ -165,7 +165,7 @@ ohos_unittest("disk_utils_test") { ] deps = [ - "${innerkits_native_path}/cloud_file_kit_inner:cloufile_kit", + "${innerkits_native_path}/cloud_file_kit_inner:cloudfile_kit", "${services_path}/distributedfiledaemon:libdistributedfiledaemon", "${utils_path}:libdistributedfiledentry", "${utils_path}:libdistributedfileutils", -- Gitee