【OpenHarmony】用户文件服务模块架构
用户文件服务模块架构
1. 模块概述
公共文件访问框架(FileAccessFramework)提供了一套公共文件访问和管理的接口。公共文件访问框架中FileAccessFramework向下对接底层文件管理服务,如medialibrary、externalFileManager。FileAccessFramework向上对接应用,提供对公共文件操作的基础能力。
源码:https://gitee.com/openharmony/filemanagement_user_file_service
1.1 功能与目标
主要功能:
用户文件服务模块(User File Service)是OpenHarmony系统中的公共文件访问框架(FileAccessFramework),提供了一套统一的文件访问和管理接口。该模块的主要功能包括:
- 文件操作管理:提供查询、创建、删除、打开、移动、重命名用户公共文件路径下媒体文件和文档文件的能力
- 多设备文件访问:支持访问共享盘设备、外置存储设备上的文件,以目录树方式呈现
- 媒体文件管理:支持图片、音频、视频等媒体文件的相册方式呈现和管理
- 文件选择器:提供文件选择器功能,支持应用选择文件
- 文件观察者:提供文件变化监听和通知机制
- 权限管理:集成文件访问权限控制和验证
使用场景:
- 文件管理器应用的文件操作
- 文件选择器组件的文件选择
- 媒体应用的文件访问
- 跨设备文件共享和管理
- 第三方应用的文件操作需求
1.2 系统位置
系统架构位置:
用户文件服务模块位于OpenHarmony系统的foundation/filemanagement
子系统下,是文件管理框架的核心组件之一。
模块关系:
- 上层对接:为应用层提供文件访问API,支持JS、Native、C等多种接口形式
- 下层对接:对接底层文件管理服务,如medialibrary、externalFileManager等
- 横向协作:与app_file_service、storage_service等模块协作
- 系统集成:集成到系统能力管理器中,提供系统级文件访问能力
核心模块地位:
该模块是文件管理子系统的核心模块,承担着统一文件访问接口的重要职责,是连接应用和底层存储服务的关键桥梁。
1.3 设计思路与模式
设计思路:
- 统一接口设计:通过FileAccessFramework提供统一的文件访问接口,屏蔽底层存储差异
- 扩展性架构:采用Extension机制,支持不同存储提供者的插件化接入
- 异步处理机制:采用异步回调模式,提高系统响应性能
- 权限安全控制:集成权限验证机制,确保文件访问安全
- 多语言支持:提供JS、Native、C等多种语言接口
设计模式:
- 代理模式:FileAccessService作为代理,管理Extension连接和请求转发
- 观察者模式:文件变化通知机制,支持多观察者订阅
- 工厂模式:Extension创建和管理机制
- 单例模式:FileAccessService采用单例模式确保全局唯一性
- 策略模式:不同存储类型的处理策略
1.4 系统框图
2. 模块结构
2.1 源文件与头文件
核心服务文件:
services/native/file_access_service/include/file_access_service.h
- 文件访问服务主类定义services/native/file_access_service/src/file_access_service.cpp
- 文件访问服务实现services/native/file_access_service/include/file_access_service_client.h
- 服务客户端接口services/native/file_access_service/src/file_access_service_client.cpp
- 服务客户端实现
Extension相关文件:
interfaces/inner_api/file_access/include/file_access_ext_ability.h
- Extension能力基类interfaces/inner_api/file_access/src/file_access_ext_ability.cpp
- Extension能力实现interfaces/inner_api/file_access/include/file_access_extension_info.h
- Extension信息定义interfaces/inner_api/file_access/include/app_file_access_ext_connection.h
- Extension连接管理
接口定义文件:
interfaces/inner_api/file_access/IFileAccessExtBase.idl
- Extension基础接口定义services/IFileAccessServiceBase.idl
- 服务基础接口定义services/IFileAccessObserver.idl
- 观察者接口定义services/NotifyType.idl
- 通知类型定义
JS API文件:
frameworks/js/napi/file_access_module/napi_fileaccess_helper.h
- JS文件访问助手frameworks/js/napi/file_access_module/native_fileaccess_module.cpp
- Native模块实现frameworks/js/napi/file_access_ext_ability/file_access_ext_ability_module.cpp
- Extension模块
Picker相关文件:
interfaces/kits/picker/include/picker_n_exporter.h
- Picker导出器interfaces/kits/picker/src/picker_n_exporter.cpp
- Picker实现interfaces/kits/picker/picker.js
- JS接口定义
工具和辅助文件:
utils/file_access_check_util.h
- 文件访问检查工具utils/file_access_framework_errno.h
- 错误码定义utils/file_util.h
- 文件工具函数
2.2 类、结构体、函数与方法
核心类定义:
FileAccessService类
class FileAccessService final : public SystemAbility, public FileAccessServiceBaseStub {
public:// 服务管理static sptr<FileAccessService> GetInstance();void Init();virtual void OnStart() override;virtual void OnStop() override;// 观察者管理int32_t RegisterNotify(const Uri &uri, bool notifyForDescendants, const sptr<IFileAccessObserver> &observer,const ConnectExtensionInfo& info);int32_t UnregisterNotify(const Uri &uri, const sptr<IFileAccessObserver> &observer,const ConnectExtensionInfo& info);// Extension管理int32_t GetExtensionProxy(const ConnectExtensionInfo& info,sptr<IFileAccessExtBase> &extensionProxy);int32_t ConnectFileExtAbility(const AAFwk::Want &want,const sptr<AAFwk::IAbilityConnection>& connection);private:// 内部管理std::unordered_map<std::string, std::shared_ptr<ObserverNode>> relationshipMap_;HolderManager<std::shared_ptr<ObserverContext>> obsManager_;std::unordered_map<std::string, sptr<IFileAccessExtBase>> cMap_;
};
FileAccessExtAbility类
class FileAccessExtAbility : public ExtensionBase<> {
public:// 文件操作接口virtual int OpenFile(const Uri &uri, const int flags, int &fd);virtual int CreateFile(const Uri &parent, const std::string &displayName, Uri &newFile);virtual int Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile);virtual int Delete(const Uri &sourceFile);virtual int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile);virtual int Copy(const Uri &sourceUri, const Uri &destUri, std::vector<Result> ©Result, bool force = false);virtual int Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile);// 文件查询接口virtual int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount,const FileFilter &filter, std::vector<FileInfo> &fileInfoVec);virtual int ScanFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount,const FileFilter &filter, std::vector<FileInfo> &fileInfoVec);virtual int Query(const Uri &uri, std::vector<std::string> &columns, std::vector<std::string> &results);// 文件信息接口virtual int GetFileInfoFromUri(const Uri &selectFile, FileInfo &fileInfo);virtual int GetFileInfoFromRelativePath(const std::string &selectFile, FileInfo &fileInfo);virtual int GetRoots(std::vector<RootInfo> &rootInfoVec);virtual int Access(const Uri &uri, bool &isExist);// 观察者接口virtual int StartWatcher(const Uri &uri);virtual int StopWatcher(const Uri &uri);
};
重要结构体:
FileInfo结构体
struct FileInfo : public virtual OHOS::Parcelable {
public:std::string uri { "" }; // 文件URIstd::string relativePath { "" }; // 相对路径std::string fileName { "" }; // 文件名int32_t mode { 0 }; // 文件模式int64_t size { 0 }; // 文件大小int64_t mtime { 0 }; // 修改时间std::string mimeType { "" }; // MIME类型// 序列化支持bool ReadFromParcel(Parcel &parcel);virtual bool Marshalling(Parcel &parcel) const override;static FileInfo *Unmarshalling(Parcel &parcel);
};
RootInfo结构体
struct RootInfo : public virtual OHOS::Parcelable {
public:int32_t deviceType { 0 }; // 设备类型std::string uri { "" }; // 根URIstd::string relativePath { "" }; // 相对路径std::string displayName { "" }; // 显示名称int32_t deviceFlags { 0 }; // 设备标志// 序列化支持bool ReadFromParcel(Parcel &parcel);virtual bool Marshalling(Parcel &parcel) const override;static RootInfo *Unmarshalling(Parcel &parcel);
};
Result结构体
struct Result : public virtual OHOS::Parcelable {
public:std::string sourceUri { "" }; // 源URIstd::string destUri { "" }; // 目标URIint32_t errCode { 0 }; // 错误码std::string errMsg { "" }; // 错误消息// 序列化支持bool ReadFromParcel(Parcel &parcel);virtual bool Marshalling(Parcel &parcel) const override;static Result *Unmarshalling(Parcel &parcel);
};
2.3 继承与多态
继承关系:
FileAccessService
继承自SystemAbility
和FileAccessServiceBaseStub
,实现系统服务能力FileAccessExtAbility
继承自ExtensionBase<>
,提供Extension能力基类FileInfo
、RootInfo
、Result
等结构体继承自Parcelable
,支持跨进程序列化ObserverContext
和ObserverNode
提供观察者模式的基础实现
多态设计:
- Extension机制支持不同存储提供者的插件化实现
- 观察者模式支持多种文件变化事件的统一处理
- 接口抽象实现不同文件操作类型的统一管理
- 回调机制支持异步操作结果的统一处理
2.4 类图
2.5 模块内部依赖框图
3. 模块间交互
3.1 交互描述
与系统模块的交互:
- 权限管理:通过AccessToken模块验证文件访问权限
- 系统能力管理:通过SAMGR注册为系统能力,提供全局服务
- 进程间通信:通过IPC机制与Extension和客户端通信
- 应用框架:通过AAFwk管理Extension生命周期
- 事件系统:通过CommonEvent处理系统级文件变化事件
- 存储管理:与StorageService协作管理存储设备
外部库依赖:
- 系统框架:SAMGR、SAFWK、AAFwk等系统框架
- IPC框架:支持跨进程通信的IPC机制
- 权限框架:AccessToken权限验证框架
- 工具库:cJSON、c_utils等基础工具库
- 日志框架:HiLog日志记录框架
异步处理机制:
- 使用NAPI异步工作队列处理JS回调
- 通过IPC异步机制处理跨进程请求
- 采用观察者模式处理文件变化通知
- 支持多线程并发处理文件操作请求
3.2 事件驱动机制
事件类型:
NOTIFY_ADD
- 文件添加事件NOTIFY_DELETE
- 文件删除事件NOTIFY_MOVE_TO
- 文件移动到事件NOTIFY_MOVE_FROM
- 文件移动出事件NOTIFY_MOVE_SELE
- 文件自身移动事件NOTIFY_DEVICE_ONLINE
- 设备上线事件NOTIFY_DEVICE_OFFLINE
- 设备下线事件
事件处理流程:
- 注册文件观察者到指定URI
- 底层存储服务检测到文件变化
- Extension接收变化通知并处理
- FileAccessService转发通知给观察者
- 观察者回调函数处理事件
3.3 外部依赖框图
4. 状态机转换图
4.1 状态机模型
用户文件服务模块的状态机包含以下主要状态:
服务状态:
STATE_NOT_START
- 服务未启动STATE_RUNNING
- 服务运行中STATE_STOPPING
- 服务停止中STATE_EXIT
- 服务已退出
Extension状态:
EXT_NOT_CONNECTED
- Extension未连接EXT_CONNECTING
- Extension连接中EXT_CONNECTED
- Extension已连接EXT_DISCONNECTED
- Extension已断开
观察者状态:
OBS_NOT_REGISTERED
- 观察者未注册OBS_REGISTERED
- 观察者已注册OBS_NOTIFYING
- 正在通知观察者OBS_UNREGISTERED
- 观察者已注销
文件操作状态:
OP_IDLE
- 操作空闲OP_IN_PROGRESS
- 操作进行中OP_SUCCESS
- 操作成功OP_FAILED
- 操作失败
4.2 状态切换规则
服务启动流程:
- 系统启动时,服务处于
STATE_NOT_START
状态 - 收到启动事件后,进入
STATE_RUNNING
状态 - 初始化Extension管理和观察者管理
- 注册到系统能力管理器
Extension连接流程:
- 收到连接请求时,从
EXT_NOT_CONNECTED
进入EXT_CONNECTING
状态 - 连接成功后,进入
EXT_CONNECTED
状态 - 连接失败或断开时,回到
EXT_NOT_CONNECTED
状态
观察者注册流程:
- 收到注册请求时,从
OBS_NOT_REGISTERED
进入OBS_REGISTERED
状态 - 文件变化时,进入
OBS_NOTIFYING
状态 - 通知完成后,回到
OBS_REGISTERED
状态 - 注销时,进入
OBS_UNREGISTERED
状态
文件操作流程:
- 收到操作请求时,从
OP_IDLE
进入OP_IN_PROGRESS
状态 - 操作成功时,进入
OP_SUCCESS
状态 - 操作失败时,进入
OP_FAILED
状态 - 操作完成后,回到
OP_IDLE
状态
事件触发条件:
- 系统启动/停止事件
- Extension连接/断开事件
- 文件变化事件
- 观察者注册/注销事件
- 文件操作请求事件
4.3 状态机转换图
5. 接口设计
5.1 公共接口
文件操作接口:
打开文件
int OpenFile(const Uri &uri, const int flags, int &fd);
- 功能:打开指定URI的文件
- 参数:
uri
- 文件URIflags
- 打开标志(READ、WRITE、WRITE_READ)fd
- 输出参数,文件描述符
- 返回值:操作结果码
- 异常处理:URI无效时返回错误码
创建文件
int CreateFile(const Uri &parent, const std::string &displayName, Uri &newFile);
- 功能:在指定父目录下创建新文件
- 参数:
parent
- 父目录URIdisplayName
- 文件名newFile
- 输出参数,新文件URI
- 返回值:操作结果码
- 权限要求:文件创建权限
删除文件
int Delete(const Uri &sourceFile);
- 功能:删除指定文件或目录
- 参数:
sourceFile
- 要删除的文件URI - 返回值:操作结果码
- 权限要求:文件删除权限
移动文件
int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile);
- 功能:将文件移动到目标父目录
- 参数:
sourceFile
- 源文件URItargetParent
- 目标父目录URInewFile
- 输出参数,新文件URI
- 返回值:操作结果码
复制文件
int Copy(const Uri &sourceUri, const Uri &destUri, std::vector<Result> ©Result, bool force = false);
- 功能:复制文件到目标位置
- 参数:
sourceUri
- 源文件URIdestUri
- 目标URIcopyResult
- 输出参数,复制结果列表force
- 是否强制覆盖
- 返回值:操作结果码
文件查询接口:
列出文件
int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount,const FileFilter &filter, std::vector<FileInfo> &fileInfoVec);
- 功能:列出指定目录下的文件
- 参数:
fileInfo
- 目录信息offset
- 偏移量maxCount
- 最大数量filter
- 文件过滤器fileInfoVec
- 输出参数,文件信息列表
- 返回值:操作结果码
扫描文件
int ScanFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount,const FileFilter &filter, std::vector<FileInfo> &fileInfoVec);
- 功能:扫描指定目录下的文件(递归)
- 参数:同ListFile
- 返回值:操作结果码
获取根目录
int GetRoots(std::vector<RootInfo> &rootInfoVec);
- 功能:获取所有可用的根目录信息
- 参数:
rootInfoVec
- 输出参数,根目录信息列表 - 返回值:操作结果码
观察者接口:
注册观察者
int32_t RegisterNotify(const Uri &uri, bool notifyForDescendants, const sptr<IFileAccessObserver> &observer,const ConnectExtensionInfo& info);
- 功能:注册文件变化观察者
- 参数:
uri
- 观察的URInotifyForDescendants
- 是否包含子目录observer
- 观察者对象info
- 连接信息
- 返回值:操作结果码
注销观察者
int32_t UnregisterNotify(const Uri &uri, const sptr<IFileAccessObserver> &observer,const ConnectExtensionInfo& info);
- 功能:注销文件变化观察者
- 参数:同RegisterNotify
- 返回值:操作结果码
5.2 数据交换接口
IPC接口定义:
- 使用IDL定义跨进程接口
- 支持Parcelable对象序列化
- 提供异步回调机制
数据格式:
- FileInfo、RootInfo、Result等结构体支持序列化
- 使用MessageParcel进行数据传递
- 支持大数据量的共享内存传输
5.3 接口调用时序图
6. 总结
用户文件服务模块是OpenHarmony系统中文件管理框架的核心组件,通过统一的FileAccessFramework接口为应用提供文件访问能力。该模块采用Extension机制支持不同存储提供者的插件化接入,通过观察者模式实现文件变化通知,使用异步处理机制提高系统性能。
主要特点:
- 统一的文件访问接口设计
- 支持多种存储类型的扩展
- 完善的文件变化通知机制
- 安全的权限控制体系
- 高性能的异步处理能力
技术优势:
- 模块化架构设计,易于扩展和维护
- 完善的错误处理和异常管理
- 支持多语言接口(JS、Native、C)
- 高效的跨进程通信机制
- 灵活的观察者模式实现