diff --git a/services/BUILD.gn b/services/BUILD.gn index 329c443b729c54fcfc58b6e66751abf153acc11d..168a7c474d2a41cc6b44414864d7a6c645dca8cb 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -39,12 +39,16 @@ ohos_shared_library("fms_server") { "$FMS_BASE_DIR/src/fileoper", "$FMS_BASE_DIR/include/fileoper", "//base/hiviewdfx/hilog/interfaces/native/innerkits/include/hilog", + "//foundation/filemanagement/storage_service/services/storage_manager/include", + "//foundation/filemanagement/storage_service/interfaces/innerkits/storage_manager/native", ] sources = [ "src/client/file_manager_proxy.cpp", + "src/fileoper/ext_storage/ext_storage_subscriber.cpp", "src/fileoper/external_storage_oper.cpp", "src/fileoper/external_storage_utils.cpp", + "src/fileoper/file_info.cpp", "src/fileoper/media_file_oper.cpp", "src/fileoper/media_file_utils.cpp", "src/fileoper/oper_factory.cpp", @@ -54,10 +58,13 @@ ohos_shared_library("fms_server") { deps = [ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "//base/notification/ans_standard/frameworks/wantagent:wantagent_innerkits", "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", "//foundation/aafwk/standard/interfaces/innerkits/base:base", "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/filemanagement/storage_service/interfaces/innerkits/storage_manager/native:storage_manager_sa_proxy", + "//foundation/filemanagement/storage_service/services/storage_manager:storage_manager", "//foundation/multimedia/medialibrary_standard/frameworks/innerkitsimpl/media_library:media_library", "//foundation/multimedia/medialibrary_standard/frameworks/innerkitsimpl/medialibrary_data_ability:medialibrary_data_ability", "//utils/native/base:utils", @@ -68,6 +75,8 @@ ohos_shared_library("fms_server") { } external_deps = [ "ability_runtime:ability_manager", + "ability_runtime:want", + "ces_standard:cesfwk_innerkits", "hiviewdfx_hilog_native:libhilog", "ipc:ipc_core", "native_appdatamgr:native_appdatafwk", diff --git a/services/include/file_manager_service_def.h b/services/include/file_manager_service_def.h index 6efd8096aa36d8edc97b1661cec2427cd42e9074..7fb87a7fda3df6fae7d349d422d22a445bd1cc8b 100644 --- a/services/include/file_manager_service_def.h +++ b/services/include/file_manager_service_def.h @@ -35,6 +35,13 @@ enum Equipment { EXTERNAL_STORAGE }; +enum VolumeState { + UNMOUNTED = 0, + CHECKING, + MOUNTED, + EJECTING +}; + constexpr int32_t CODE_MASK = 0xff; constexpr int32_t EQUIPMENT_SHIFT = 16; @@ -47,6 +54,9 @@ const std::string FILE_ROOT_NAME = "file_folder"; const std::string ALBUM_TYPE = "album"; const std::string FILE_MIME_TYPE = "file/*"; + +const std::string EXTERNAL_STORAGE_URI = "dataability:///external_storage"; + constexpr int FILE_MEDIA_TYPE = Media::MediaType::MEDIA_TYPE_FILE; constexpr int RESULTSET_EMPTY = 0; constexpr int RESULTSET_ONE = 1; diff --git a/services/src/client/file_manager_proxy.cpp b/services/src/client/file_manager_proxy.cpp index 5fc4431d08b91b7eae0e08b14bdfd2f73e2e2feb..457527e611122a7cae740e2e35870404fe46af08 100644 --- a/services/src/client/file_manager_proxy.cpp +++ b/services/src/client/file_manager_proxy.cpp @@ -28,14 +28,35 @@ namespace FileManagerService { FileManagerProxy::FileManagerProxy(const sptr &impl) : IRemoteProxy(impl) {} -int FileManagerProxy::GetRoot(const std::string &devName, vector &fileRes) const +int FileManagerProxy::GetRoot(const std::string &devName, vector &fileRes) { - // currently getRoot don't need to sendReq - fileRes.emplace_back(IMAGE_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); - fileRes.emplace_back(VIDEO_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); - fileRes.emplace_back(AUDIO_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); - fileRes.emplace_back(FILE_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); - return SUCCESS; + if (devName == "external_storage") { + MessageParcel data; + data.WriteString(devname); + MessageParcel reply; + MessageOption option; + int code = (Equipment::EXTERNAL_STORAGE << EQUIPMENT_SHIFT) | Operation::GET_ROOT; + int err = Remote()->SendRequest(code, data, reply, option); + if (err != ERR_NONE) { + ERR_LOG("GetRoot inner error send request fail %{public}d", err); + return FAIL; + } + int count = 0; + reply.ReadInt32(count); + for (int i = 0; i < count; i++) { + string rootPath; + reply.ReadString(rootPath); + fileRes.emplace_back(FILE_ROOT_NAME, rootPath, ALBUM_TYPE); + } + reply.ReadInt32(err); + return err; + } else { + fileRes.emplace_back(IMAGE_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); + fileRes.emplace_back(VIDEO_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); + fileRes.emplace_back(AUDIO_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); + fileRes.emplace_back(FILE_ROOT_NAME, FISRT_LEVEL_ALBUM, ALBUM_TYPE); + return SUCCESS; + } } int FileManagerProxy::CreateFile(const string &name, const string &path, string &uri) diff --git a/services/src/client/file_manager_proxy.h b/services/src/client/file_manager_proxy.h index 080fedbb774c79e3a4c8a3976c3b0092dbd1647b..2d24e616d01421e05f41592970d638c0db27493e 100644 --- a/services/src/client/file_manager_proxy.h +++ b/services/src/client/file_manager_proxy.h @@ -31,7 +31,7 @@ public: int ListFile(const std::string &type, const std::string &path, const CmdOptions &option, std::vector &fileRes) override; int CreateFile(const std::string &name, const std::string &path, std::string &uri) override; - int GetRoot(const std::string &devName, std::vector &fileRes) const override; + int GetRoot(const std::string &devName, std::vector &fileRes) override; private: static inline BrokerDelegator delegator_; }; diff --git a/services/src/client/ifms_client.h b/services/src/client/ifms_client.h index 26088466493309edd40775c50a13394ef023d8ad..e069f10bf6b289fa6b8bb26c2aceff78dd7a157d 100644 --- a/services/src/client/ifms_client.h +++ b/services/src/client/ifms_client.h @@ -25,7 +25,7 @@ public: virtual int Mkdir(const std::string &name, const std::string &path) = 0; virtual int ListFile(const std::string &type, const std::string &path, const CmdOptions &option, std::vector &fileRes) = 0; - virtual int GetRoot(const std::string &devName, std::vector &fileRes) const = 0; + virtual int GetRoot(const std::string &devName, std::vector &fileRes) = 0; virtual int CreateFile(const std::string &name, const std::string &path, std::string &uri) = 0; }; } // namespace FileManagerService { diff --git a/services/src/fileoper/ext_storage/ext_storage_subscriber.cpp b/services/src/fileoper/ext_storage/ext_storage_subscriber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8cdcc51a82d49ddc8e0faa5e7c86750af4e63e5 --- /dev/null +++ b/services/src/fileoper/ext_storage/ext_storage_subscriber.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 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 "ext_storage_subscriber.h" + +#include + +#include "app_log_wrapper.h" +#include "appexecfwk_errors.h" +#include "bundle_info.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "log.h" +#include "want.h" + +using namespace OHOS::AAFwk; + +namespace OHOS { +namespace FileManagerService { +/** + * @brief Receiver Constructor. + * @param subscriberInfo Subscriber info. + */ +ExtStorageSubscriber::ExtStorageSubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo) + : EventFwk::CommonEventSubscriber(subscriberInfo) +{} + +std::shared_ptr ExtStorageSubscriber_ = nullptr; +bool ExtStorageSubscriber::Subscriber(void) +{ + if (ExtStorageSubscriber_ == nullptr) { + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + + EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); + ExtStorageSubscriber_ = std::make_shared(subscribeInfo); + EventFwk::CommonEventManager::SubscribeCommonEvent(ExtStorageSubscriber_); + } + return true; +} + +/** + * @brief Receive common event. + * @param eventData Common event data. + */ +void ExtStorageSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + const AAFwk::Want& want = eventData.GetWant(); + std::string action = want.GetAction(); + DEBUG_LOG("%{public}s, action:%{public}s.", __func__, action.c_str()); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/services/src/fileoper/ext_storage/ext_storage_subscriber.h b/services/src/fileoper/ext_storage/ext_storage_subscriber.h new file mode 100644 index 0000000000000000000000000000000000000000..06222a6e1c89c21626b954322b512faeb7ff88f6 --- /dev/null +++ b/services/src/fileoper/ext_storage/ext_storage_subscriber.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 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 STORAGE_FILE_SYS_EVENT_RECEIVER_H +#define STORAGE_FILE_SYS_EVENT_RECEIVER_H + +#include "common_event_manager.h" +#include "common_event_subscribe_info.h" +#include "common_event_subscriber.h" +#include "common_event_support.h" +#include "matching_skills.h" + +namespace OHOS { +namespace FileManagerService { +/** + * @class ExtStorageSubscriber + * Receive system common event. + */ +class ExtStorageSubscriber : public EventFwk::CommonEventSubscriber { +public: + ExtStorageSubscriber() = default; + ExtStorageSubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo); + static bool Subscriber(void); + virtual ~ExtStorageSubscriber() = default; + /** + * @brief System common event receiver. + * @param eventData Common event data. + */ + virtual void OnReceiveEvent(const EventFwk::CommonEventData &eventData) override; +}; +} // namespace FileManagerService +} // namespace OHOS + +#endif // STORAGE_FILE_SYS_EVENT_RECEIVER_H \ No newline at end of file diff --git a/services/src/fileoper/external_storage_oper.cpp b/services/src/fileoper/external_storage_oper.cpp index 7d8218938ef87e2699b9e8ef6434c80024d8835f..da0f6c52c43f2bd0ed3e56e844eadea957ccd0fe 100644 --- a/services/src/fileoper/external_storage_oper.cpp +++ b/services/src/fileoper/external_storage_oper.cpp @@ -23,6 +23,7 @@ #include "file_manager_service_errno.h" #include "log.h" +using namespace std; namespace OHOS { namespace FileManagerService { int ExternalStorageOper::OperProcess(uint32_t code, MessageParcel &data, MessageParcel &reply) const @@ -48,6 +49,13 @@ int ExternalStorageOper::OperProcess(uint32_t code, MessageParcel &data, Message errCode = this->CreateFile(uri, name, reply); break; } + case Operation::GET_ROOT: { + string path = data.ReadString(); + // name for extension + string name = "name"; + errCode = GetRoot(path, name, reply); + break; + } default: { DEBUG_LOG("not valid code %{public}d.", code); break; @@ -56,6 +64,11 @@ int ExternalStorageOper::OperProcess(uint32_t code, MessageParcel &data, Message return errCode; } +int ExternalStorageOper::GetRoot(const std::string &path, const std::string &name, MessageParcel &reply) const +{ + return ExternalStorageUtils::DoGetRoot(path, name, reply); +} + int ExternalStorageOper::CreateFile(const std::string &uri, const std::string &name, MessageParcel &reply) const { return ExternalStorageUtils::DoCreateFile(uri, name, reply); diff --git a/services/src/fileoper/external_storage_oper.h b/services/src/fileoper/external_storage_oper.h index 09502070abe54196a82c19f890d881402bff63cc..53ee4e2ebca5bd805b38dfec999be2a6ee1f7eff 100644 --- a/services/src/fileoper/external_storage_oper.h +++ b/services/src/fileoper/external_storage_oper.h @@ -29,6 +29,7 @@ private: int CreateFile(const std::string &uri, const std::string &name, MessageParcel &reply) const; int ListFile(const std::string &type, const std::string &uri, const CmdOptions &option, MessageParcel &reply) const; + int GetRoot(const std::string &path, const std::string &name, MessageParcel &reply) const; }; } // namespace FileManagerService } // namespace OHOS diff --git a/services/src/fileoper/external_storage_utils.cpp b/services/src/fileoper/external_storage_utils.cpp index 8ce1b5b93ce1c2573c6a9119400d3fbc594d9fb8..c0e24ef1ba855ceb96cb61431a5d34a8c6e9eda6 100644 --- a/services/src/fileoper/external_storage_utils.cpp +++ b/services/src/fileoper/external_storage_utils.cpp @@ -26,10 +26,129 @@ #include "file_manager_service_def.h" #include "file_manager_service_errno.h" +#include "ipc/storage_manager_proxy.h" +#include "ipc/storage_manager.h" +#include "istorage_manager.h" #include "log.h" +#include +#include + +using namespace std; +using namespace OHOS::StorageManager; namespace OHOS { namespace FileManagerService { +sptr storageManager_; + +static bool GetPathFromUri(const string &uri, string &path) +{ + uint len = EXTERNAL_STORAGE_URI.size(); + string head = uri.substr(0, len); + + if (head != EXTERNAL_STORAGE_URI) { + ERR_LOG("invalid format uri %{public}s, head check fail", uri.c_str()); + return false; + } + if (uri.size() == len) { + ERR_LOG("uri content is invalid %{public}s", uri.c_str()); + return false; + } + path = uri.substr(len); + return true; +} + +static bool GetRealPath(string &path) +{ + char filePath[PATH_MAX]; + memset(filePath, 0, sizeof(filePath)); + if (realpath(path.c_str(), filePath) == nullptr) { + ERR_LOG("untrustPath invalid %{public}d %{public}s \n", errno, strerror(errno)); + return false; + } + path = string(filePath); + return true; +} + +static int32_t Connect() +{ + DEBUG_LOG("StorageManagerConnect::Connect start"); + auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sam == nullptr) { + ERR_LOG("StorageManagerConnect::Connect samgr == nullptr"); + return FAIL; + } + auto object = sam->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (object == nullptr) { + ERR_LOG("StorageManagerConnect::Connect object == nullptr"); + return FAIL; + } + storageManager_ = iface_cast(object); + if (storageManager_ == nullptr) { + ERR_LOG("StorageManagerConnect::Connect service == nullptr"); + return FAIL; + } + DEBUG_LOG("StorageManagerConnect::Connect end"); + return SUCCESS; +} + +static std::vector GetAllVolumes() +{ + vector result = {}; + if (Connect() != SUCCESS) { + ERR_LOG("GetTotalSizeOfVolume:Connect error"); + return result; + } + return storageManager_->GetAllVolumes(); +} + +static bool GetMountedVolumes(vector &vecRootPath) +{ + bool succ = false; + vector result = GetAllVolumes(); + if(result.size() == 0) { + ERR_LOG("empty volume result"); + return succ; + } + for (auto vol : result) { + ERR_LOG("find vol.GetPath() %{public}d %{public}d", vol.GetState(), VolumeState::MOUNTED); + if (vol.GetState() == VolumeState::MOUNTED) { + ERR_LOG("find vol.GetPath()"); + vecRootPath.emplace_back(EXTERNAL_STORAGE_URI + vol.GetPath()); + succ = true; + } + } + return succ; +} + +static bool GetMountPointFromPath(const string &path, string &mountPoint) +{ + // need to deal with path + mountPoint = path; + return true; +} + +static bool StoragePathValidCheck(const string &path) +{ + string mountPoint; + if (!GetMountPointFromPath(path, mountPoint)) { + ERR_LOG("uri path is invalid"); + return false; + } + vector result = GetAllVolumes(); + if(result.size() == 0) { + ERR_LOG("empty volume result"); + return false; + } + bool succ = false; + for (auto vol : result) { + if (vol.GetPath() == mountPoint && vol.GetState() == VolumeState::MOUNTED) { + succ = true; + break; + } + } + return succ; +} + static bool GetFileInfo(const std::string &path, const std::string &name, FileInfo &fileInfo) { std::string fullPath(""); @@ -54,7 +173,18 @@ static bool GetFileInfo(const std::string &path, const std::string &name, FileIn static bool ConvertUriToAbsolutePath(const std::string &uri, std::string &path) { - path = "/data/media"; + if(!GetPathFromUri(uri, path)) { + ERR_LOG("GetPathFromUri fail"); + return false; + } + if(!GetRealPath(path)) { + ERR_LOG("get real path fail"); + return false; + } + if (!StoragePathValidCheck(path)) { + ERR_LOG("external uri path was ejected"); + return false; + } return true; } @@ -124,6 +254,22 @@ int ExternalStorageUtils::DoCreateFile(const std::string &uri, const std::string return SUCCESS; } +int ExternalStorageUtils::DoGetRoot(const std::string &path, const std::string &name, MessageParcel &reply) +{ + vector vecRootPath; + if(!GetMountedVolumes(vecRootPath)) { + ERR_LOG("there is valid extorage storage"); + reply.WriteInt32(0); + return FAIL; + } + + reply.WriteInt32(vecRootPath.size()); + for (auto path : vecRootPath) { + reply.WriteString(path); + } + return SUCCESS; +} + bool ExternalStorageUtils::PopFileInfo(FileInfo &fileInfo, MessageParcel &reply) { std::string path; diff --git a/services/src/fileoper/external_storage_utils.h b/services/src/fileoper/external_storage_utils.h index 7f4e7f35e0de445242a0a2423258ecea7d18ee6e..c09ba5622b7655703c26aa77528bbc4f0c4975ae 100644 --- a/services/src/fileoper/external_storage_utils.h +++ b/services/src/fileoper/external_storage_utils.h @@ -31,6 +31,7 @@ public: static int DoListFile(const std::string &type, const std::string &uri, MessageParcel &reply); static int DoCreateFile(const std::string &uri, const std::string &name, MessageParcel &reply); static bool PopFileInfo(FileInfo &fileInfo, MessageParcel &reply); + static int DoGetRoot(const std::string &path, const std::string &name, MessageParcel &reply); }; } // namespace FileManagerService } // namespace OHOS diff --git a/services/src/fileoper/file_info.cpp b/services/src/fileoper/file_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..121ad49de4dd081d5f08f733b5445d1c3c2e31fc --- /dev/null +++ b/services/src/fileoper/file_info.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 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_info.h" +#include "log.h" +using namespace std; + +namespace OHOS { +namespace FileManagerService { +bool FileInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteString(path_); + parcel.WriteString(name_); + parcel.WriteString(type_); + parcel.WriteInt64(size_); + parcel.WriteInt64(addedTime_); + parcel.WriteInt64(modifiedTime_); + return true; +} +FileInfo* FileInfo::Unmarshalling(Parcel &parcel) +{ + auto *obj = new (std::nothrow) FileInfo(); + if (obj == nullptr) { + ERR_LOG("Unmarshalling fail"); + } + // auto obj = make_unique(); + obj->path_ = parcel.ReadString(); + obj->name_ = parcel.ReadString(); + obj->type_ = parcel.ReadString(); + obj->size_ = parcel.ReadInt64(); + obj->addedTime_ = parcel.ReadInt64(); + obj->modifiedTime_ = parcel.ReadInt64(); + return obj; +} +} // namespace FileManagerService +} // namespace OHOS + + diff --git a/services/src/fileoper/file_info.h b/services/src/fileoper/file_info.h index a8ab503084dfce5f5219539059f0ea1161c83e2d..8a8742b69811f060918fbf61092aa89ea283bc9e 100644 --- a/services/src/fileoper/file_info.h +++ b/services/src/fileoper/file_info.h @@ -17,14 +17,11 @@ #include #include -#include "ipc_types.h" -#include "iremote_broker.h" -#include "iremote_proxy.h" -#include "iremote_stub.h" +#include "parcel.h" namespace OHOS { namespace FileManagerService { -class FileInfo { +class FileInfo : public Parcelable { public: FileInfo(const std::string &name, const std::string &path, const std::string &type) : path_(path), name_(name), type_(type) {} @@ -79,6 +76,8 @@ public: { return modifiedTime_; } + bool Marshalling(Parcel &parcel) const override; + static FileInfo* Unmarshalling(Parcel &parcel); private: std::string path_; std::string name_; diff --git a/services/src/server/file_manager_service.cpp b/services/src/server/file_manager_service.cpp index 5eae3bcff17f7f2d0037ce832c371ba895d11d99..f1471a258eb289e954b2bb2a84232d22fa129583 100644 --- a/services/src/server/file_manager_service.cpp +++ b/services/src/server/file_manager_service.cpp @@ -18,6 +18,7 @@ #include "iservice_registry.h" #include "log.h" #include "system_ability_definition.h" +#include "ext_storage/ext_storage_subscriber.h" namespace OHOS { namespace FileManagerService { @@ -30,6 +31,7 @@ void FileManagerService::OnDump() {} void FileManagerService::OnStart() { DEBUG_LOG("FileManagerService OnStart"); + ExtStorageSubscriber::Subscriber(); bool res = Publish(this); if (!res) { ERR_LOG("FileManagerService OnStart invalid");