diff --git a/bundle.json b/bundle.json index af66ffd059c061f742e9d142aa9d6dce8d0e39b2..243c65f5671ba5dbaa0ce2cc5d8dd861c3394e94 100644 --- a/bundle.json +++ b/bundle.json @@ -16,6 +16,9 @@ "SystemCapability.FileManagement.UserFileService", "SystemCapability.FileManagement.UserFileService.FolderSelection" ], + "features": [ + "user_file_service_cloud_disk_enable" + ], "adapted_system_type": [ "standard" ], @@ -82,6 +85,24 @@ "header_files": [], "header_base": "//foundation/filemanagement/user_file_service/interfaces/kits/picker/cj/include" } + }, + { + "name": "//foundation/filemanagement/user_file_service/interfaces/inner_api/cloud_disk_kit_inner:cloud_disk_manager_kit", + "header": { + "header_files": [ + "cloud_disk_manager.h" + ], + "header_base": "//foundation/filemanagement/user_file_service/interfaces/inner_api/cloud_disk_kit_inner/include" + } + }, + { + "name": "//foundation/filemanagement/user_file_service/interfaces/inner_api/cloud_disk_kit_inner:cloud_disk_manager_js_kit", + "header": { + "header_files": [ + "cloud_disk_js_manager.h" + ], + "header_base": "//foundation/filemanagement/user_file_service/interfaces/inner_api/cloud_disk_kit_inner/include" + } } ], "test": [ diff --git a/filemanagement_aafwk.gni b/filemanagement_aafwk.gni index 92a939f8cfd686bdb88d0edc252a3df34b313cfd..9d0c94b5c2b47764eeb6d4495bb346d32726f629 100644 --- a/filemanagement_aafwk.gni +++ b/filemanagement_aafwk.gni @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-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 @@ -21,4 +21,5 @@ declare_args() { if (defined(global_parts_info) && !defined(global_parts_info.distributeddatamgr_udmf)) { picker_udmf_enabled = false } + user_file_service_cloud_disk_enable = false } \ No newline at end of file diff --git a/interfaces/inner_api/cloud_disk_kit_inner/BUILD.gn b/interfaces/inner_api/cloud_disk_kit_inner/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..cf16b12716b999c7aafe5e31485b8dcbdac3bbe0 --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/BUILD.gn @@ -0,0 +1,149 @@ +# 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/user_file_service/filemanagement_aafwk.gni") + +config("cloud_disk_public_config") { + include_dirs = [ "include" ] +} + +ohos_shared_library("cloud_disk_manager_js_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + public_configs = [":cloud_disk_public_config"] + + include_dirs = [ + "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/utils/file_access_framework_errno.h", + "include" + ] + + deps = [ + "${user_file_service_path}/interfaces/inner_api/file_access:file_access_ext_base_source", + "${user_file_service_path}/services:file_access_service_base_source" + ] + + sources = [ + "${user_file_service_path}/services/native/file_access_service/src/file_access_service_client.cpp", + "${user_file_service_path}/interfaces/inner_api/file_access/src/uri_ext.cpp", + "src/cloud_disk_comm.cpp", + "src/cloud_disk_js_manager.cpp" + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_connect_callback_stub", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "file_api:filemgmt_libn", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "os_account:os_account_innerkits", + "samgr:samgr_proxy", + ] + + if (user_file_service_cloud_disk_enable) { + defines = ["SUPPORT_CLOUD_DISK_MANAGER"] + } + + subsystem_name = "filemanagement" + part_name = "user_file_service" + innerapi_tags = [ "platformsdk" ] +} + +ohos_shared_library("cloud_disk_manager_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + include_dirs = [ + "${user_file_service_path}/services/native/file_access_service/include", + ] + + public_configs = [":cloud_disk_public_config"] + + deps = [ + "${user_file_service_path}/interfaces/inner_api/file_access:file_access_ext_base_source", + "${user_file_service_path}/services:file_access_service_base_source" + ] + + sources = [ + "${user_file_service_path}/services/native/file_access_service/src/file_access_service_client.cpp", + "${user_file_service_path}/interfaces/inner_api/file_access/src/uri_ext.cpp", + "src/cloud_disk_comm.cpp", + "src/cloud_disk_manager.cpp", + "src/cloud_disk_manager_impl.cpp" + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_connect_callback_stub", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "file_api:filemgmt_libn", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "os_account:os_account_innerkits", + "samgr:samgr_proxy", + ] + + if (user_file_service_cloud_disk_enable) { + defines = ["SUPPORT_CLOUD_DISK_MANAGER"] + } + + subsystem_name = "filemanagement" + part_name = "user_file_service" + innerapi_tags = [ "platformsdk" ] +} \ No newline at end of file diff --git a/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_comm.h b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_comm.h new file mode 100644 index 0000000000000000000000000000000000000000..c7fc102be09f89e7b930350b38d9065b097de8ba --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_comm.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef CLOUD_DISK_COMMON_H +#define CLOUD_DISK_COMMON_H + +#include "parcel.h" + +#ifndef CLOUD_DISK_EXPORT +#define CLOUD_DISK_EXPORT __attribute__((visibility("default"))) +#endif + +namespace OHOS { +namespace FileManagement { + enum class State { + INACTIVE, + ACTIVE, + MAX_VALUE + }; + + struct SyncFolder : public OHOS::Parcelable { + std::string path_; + State state_ { State::INACTIVE }; + int32_t displayNameResId_ { -1 }; + std::string displayName_; + + SyncFolder() = default; + SyncFolder(std::string path, State state, int resId, std::string displayName) : + path_(path), state_(state), displayNameResId_(resId), displayName_(displayName) {} + bool Marshalling(Parcel &parcel) const override; + bool ReadFromParcel(Parcel &parcel); + static SyncFolder *Unmarshalling(Parcel &parcel); + }; + + struct SyncFolderExt : SyncFolder { + std::string bundleName_; + + SyncFolderExt() = default; + SyncFolderExt(std::string path, State state, int resId, std::string displayName, std::string bundleName) : + SyncFolder(path, state, resId, displayName), bundleName_(bundleName) {} + bool Marshalling(Parcel &parcel) const override; + bool ReadFromParcel(Parcel &parcel); + static SyncFolderExt *Unmarshalling(Parcel &parcel); + }; +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_COMMON_H \ No newline at end of file diff --git a/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_js_manager.h b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_js_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..bf879e1352117da3ba856e3455cc51129b02303a --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_js_manager.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CLOUD_DISK_MANAGER_JS_H +#define CLOUD_DISK_MANAGER_JS_H + +#include "cloud_disk_comm.h" + +namespace OHOS { +namespace FileManagement { +class CloudDiskJSManager { +public: + CloudDiskJSManager() = default; + ~CloudDiskJSManager() = default; + int Register(const SyncFolder &rootInfo); + int Unregister(const std::string &path); + int Active(const std::string &path); + int Deactive(const std::string &path); + int GetSyncFolders(std::vector &syncFolders); + int GetAllSyncFolders(std::vector &syncFolderExts); + int UpdateDisplayName(const std::string &path, const std::string &displayName); +}; +} // namespace FileAccessFwk +} // namespace OHOS +#endif // CLOUD_DISK_MANAGER_JS_H diff --git a/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_manager.h b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..36ed7632c3e90231296d5e482c412d5a889a80fd --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_manager.h @@ -0,0 +1,31 @@ +/* + * 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_MANAGER_H +#define CLOUD_DISK_MANAGER_H + +#include "cloud_disk_comm.h" + +namespace OHOS { +namespace FileManagement { +class CloudDiskManager { +public: + CLOUD_DISK_EXPORT static CloudDiskManager &GetInstance(); + virtual std::vector GetAllSyncFoldersForSa() = 0; + virtual bool DeactiveForSa(const std::string &bundleName, int appIndex) = 0; +}; +} // namespace FileAccessFwk +} // namespace OHOS +#endif // CLOUD_DISK_MANAGER_H diff --git a/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_manager_impl.h b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_manager_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..effa88454c7ad7be0cbdd43b55bbf59b2113f671 --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_manager_impl.h @@ -0,0 +1,31 @@ +/* + * 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_MANAGER_IMPL_H +#define CLOUD_DISK_MANAGER_IMPL_H + +#include "cloud_disk_manager.h" + +namespace OHOS { +namespace FileManagement { +class CloudDiskManagerImpl : public CloudDiskManager { +public: + static CloudDiskManagerImpl &GetInstance(); + virtual std::vector GetAllSyncFoldersForSa() override; + virtual bool DeactiveForSa(const std::string &bundleName, int appIndex) override; +}; +} // namespace FileAccessFwk +} // namespace OHOS +#endif // CLOUD_DISK_MANAGER_IMPL_H diff --git a/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2bf22221ca93d9a1aef0d239eea27d3e290226a --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp @@ -0,0 +1,126 @@ +/* + * 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_comm.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace FileManagement { +bool SyncFolder::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(path_)) { + HILOG_ERROR("write path failed"); + return false; + } + if (!parcel.WriteInt32(static_cast(state_))) { + HILOG_ERROR("write state failed"); + return false; + } + if (!parcel.WriteInt32(displayNameResId_)) { + HILOG_ERROR("write resId failed"); + return false; + } + if (!parcel.WriteString(displayName_)) { + HILOG_ERROR("write displayName failed"); + return false; + } + return true; +} + +bool SyncFolder::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(path_)) { + HILOG_ERROR("read path failed"); + return false; + } + int32_t state = 0; + if (!parcel.ReadInt32(state)) { + HILOG_ERROR("read state failed"); + return false; + } + if (state < static_cast(State::INACTIVE) || state >= static_cast(State::MAX_VALUE)) { + HILOG_ERROR("state check failed, read state is: %{public}d", state); + return false; + } + state_ = static_cast(state); + if (!parcel.ReadInt32(displayNameResId_)) { + HILOG_ERROR("read resId failed"); + return false; + } + if (!parcel.ReadString(displayName_)) { + HILOG_ERROR("read displayName failed"); + return false; + } + return true; +} + +SyncFolder *SyncFolder::Unmarshalling(Parcel &parcel) +{ + SyncFolder *info = new (std::nothrow) SyncFolder(); + if (info == nullptr) { + HILOG_ERROR("new rootInfo failed"); + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + HILOG_ERROR("rootInfo ReadFromParcel falied"); + delete info; + info = nullptr; + } + return info; +} + +bool SyncFolderExt::Marshalling(Parcel &parcel) const +{ + if (!SyncFolder::Marshalling(parcel)) { + HILOG_ERROR("rootInfo marshalling failed"); + return false; + } + if (!parcel.WriteString(bundleName_)) { + HILOG_ERROR("write bundleName failed"); + return false; + } + return true; +} + +bool SyncFolderExt::ReadFromParcel(Parcel &parcel) +{ + if (!SyncFolder::ReadFromParcel(parcel)) { + HILOG_ERROR("rootInfo ReadFromParcel failed"); + return false; + } + if (!parcel.ReadString(bundleName_)) { + HILOG_ERROR("read bundleName failed"); + return false; + } + return true; +} + +SyncFolderExt *SyncFolderExt::Unmarshalling(Parcel &parcel) +{ + SyncFolderExt *info = new (std::nothrow) SyncFolderExt(); + if (info == nullptr) { + HILOG_ERROR("new rootInfoExt failed"); + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + HILOG_ERROR("rootInfoExt ReadFromParcel failed"); + delete info; + info = nullptr; + } + return info; +} +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_js_manager.cpp b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_js_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ac464ddd0073486d40edb41778875d5211c9844 --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_js_manager.cpp @@ -0,0 +1,217 @@ +/* + * 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_js_manager.h" + +#include "ipc_skeleton.h" +#include "tokenid_kit.h" +#include "file_access_framework_errno.h" +#include "file_access_service_client.h" + +namespace OHOS { +namespace FileManagement { +using namespace FileAccessFwk; +#ifdef SUPPORT_CLOUD_DISK_MANAGER +constexpr int MAX_RETRY_TIMES = 3; +#endif + +#ifdef SUPPORT_CLOUD_DISK_MANAGER +static bool IsSystemApp() +{ + uint64_t accessTokenIDEx = OHOS::IPCSkeleton::GetCallingFullTokenID(); + return OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenIDEx); +} +#endif + +int CloudDiskJSManager::Register(const SyncFolder &syncFolder) +{ + HILOG_INFO("CloudDiskJSManager::Register in"); +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Register get SA failed"); + return E_LOAD_SA; + } + int ret = proxy->Register(syncFolder); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Register get SA failed"); + } else { + ret = proxy->Register(syncFolder); + } + ++retryTimes; + } + return ret; +#endif + return ERR_NOT_SUPPORT; +} + +int CloudDiskJSManager::Unregister(const std::string &path) +{ + HILOG_INFO("CloudDiskJSManager::Unregister in"); +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Unregister get SA failed"); + return E_LOAD_SA; + } + int ret = proxy->Unregister(path); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Register get SA failed"); + } else { + ret = proxy->Unregister(path); + } + ++retryTimes; + } + return ret; +#endif + return ERR_NOT_SUPPORT; +} + +int CloudDiskJSManager::Active(const std::string &path) +{ + HILOG_INFO("CloudDiskJSManager::Active in"); +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Active get SA failed"); + return E_LOAD_SA; + } + int ret = proxy->Active(path); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Active get SA failed"); + } else { + ret = proxy->Active(path); + } + ++retryTimes; + } + return ret; +#endif + return ERR_NOT_SUPPORT; +} + +int CloudDiskJSManager::Deactive(const std::string &path) +{ + HILOG_INFO("CloudDiskJSManager::Deactive in"); +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Deactive get SA failed"); + return E_LOAD_SA; + } + int ret = proxy->Deactive(path); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("Deactive get SA failed"); + } else { + ret = proxy->Deactive(path); + } + ++retryTimes; + } + return ret; +#endif + return ERR_NOT_SUPPORT; +} + +int CloudDiskJSManager::GetSyncFolders(std::vector &syncFolders) +{ + HILOG_INFO("CloudDiskJSManager::GetSyncFolders in"); +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("GetSyncFolders get SA failed"); + return E_LOAD_SA; + } + int ret = proxy->GetSyncFolders(syncFolders); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("GetSyncFolders get SA failed"); + } else { + ret = proxy->GetSyncFolders(syncFolders); + } + ++retryTimes; + } + return ret; +#endif + return ERR_NOT_SUPPORT; +} + +int CloudDiskJSManager::GetAllSyncFolders(std::vector &syncFolderExts) +{ + HILOG_INFO("CloudDiskJSManager::GetAllSyncFolders in"); +#ifdef SUPPORT_CLOUD_DISK_MANAGER + if (!IsSystemApp()) { + HILOG_ERROR("GetAllSyncFolders check IsSystemAppByFullTokenID failed"); + return E_PERMISSION_SYS; + } + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("GetAllSyncFolders get SA failed"); + return E_LOAD_SA; + } + int ret = proxy->GetAllSyncFolders(syncFolderExts); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("GetAllSyncFolders get SA failed"); + } else { + ret = proxy->GetAllSyncFolders(syncFolderExts); + } + ++retryTimes; + } + return ret; +#endif + return ERR_NOT_SUPPORT; +} + +int CloudDiskJSManager::UpdateDisplayName(const std::string &path, const std::string &displayName) +{ + HILOG_INFO("CloudDiskJSManager::UpdateDisplayName in"); +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("UpdateDisplayName get SA failed"); + return E_LOAD_SA; + } + int ret = proxy->UpdateDisplayName(path, displayName); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("UpdateDisplayName get SA failed"); + } else { + ret = proxy->UpdateDisplayName(path, displayName); + } + ++retryTimes; + } + return ret; +#endif + return ERR_NOT_SUPPORT; +} +} // namespace FileAccessFwk +} // namespace OHOS diff --git a/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_manager.cpp b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5879d9b2422fb98a644eb066bddb588fdb370330 --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_manager.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cloud_disk_manager.h" +#include "cloud_disk_manager_impl.h" + +namespace OHOS { +namespace FileManagement { +CloudDiskManager &CloudDiskManager::GetInstance() +{ + return CloudDiskManagerImpl::GetInstance(); +} +} // namespace FileAccessFwk +} // namespace OHOS diff --git a/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_manager_impl.cpp b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_manager_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d142bd1776d24227cc0ffc094a01ffce11dafc46 --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_manager_impl.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cloud_disk_manager_impl.h" +#include "file_access_service_client.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace FileManagement { +using namespace FileAccessFwk; +#ifdef SUPPORT_CLOUD_DISK_MANAGER +constexpr int ERR_SERVICE_DIED = 29189; +constexpr int MAX_RETRY_TIMES = 3; +#endif + +CloudDiskManagerImpl &CloudDiskManagerImpl::GetInstance() +{ + static CloudDiskManagerImpl instance; + return instance; +} + +std::vector CloudDiskManagerImpl::GetAllSyncFoldersForSa() +{ + HILOG_INFO("CloudDiskManagerImpl::GetAllRootsForSa in"); + std::vector syncFolderExts; +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("GetAllRootsForSa get SA failed"); + return syncFolderExts; + } + int ret = proxy->GetAllSyncFolders(syncFolderExts); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("GetAllRootsForSa get SA failed"); + } else { + ret = proxy->GetAllSyncFolders(syncFolderExts); + } + ++retryTimes; + } +#endif + return syncFolderExts; +} + +bool CloudDiskManagerImpl::DeactiveForSa(const std::string &bundleName, int appIndex) +{ + HILOG_INFO("CloudDiskManagerImpl::DeactiveForSa in"); + if (bundleName.empty() || appIndex < 0) { + HILOG_ERROR("Parameter error, bundleName: %{public}s, appIndex: %{public}d", bundleName.c_str(), appIndex); + return false; + } +#ifdef SUPPORT_CLOUD_DISK_MANAGER + auto proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("DeactiveForSa get SA failed"); + return false; + } + int ret = proxy->DeactiveForSa(bundleName, appIndex); + int retryTimes = 1; + while (ret == ERR_SERVICE_DIED && retryTimes <= MAX_RETRY_TIMES) { + proxy = FileAccessServiceClient::GetInstance(); + if (proxy == nullptr) { + HILOG_ERROR("DeactiveForSa get SA failed"); + } else { + ret = proxy->DeactiveForSa(bundleName, appIndex); + } + ++retryTimes; + } + return ret == FileAccessFwk::ERR_OK; +#endif + return false; +} +} // namespace FileAccessFwk +} // namespace OHOS diff --git a/interfaces/inner_api/file_access/BUILD.gn b/interfaces/inner_api/file_access/BUILD.gn index fb401d917d72ad11a6e730122b4822c184fc0ecc..0401b9601f026ed82dcdd0a2c6f468cded802f78 100644 --- a/interfaces/inner_api/file_access/BUILD.gn +++ b/interfaces/inner_api/file_access/BUILD.gn @@ -29,6 +29,7 @@ config("IFile_Access_Ext_Base_config") { "${user_file_service_path}/utils", "${user_file_service_path}/services/native/file_access_service/include", "${user_file_service_path}/interfaces/kits/js/src/common", + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", "${target_gen_dir}", ] } @@ -128,6 +129,7 @@ ohos_shared_library("file_access_extension_ability_kit") { ] sources = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp", "${user_file_service_path}/services/native/file_access_service/src/file_access_service_client.cpp", "src/app_file_access_ext_connection.cpp", "src/file_access_ext_ability.cpp", diff --git a/interfaces/kits/js/src/common/file_info_shared_memory.h b/interfaces/kits/js/src/common/file_info_shared_memory.h index df9965b4d17aa31ed0391247d7f5838b23ee3051..edfb3865f4df591f46bee8f3aba68ef25df5ab45 100644 --- a/interfaces/kits/js/src/common/file_info_shared_memory.h +++ b/interfaces/kits/js/src/common/file_info_shared_memory.h @@ -1,6 +1,5 @@ - /* - * Copyright (C) 2023 - 2025 Huawei Device Co., Ltd. + * Copyright (C) 2023-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 @@ -168,7 +167,7 @@ public: memInfo.memFd = AshmemCreate(memInfo.memName, memInfo.memSize); if (memInfo.memFd < 0) { HILOG_ERROR("Create shared memory error, shared memory name is %{public}s code: %{public}d", - memInfo.memName, memInfo.memFd); + memInfo.memName, memInfo.memFd); return memInfo.memFd; } diff --git a/services/BUILD.gn b/services/BUILD.gn index d0441abdc546527462cf4d61e84de35bdd674661..b269f07e4f45536470b414dab3bda87b140f5777 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -174,15 +174,20 @@ ohos_shared_library("file_access_service") { } include_dirs = [ - "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/services/native/notify_event/include" ] shlib_type = "sa" sources = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp", "${user_file_service_path}/interfaces/inner_api/file_access/src/uri_ext.cpp", + "native/cloud_disk_service/src/cloud_disk_service.cpp", "native/file_access_service/src/file_access_ext_connection.cpp", "native/file_access_service/src/file_access_service.cpp", "native/file_access_service/src/file_access_service_client.cpp", + "native/notify_event/src/notify_work_service.cpp" ] configs = [ ":ability_config" ] version_script = "libfile_access_service.map" @@ -203,12 +208,13 @@ ohos_shared_library("file_access_service") { "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "bundle_framework:appexecfwk_core", + "common_event_service:cesfwk_innerkits", "c_utils:utils", "hilog:libhilog", "hitrace:hitrace_meter", "ipc:ipc_core", "safwk:system_ability_fwk", - "samgr:samgr_proxy", + "samgr:samgr_proxy" ] subsystem_name = "filemanagement" diff --git a/services/IFileAccessServiceBase.idl b/services/IFileAccessServiceBase.idl index 704913b039e4ce265b6daf21fc52f6c9a22628bc..845aa31a7224c73ce70e6786b80a2b6ac7d5f9ed 100644 --- a/services/IFileAccessServiceBase.idl +++ b/services/IFileAccessServiceBase.idl @@ -18,6 +18,8 @@ import IFileAccessObserver; sequenceable Uri..OHOS.Uri; sequenceable FileAccessExtensionInfo..OHOS.FileAccessFwk.ConnectExtensionInfo; sequenceable Want..OHOS.AAFwk.Want; +sequenceable CloudDiskComm..OHOS.FileManagement.SyncFolder; +sequenceable CloudDiskComm..OHOS.FileManagement.SyncFolderExt; interface OHOS.FileAccessFwk.IFileAccessExtBase; interface OHOS.AAFwk.IAbilityConnection; interface OHOS.FileAccessFwk.IFileAccessServiceBase { @@ -29,4 +31,12 @@ interface OHOS.FileAccessFwk.IFileAccessServiceBase { void ConnectFileExtAbility([in] Want want, [in] IAbilityConnection connection); void DisConnectFileExtAbility([in] IAbilityConnection connection); void UnregisterNotifyNoObserver([in] Uri uri, [in] ConnectExtensionInfo info); + void Register([in] SyncFolder syncFolder); + void Unregister([in] String path); + void Active([in] String path); + void Deactive([in] String path); + void GetSyncFolders([out] SyncFolder[] syncFolders); + void GetAllSyncFolders([out] SyncFolderExt[] syncFolderExts); + void UpdateDisplayName([in] String path, [in] String displayName); + void DeactiveForSa([in] String bundleName, [in] int appIndex); } \ No newline at end of file diff --git a/services/file_access_service.cfg b/services/file_access_service.cfg index ab218fe9909b161c9800587a984b09ff09d758d1..490b6855f5b02182893689f3c051560ac53589db 100644 --- a/services/file_access_service.cfg +++ b/services/file_access_service.cfg @@ -2,12 +2,13 @@ "services" : [{ "name" : "file_access_service", "path" : ["/system/bin/sa_main", "/system/profile/file_access_service.json"], - "uid" : "file_manager", + "uid" : "ufs", "ondemand" : true, "secon" : "u:r:file_access_service:s0", "permission" : [ "ohos.permission.FILE_ACCESS_MANAGER", - "ohos.permission.CONNECT_FILE_ACCESS_EXTENSION" + "ohos.permission.CONNECT_FILE_ACCESS_EXTENSION", + "ohos.permission.ACCESS_CLOUD_DISK_INFO" ] } ] diff --git a/services/file_extension_hap/entry/src/main/module.json b/services/file_extension_hap/entry/src/main/module.json index 36f17c61be00e392a4e8a6db402f0ebac5292534..f129d8f13a3b991a21b0771cbae43ab7003b5b03 100644 --- a/services/file_extension_hap/entry/src/main/module.json +++ b/services/file_extension_hap/entry/src/main/module.json @@ -29,5 +29,5 @@ "name": "ohos.permission.FILE_ACCESS_MANAGER" } ] - } + } } diff --git a/services/native/cloud_disk_service/src/cloud_disk_service.cpp b/services/native/cloud_disk_service/src/cloud_disk_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37e5a2f726922c7d30af55b031ab2cdd59ae4833 --- /dev/null +++ b/services/native/cloud_disk_service/src/cloud_disk_service.cpp @@ -0,0 +1,148 @@ +/* + * 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 "file_access_service.h" +#include "notify_work_service.h" + +using namespace std; +namespace OHOS { +namespace FileAccessFwk { + +void FileAccessService::IncreaseCnt(const std::string funcName) +{ + ++calledCount_; + HILOG_INFO("Func name: %{public}s, count: %{public}d", funcName.c_str(), calledCount_.load()); +} + +void FileAccessService::DncreaseCnt(const std::string funcName) +{ + --calledCount_; + HILOG_INFO("Func name: %{public}s, count: %{public}d", funcName.c_str(), calledCount_.load()); +} + +int32_t FileAccessService::Register(const SyncFolder &syncFolder) +{ + HILOG_INFO("FileAccessService::Register begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = syncFolder.path_; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + if (!NotifyWorkService::GetInstance().NotifyRootInfoDetail(syncFolderExt, EventType::REGISTER)) { + HILOG_ERROR("FileAccessService::Register NotifyRootInfoDetail failed"); + DncreaseCnt(__PRETTY_FUNCTION__); + return E_NOTIFY; + } + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} + +int32_t FileAccessService::Unregister(const std::string &path) +{ + HILOG_INFO("FileAccessService::Unregister begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + if (!NotifyWorkService::GetInstance().NotifyRootInfoDetail(syncFolderExt, EventType::UNREGISTER)) { + HILOG_ERROR("FileAccessService::Unregister NotifyRootInfoDetail failed"); + DncreaseCnt(__PRETTY_FUNCTION__); + return E_NOTIFY; + } + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} + +int32_t FileAccessService::Active(const std::string &path) +{ + HILOG_INFO("FileAccessService::Active begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + if (!NotifyWorkService::GetInstance().NotifyRootInfoDetail(syncFolderExt, EventType::ACTIVE)) { + HILOG_ERROR("FileAccessService::Active NotifyRootInfoDetail failed"); + DncreaseCnt(__PRETTY_FUNCTION__); + return E_NOTIFY; + } + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} + +int32_t FileAccessService::Deactive(const std::string &path) +{ + HILOG_INFO("FileAccessService::Deactive begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + if (!NotifyWorkService::GetInstance().NotifyRootInfoDetail(syncFolderExt, EventType::INACTIVE)) { + HILOG_ERROR("FileAccessService::Deactive NotifyRootInfoDetail failed"); + DncreaseCnt(__PRETTY_FUNCTION__); + return E_NOTIFY; + } + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} + +int32_t FileAccessService::GetSyncFolders(std::vector &syncFolders) +{ + HILOG_INFO("FileAccessService::GetSyncFolders begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} + +int32_t FileAccessService::GetAllSyncFolders(std::vector &syncFolderExts) +{ + HILOG_INFO("FileAccessService::GetAllSyncFolders begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} + +int32_t FileAccessService::UpdateDisplayName(const std::string &path, const std::string &displayName) +{ + HILOG_INFO("FileAccessService::UpdateDisplayName begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + syncFolderExt.displayName_ = displayName; + if (!NotifyWorkService::GetInstance().NotifyRootInfoDetail(syncFolderExt, EventType::UPDATE)) { + HILOG_ERROR("FileAccessService::UpdateDisplayName NotifyRootInfoDetail failed"); + DncreaseCnt(__PRETTY_FUNCTION__); + return E_NOTIFY; + } + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} + +int32_t FileAccessService::DeactiveForSa(const std::string &bundleName, int appIndex) +{ + HILOG_INFO("FileAccessService::DeactiveForSa begin"); + IncreaseCnt(__PRETTY_FUNCTION__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = "testPath"; + syncFolderExt.bundleName_ = bundleName; + if (!NotifyWorkService::GetInstance().NotifyRootInfoDetail(syncFolderExt, EventType::INACTIVE)) { + HILOG_ERROR("FileAccessService::DeactiveForSa NotifyRootInfoDetail failed"); + DncreaseCnt(__PRETTY_FUNCTION__); + return E_NOTIFY; + } + DncreaseCnt(__PRETTY_FUNCTION__); + return ERR_OK; +} +} // namespace FileAccessFwk +} // namespace OHOS diff --git a/services/native/file_access_service/include/file_access_service.h b/services/native/file_access_service/include/file_access_service.h index b24e0c47364f9719645f4ba3ba44e7b0bfcf9dc8..cea7ff64f2767d940a68fe9e89a23b829ea09985 100644 --- a/services/native/file_access_service/include/file_access_service.h +++ b/services/native/file_access_service/include/file_access_service.h @@ -245,6 +245,14 @@ protected: int32_t ConnectFileExtAbility(const AAFwk::Want &want, const sptr& connection) override; int32_t DisConnectFileExtAbility(const sptr& connection) override; + int32_t Register(const SyncFolder &syncFolder) override; + int32_t Unregister(const std::string &path) override; + int32_t Active(const std::string &path) override; + int32_t Deactive(const std::string &path) override; + int32_t GetSyncFolders(std::vector &syncFolder) override; + int32_t GetAllSyncFolders(std::vector &syncFolderExt) override; + int32_t UpdateDisplayName(const std::string &path, const std::string &displayName) override; + int32_t DeactiveForSa(const std::string &bundleName, int appIndex) override; private: class ExtensionDeathRecipient : public IRemoteObject::DeathRecipient { @@ -285,6 +293,8 @@ private: void AddExtProxyInfo(std::string bundleName, sptr extProxy); // 管理对象 方法 void AddAppProxy(const sptr& key, sptr& value); + void IncreaseCnt(const std::string funcName); + void DncreaseCnt(const std::string funcName); std::shared_ptr unLoadTimer_ = nullptr; std::shared_ptr onDemandTimer_ = nullptr; static sptr instance_; @@ -298,7 +308,7 @@ private: HolderManager> obsManager_; std::mutex mapMutex_; std::unordered_map> cMap_; - + class AppDeathRecipient : public IRemoteObject::DeathRecipient { public: AppDeathRecipient() {} @@ -310,6 +320,9 @@ private: std::unordered_map> appProxyMap_; std::unordered_map> appConnection_; sptr appDeathRecipient_; + + std::atomic calledCount_{0}; + std::mutex countMutex_; }; } // namespace FileAccessFwk } // namespace OHOS diff --git a/services/native/file_access_service/src/file_access_service.cpp b/services/native/file_access_service/src/file_access_service.cpp index e87c99cf9e9de71a62171d59f2f2c8b7e5672459..77e60848e7b465f1299636ada0e083d910a57fe4 100644 --- a/services/native/file_access_service/src/file_access_service.cpp +++ b/services/native/file_access_service/src/file_access_service.cpp @@ -683,9 +683,9 @@ int32_t FileAccessService::OnChange(const Uri &uri, NotifyType notifyType) bool FileAccessService::IsUnused() { - HILOG_INFO("IsUnused: obsManager_: %{public}d, appProxyMap_: %{public}d", - obsManager_.isEmpty(), appProxyMap_.empty()); - return obsManager_.isEmpty() && appProxyMap_.empty(); + HILOG_INFO("IsUnused: obsManager_: %{public}d, appProxyMap_: %{public}d, calledCount_: %{public}d", + obsManager_.isEmpty(), appProxyMap_.empty(), calledCount_.load()); + return obsManager_.isEmpty() && appProxyMap_.empty() && !calledCount_.load(); } void FileAccessService::InitTimer() @@ -906,6 +906,5 @@ void FileAccessService::AppDeathRecipient::OnRemoteDied(const wptrRemoveAppProxy(remoteBroker); } - } // namespace FileAccessFwk } // namespace OHOS diff --git a/services/native/notify_event/include/notify_work_service.h b/services/native/notify_event/include/notify_work_service.h new file mode 100644 index 0000000000000000000000000000000000000000..282c395b350e2954830705ec0af59a27602b58bf --- /dev/null +++ b/services/native/notify_event/include/notify_work_service.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_FILEMGMT_CLOUD_DISK_NOTIFY_WORK_SERVICE_H +#define OHOS_FILEMGMT_CLOUD_DISK_NOTIFY_WORK_SERVICE_H + +#include + +#include "cloud_disk_comm.h" +namespace OHOS::FileAccessFwk { +using namespace OHOS::FileManagement; + +enum class EventType { + REGISTER, + UNREGISTER, + ACTIVE, + INACTIVE, + UPDATE, + MAX +}; +class NotifyWorkService final : public NoCopyable { +public: + static NotifyWorkService &GetInstance(); + bool NotifyRootInfoDetail(const SyncFolderExt &rootInfoExt, EventType eventType); +private: + NotifyWorkService() = default; +}; +} // namespace OHOS::FileAccessFwk + +#endif // OHOS_FILEMGMT_CLOUD_DISK_NOTIFY_WORK_SERVICE_H \ No newline at end of file diff --git a/services/native/notify_event/src/notify_work_service.cpp b/services/native/notify_event/src/notify_work_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a99c988235a5d68240e9fde9c890d788b050012 --- /dev/null +++ b/services/native/notify_event/src/notify_work_service.cpp @@ -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. + */ + +#include "notify_work_service.h" + +#include "common_event_data.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "hilog_wrapper.h" +#include "want.h" +#include "want_params.h" + +namespace OHOS::FileAccessFwk { +const std::vector NOTIFY_EVENT_TYPES = { + "REGISTER", + "UNREGISTER", + "ACTIVE", + "INACTIVE", + "UPDATE" +}; +NotifyWorkService &NotifyWorkService::GetInstance() +{ + static NotifyWorkService instance; + return instance; +} + +bool NotifyWorkService::NotifyRootInfoDetail(const SyncFolderExt &rootInfoExt, EventType eventType) +{ + AAFwk::Want want; + HILOG_INFO("Start publish event, bundleName is: %{public}s", rootInfoExt.bundleName_.c_str()); + want.SetBundle(rootInfoExt.bundleName_); + want.SetParam("bundleName", rootInfoExt.bundleName_); + if (eventType < EventType::REGISTER || eventType >= EventType::MAX) { + HILOG_INFO("EventType is invalid: %{public}d", static_cast(eventType)); + return false; + } + want.SetParam("eventType", NOTIFY_EVENT_TYPES[static_cast(eventType)]); + want.SetParam("path", rootInfoExt.path_); + want.SetParam("state", static_cast(rootInfoExt.state_)); + if (rootInfoExt.displayNameResId_ == -1) { + want.SetParam("displayNameResId", rootInfoExt.displayNameResId_); + } + if (!rootInfoExt.displayName_.empty()) { + want.SetParam("displayName", rootInfoExt.displayName_); + } + want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_CLOUD_DISK_ROOT_CHANGED); + EventFwk::CommonEventData commonData {want}; + HILOG_INFO("End publish event, bundleName is: %{public}s", rootInfoExt.bundleName_.c_str()); + return EventFwk::CommonEventManager::PublishCommonEvent(commonData); +} +} \ No newline at end of file diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 1e41b55e2c30d77fc064eeebcd3c9fd1383d1bff..3bf3563b4953fa46588560858a0736faebd16f0d 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -193,6 +193,7 @@ ohos_unittest("abnormal_file_access_test") { module_out_path = "user_file_service/user_file_service" sources = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp", "${user_file_service_path}/interfaces/inner_api/file_access/src/uri_ext.cpp", "abnormal_file_access_test.cpp", ] @@ -295,6 +296,7 @@ ohos_unittest("js_file_access_ext_ability_test") { module_out_path = "user_file_service/user_file_service" include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", "${user_file_service_path}/interfaces/inner_api/file_access/include", "${user_file_service_path}/interfaces/inner_api/file_access/src", "${user_file_service_path}/interfaces/kits/js/src/common", @@ -371,16 +373,193 @@ ohos_unittest("urie_test") { defines = [ "private=public" ] } +ohos_unittest("cloud_disk_js_manager_test") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${user_file_service_path}/cfi_blocklist.txt" + } + module_out_path = "user_file_service/user_file_service" + + include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", + "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/interfaces/inner_api/file_access/src", + "${user_file_service_path}/interfaces/kits/js/src/common", + "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/utils", + "mock", + ] + + sources = [ + "cloud_disk_js_manager_test.cpp", + ] + + deps = [ + "${user_file_service_path}/interfaces/inner_api/file_access:file_access_ext_base_include", + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner:cloud_disk_manager_js_kit", + "${user_file_service_path}/services:file_access_service_base_include", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "file_api:filemgmt_libn", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "os_account:os_account_innerkits", + ] + + defines = [ "private=public" ] + + use_exceptions = true +} + +ohos_unittest("cloud_disk_service_test") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${user_file_service_path}/cfi_blocklist.txt" + } + module_out_path = "user_file_service/user_file_service" + + include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", + "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/services/native/notify_event/include", + "${user_file_service_path}/utils", + "mock", + ] + + sources = [ + "cloud_disk_service_test.cpp", + ] + + deps = [ + "${user_file_service_path}/services:file_access_service", + "${user_file_service_path}/services:file_access_service_base_source", + "${user_file_service_path}/interfaces/inner_api/file_access:file_access_ext_base_include", + "${user_file_service_path}/interfaces/inner_api/file_access:file_access_extension_ability_kit", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "file_api:filemgmt_libn", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "os_account:os_account_innerkits", + ] + + defines = [ + "private=public", + "protected=public" + ] + + use_exceptions = true +} + +ohos_unittest("notify_work_service_test") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${user_file_service_path}/cfi_blocklist.txt" + } + module_out_path = "user_file_service/user_file_service" + + include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", + "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/services/native/notify_event/include", + "${user_file_service_path}/utils", + "mock", + ] + + sources = [ + "notify_work_service_test.cpp", + ] + + deps = [ + "${user_file_service_path}/services:file_access_service", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "file_api:filemgmt_libn", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "os_account:os_account_innerkits", + "common_event_service:cesfwk_innerkits", + ] + + defines = [ "private=public" ] + + use_exceptions = true +} + group("user_file_service_unit_test") { testonly = true deps = [ ":abnormal_file_access_test", + ":cloud_disk_js_manager_test", + ":cloud_disk_service_test", ":external_file_access_basic_test", ":external_file_access_management_test", ":external_file_access_notify_test", ":file_access_ext_stub_impl_test", ":js_file_access_ext_ability_test", + ":notify_work_service_test", ":urie_test", ] } \ No newline at end of file diff --git a/test/unittest/cloud_disk_js_manager_test.cpp b/test/unittest/cloud_disk_js_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b3e5f08b2805953a2604f56126b33b03848573b --- /dev/null +++ b/test/unittest/cloud_disk_js_manager_test.cpp @@ -0,0 +1,431 @@ +/* + * 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 "cloud_disk_js_manager.h" +#include "file_access_framework_errno.h" +#include "file_access_service_client.h" +#include "file_access_service_mock.h" + +using namespace testing; +using namespace testing::ext; + +using namespace OHOS; +using namespace FileAccessFwk; + +namespace { + sptr g_fileAccessSvc = nullptr; + bool g_svcTrue = false; +} + +sptr FileAccessServiceClient::GetInstance() +{ + if (g_svcTrue) { + return iface_cast(g_fileAccessSvc); + } else { + return nullptr; + } +} + + +namespace OHOS { +namespace FileManagement { +constexpr int ERR_SERVICE_DIED = 29189; +class CloudDiskJSManagerTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + } + static void TearDownTestCase() + { + } + void SetUp(){ + g_fileAccessSvc = new (std::nothrow) FileAccessServiceMock(); + ASSERT_NE(g_fileAccessSvc, nullptr); + } + void TearDown(){ + g_fileAccessSvc = nullptr; + } +}; + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Register_001 + * @tc.name: Register + * @tc.desc: Test Register interface for failure case with null proxy. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Register_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Register_001 start"; + SyncFolder syncFolder; + g_svcTrue = false; + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Register(syncFolder); + EXPECT_EQ(res, E_LOAD_SA); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Register_001 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Register_002 + * @tc.name: Register + * @tc.desc: Test Register interface for success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Register_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Register_002 start"; + SyncFolder syncFolder; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, Register(_)).WillOnce(Return(0)); + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Register(syncFolder); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Register_002 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Register_003 + * @tc.name: Register + * @tc.desc: Test Register interface for service died and retry success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Register_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Register_003 start"; + SyncFolder syncFolder; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, Register(_)) + .WillOnce(Return(ERR_SERVICE_DIED)) // ERR_SERVICE_DIED + .WillOnce(Return(0)); // Success on retry + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Register(syncFolder); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Register_003 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Unregister_001 + * @tc.name: Unregister + * @tc.desc: Test Unregister interface for failure case with null proxy. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Unregister_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Unregister_001 start"; + std::string uri = "test_uri"; + g_svcTrue = false; + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Unregister(uri); + EXPECT_EQ(res, E_LOAD_SA); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Unregister_001 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Unregister_002 + * @tc.name: Unregister + * @tc.desc: Test Unregister interface for success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Unregister_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Unregister_002 start"; + std::string uri = "test_uri"; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, Unregister(_)).WillOnce(Return(0)); + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Unregister(uri); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Unregister_002 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Unregister_003 + * @tc.name: Unregister + * @tc.desc: Test Unregister interface for service died and retry success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Unregister_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Unregister_003 start"; + std::string uri = "test_uri"; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, Unregister(_)) + .WillOnce(Return(ERR_SERVICE_DIED)) // ERR_SERVICE_DIED + .WillOnce(Return(0)); // Success on retry + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Unregister(uri); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Unregister_003 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Active_001 + * @tc.name: Active + * @tc.desc: Test Active interface for failure case with null proxy. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Active_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Active_001 start"; + std::string uri = "test_uri"; + g_svcTrue = false; + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Active(uri); + EXPECT_EQ(res, E_LOAD_SA); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Active_001 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Active_002 + * @tc.name: Active + * @tc.desc: Test Active interface for success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Active_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Active_002 start"; + std::string uri = "test_uri"; + EXPECT_CALL(*g_fileAccessSvc, Active(_)).WillOnce(Return(0)); + g_svcTrue = true; + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Active(uri); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Active_002 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_Active_003 + * @tc.name: Active + * @tc.desc: Test Active interface for service died and retry success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_Active_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_Active_003 start"; + std::string uri = "test_uri"; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, Active(_)) + .WillOnce(Return(ERR_SERVICE_DIED)) // ERR_SERVICE_DIED + .WillOnce(Return(0)); // Success on retry + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Active(uri); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_Active_003 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_InActive_001 + * @tc.name: Deactive + * @tc.desc: Test Deactive interface for failure case with null proxy. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_InActive_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_InActive_001 start"; + std::string uri = "test_uri"; + g_svcTrue = false; + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Deactive(uri); + EXPECT_EQ(res, E_LOAD_SA); + GTEST_LOG_(INFO) << "CloudDiskJSManager_InActive_001 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_InActive_002 + * @tc.name: Deactive + * @tc.desc: Test Deactive interface for success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_InActive_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_InActive_002 start"; + std::string uri = "test_uri"; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, Deactive(_)).WillOnce(Return(0)); + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Deactive(uri); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_InActive_002 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_InActive_003 + * @tc.name: Deactive + * @tc.desc: Test Deactive interface for service died and retry success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_InActive_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_InActive_003 start"; + std::string uri = "test_uri"; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, Deactive(_)) + .WillOnce(Return(ERR_SERVICE_DIED)) // ERR_SERVICE_DIED + .WillOnce(Return(0)); // Success on retry + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.Deactive(uri); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_InActive_003 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_GetSyncFolders_001 + * @tc.name: GetSyncFolders + * @tc.desc: Test GetSyncFolders interface for failure case with null proxy. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_GetSyncFolders_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetSyncFolders_001 start"; + std::vector syncFolders; + g_svcTrue = false; + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.GetSyncFolders(syncFolders); + EXPECT_EQ(res, E_LOAD_SA); + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetSyncFolders_001 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_GetSyncFolders_002 + * @tc.name: GetSyncFolders + * @tc.desc: Test GetSyncFolders interface for success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_GetSyncFolders_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetSyncFolders_002 start"; + std::vector syncFolders; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, GetSyncFolders(_)).WillOnce(Return(0)); + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.GetSyncFolders(syncFolders); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetSyncFolders_002 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_GetSyncFolders_003 + * @tc.name: GetSyncFolders + * @tc.desc: Test GetSyncFolders interface for service died and retry success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_GetSyncFolders_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetSyncFolders_003 start"; + std::vector syncFolders; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, GetSyncFolders(_)) + .WillOnce(Return(ERR_SERVICE_DIED)) // ERR_SERVICE_DIED + .WillOnce(Return(0)); // Success on retry + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.GetSyncFolders(syncFolders); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetSyncFolders_003 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_GetAllSyncFolders_001 + * @tc.name: GetAllSyncFolders + * @tc.desc: Test GetAllSyncFolders interface for failure case with null proxy. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_GetAllSyncFolders_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetAllSyncFolders_001 start"; + std::vector syncFolderExts; + g_svcTrue = false; + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.GetAllSyncFolders(syncFolderExts); + EXPECT_EQ(res, E_LOAD_SA); + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetAllSyncFolders_001 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_GetAllSyncFolders_002 + * @tc.name: GetAllSyncFolders + * @tc.desc: Test GetAllSyncFolders interface for success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_GetAllSyncFolders_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetAllSyncFolders_002 start"; + std::vector syncFolderExts; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, GetAllSyncFolders(_)).WillOnce(Return(0)); + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.GetAllSyncFolders(syncFolderExts); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetAllSyncFolders_002 end"; +} + +/** + * @tc.number: user_file_service_cloud_disk_js_manager_GetAllSyncFolders_003 + * @tc.name: GetAllSyncFolders + * @tc.desc: Test GetAllSyncFolders interface for service died and retry success case. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloudDiskJSManagerTest, CloudDiskJSManager_GetAllSyncFolders_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetAllSyncFolders_003 start"; + std::vector syncFolderExts; + g_svcTrue = true; + EXPECT_CALL(*g_fileAccessSvc, GetAllSyncFolders(_)) + .WillOnce(Return(ERR_SERVICE_DIED)) // ERR_SERVICE_DIED + .WillOnce(Return(0)); // Success on retry + CloudDiskJSManager cloudDiskJSManager; + auto res = cloudDiskJSManager.GetAllSyncFolders(syncFolderExts); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "CloudDiskJSManager_GetAllSyncFolders_003 end"; +} +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/cloud_disk_service_test.cpp b/test/unittest/cloud_disk_service_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b25f38e2b24284a424f286e5050439042106a750 --- /dev/null +++ b/test/unittest/cloud_disk_service_test.cpp @@ -0,0 +1,183 @@ +/* + * 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 "file_access_service.h" + +#include +#include + +#include "notify_work_service.h" +#include "hilog_wrapper.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::FileAccessFwk; +using namespace OHOS::FileManagement; + +namespace OHOS { +namespace FileAccessFwk { +class CloudDiskServiceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void CloudDiskServiceTest::SetUpTestCase(void) +{ + // Setup code to run before all tests +} + +void CloudDiskServiceTest::TearDownTestCase(void) +{ + // Teardown code to run after all tests +} + +void CloudDiskServiceTest::SetUp() +{ + // Setup code to run before each test +} + +void CloudDiskServiceTest::TearDown() +{ + // Teardown code to run after each test +} + +/** + * @tc.number: CloudDiskService_Register_001 + * @tc.name: Register cloud disk root info + * @tc.desc: Verify Register function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_Register_001, TestSize.Level1) +{ + GTEST_SKIP() << "Skipping test as we need to mock NotifyWorkService"; + SyncFolder syncFolder; + syncFolder.uri_ = "cloud://test/root"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Register(syncFolder); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.number: CloudDiskService_Unregister_001 + * @tc.name: Unregister cloud disk root info + * @tc.desc: Verify Unregister function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_Unregister_001, TestSize.Level1) +{ + GTEST_SKIP() << "Skipping test as we need to mock NotifyWorkService"; + std::string path = "cloud://test/root"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Unregister(path); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.number: CloudDiskService_Active_001 + * @tc.name: Active cloud disk + * @tc.desc: Verify Active function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_Active_001, TestSize.Level1) +{ + GTEST_SKIP() << "Skipping test as we need to mock NotifyWorkService"; + std::string path = "cloud://test/root"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Active(path); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.number: CloudDiskService_InActive_001 + * @tc.name: Deactive cloud disk + * @tc.desc: Verify Deactive function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_InActive_001, TestSize.Level1) +{ + GTEST_SKIP() << "Skipping test as we need to mock NotifyWorkService"; + std::string path = "cloud://test/root"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Deactive(path); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.number: CloudDiskService_GetSyncFolders_001 + * @tc.name: Get cloud disk roots + * @tc.desc: Verify GetSyncFolders function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_GetSyncFolders_001, TestSize.Level1) +{ + std::vector syncFolders; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->GetSyncFolders(syncFolders); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.number: CloudDiskService_GetAllSyncFolders_001 + * @tc.name: Get all cloud disk roots + * @tc.desc: Verify GetAllSyncFolders function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_GetAllSyncFolders_001, TestSize.Level1) +{ + std::vector syncFolderExts; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->GetAllSyncFolders(syncFolderExts); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.number: CloudDiskService_IncreaseCnt_001 + * @tc.name: IncreaseCnt function + * @tc.desc: Verify IncreaseCnt function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_IncreaseCnt_001, TestSize.Level1) +{ + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + + int32_t initialCount = service->calledCount_.load(); + service->IncreaseCnt("test_func"); + EXPECT_EQ(service->calledCount_.load(), initialCount + 1); +} + +/** + * @tc.number: CloudDiskService_DncreaseCnt_001 + * @tc.name: DncreaseCnt function + * @tc.desc: Verify DncreaseCnt function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_DncreaseCnt_001, TestSize.Level1) +{ + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + + int32_t initialCount = service->calledCount_.load(); + service->DncreaseCnt("test_func"); + EXPECT_EQ(service->calledCount_.load(), initialCount - 1); +} +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/js_file_access_ext_ability_test.cpp b/test/unittest/js_file_access_ext_ability_test.cpp index a7a0b642c3329fcb44709d121855e5d679699c22..91f35e98d660bb6c4f8152cc738e7d50296456d1 100644 --- a/test/unittest/js_file_access_ext_ability_test.cpp +++ b/test/unittest/js_file_access_ext_ability_test.cpp @@ -82,6 +82,46 @@ int32_t FileAccessServiceBaseProxy::DisConnectFileExtAbility(const sptr &syncFolders) +{ + return ERR_OK; +} + +int32_t FileAccessServiceBaseProxy::GetAllSyncFolders(std::vector &syncFolderExts) +{ + return ERR_OK; +} + +int32_t FileAccessServiceBaseProxy::UpdateDisplayName(const std::string &path, const std::string &displayName) +{ + return ERR_OK; +} + +int32_t FileAccessServiceBaseProxy::DeactiveForSa(const std::string &bundleName, int appIndex) +{ + return ERR_OK; +} + void FileAccessExtAbility::Init(const std::shared_ptr &record, const std::shared_ptr &application, std::shared_ptr &handler, diff --git a/test/unittest/mock/file_access_service_mock.h b/test/unittest/mock/file_access_service_mock.h index 6e8f44924025591511f4efcf1732674194c8dde7..c5c587f2cd42bfffd0f18fcf5d281b746d5417d7 100644 --- a/test/unittest/mock/file_access_service_mock.h +++ b/test/unittest/mock/file_access_service_mock.h @@ -42,6 +42,14 @@ public: MOCK_METHOD2(ConnectFileExtAbility, int32_t(const AAFwk::Want &want, const sptr& connection)); MOCK_METHOD1(DisConnectFileExtAbility, int32_t(const sptr& connection)); + MOCK_METHOD1(Register, int32_t(const SyncFolder &rootInfo)); + MOCK_METHOD1(Unregister, int32_t(const std::string &path)); + MOCK_METHOD1(Active, int32_t(const std::string &path)); + MOCK_METHOD1(Deactive, int32_t(const std::string &path)); + MOCK_METHOD1(GetSyncFolders, int32_t(std::vector &syncFolders)); + MOCK_METHOD1(GetAllSyncFolders, int32_t(std::vector &syncFolderExts)); + MOCK_METHOD2(UpdateDisplayName, int32_t(const std::string &path, const std::string &displayName)); + MOCK_METHOD2(DeactiveForSa, int32_t(const std::string &bundleName, int appIndex)); }; } // namespace FileAccessFwk } // namespace OHOS diff --git a/test/unittest/notify_work_service_test.cpp b/test/unittest/notify_work_service_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f94a7b7e66ab71880934f42b1f94edb3e1e9633 --- /dev/null +++ b/test/unittest/notify_work_service_test.cpp @@ -0,0 +1,98 @@ +/* + * 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 "notify_work_service.h" + +#include "cloud_disk_comm.h" +#include "hilog_wrapper.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::FileAccessFwk; +using namespace OHOS::FileManagement; + +namespace OHOS { +namespace FileAccessFwk { +class NotifyWorkServiceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void NotifyWorkServiceTest::SetUpTestCase(void) +{ + // Setup code to run before all tests +} + +void NotifyWorkServiceTest::TearDownTestCase(void) +{ + // Teardown code to run after all tests +} + +void NotifyWorkServiceTest::SetUp() +{ + // Setup code to run before each test +} + +void NotifyWorkServiceTest::TearDown() +{ + // Teardown code to run after each test +} + +/** + * @tc.number: NotifyWorkService_NotifyRootInfoDetail_001 + * @tc.name: Notify root info detail + * @tc.desc: Verify NotifyRootInfoDetail function works correctly + */ +HWTEST_F(NotifyWorkServiceTest, NotifyWorkService_NotifyRootInfoDetail_001, TestSize.Level1) +{ + GTEST_SKIP() << "Skipping test as we need to mock CommonEventManager"; + SyncFolderExt rootInfoExt; + rootInfoExt.bundleName_ = "com.example.simulatecloud"; + rootInfoExt.uri_ = "cloud://test/root"; + rootInfoExt.state_ = State::ACTIVE; + NotifyWorkService& service = NotifyWorkService::GetInstance(); + bool result = service.NotifyRootInfoDetail(rootInfoExt, EventType::REGISTER); + EXPECT_EQ(result, true); +} + +/** + * @tc.number: NotifyWorkService_NotifyRootInfoDetail_002 + * @tc.name: Notify root info detail with different event types + * @tc.desc: Verify NotifyRootInfoDetail works with all event types + */ +HWTEST_F(NotifyWorkServiceTest, NotifyWorkService_NotifyRootInfoDetail_002, TestSize.Level1) +{ + GTEST_SKIP() << "Skipping test as we need to mock CommonEventManager"; + SyncFolderExt rootInfoExt; + rootInfoExt.bundleName_ = "com.example.simulatecloud"; + rootInfoExt.uri_ = "cloud://test/root"; + rootInfoExt.state_ = State::ACTIVE; + + NotifyWorkService& service = NotifyWorkService::GetInstance(); + std::vector eventTypes = {EventType::REGISTER, EventType::UNREGISTER, + EventType::ACTIVE, EventType::INACTIVE}; + for (const auto& eventType : eventTypes) { + bool result = service.NotifyRootInfoDetail(rootInfoExt, eventType); + EXPECT_EQ(result, true); + } +} +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file diff --git a/utils/file_access_framework_errno.h b/utils/file_access_framework_errno.h index cc11ccbb32bbd6894a0fe413f61b90b3af6d0535..eedba99c2db7521d8e6b1c18fde2ede22bd18120 100644 --- a/utils/file_access_framework_errno.h +++ b/utils/file_access_framework_errno.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-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 @@ -17,6 +17,7 @@ #define FILE_ACCESS_FRAMEWORK_ERRNO_H #include "errors.h" +#include namespace OHOS { namespace FileAccessFwk { @@ -28,6 +29,8 @@ const int ERR_URI = 13900002; const int ERR_NOT_DIR = 13900018; const int ERR_IS_DIR = 13900019; const int BASE_OFFSET = 14300001; +constexpr int CLOUD_DISK_BASE_OFFSET = 14500001; + enum { ERR_OK = 0, E_IPCS = BASE_OFFSET, // IPC error @@ -46,7 +49,23 @@ enum { E_DO_NOT_HAVE_PARENT, // Do not have parent uri in observerNode E_LOAD_SA, // load SA failed E_PERMISSION = 201, // Permission verification failed - E_PERMISSION_SYS // is not system app + E_PERMISSION_SYS, // is not system app + ERR_NOT_SUPPORT = 801, + ERR_SERVICE_DIED = 29189, + + // cloud disk errcode + ERR_INVALID_PARAM = CLOUD_DISK_BASE_OFFSET, // Invalid parameter + ERR_PERSIST_SYNC_FOLDER_FAILED, // Failed to persist Sync folder + ERR_IPC_FAILED, // IPC error + ERR_SYNC_FOLDER_LIMIT_EXCEEDED, // Sync folder limit exceeded + ERR_SYNC_FOLDER_CONFLICT_SELF, // Conflict with own app's Sync folder + ERR_SYNC_FOLDER_CONFLICT_OTHER, // Conflict with other app's Sync folder + ERR_CREATE_SYNC_FOLDER_FAILED, // Failed to create Sync folder + ERR_SYNC_FOLDER_NOT_EXIST, // Sync folder does not exist + ERR_REMOVE_SYNC_FOLDER_FAILED, // Failed to remove Sync folder + ERR_UPDATE_SYNC_FOLDER_FAILED, // Failed to update Sync folder properties + ERR_INTERNAL_ERROR, // Internal error + ERR_SYSTEM_RESTRICTED, // System restricted }; } // namespace FileAccessFwk } // namespace OHOS