MediaProvider 模块

MediaProvider 模块可优化编入索引的元数据(来自 SD 卡和 USB 设备的音频、视频和图片),并通过 MediaStore 公共 API 将这些数据提供给应用。为了维护用户隐私,MediaProvider 模块强制采用 Android 10 中引入的分区存储安全模型,其中包括隐去敏感的位置元数据。此模块是可更新的,因此 Android 可以更快地应对安全问题(保护敏感的用户数据),而且还能更快地添加新媒体格式(为用户和开发者提供一致性)。

Android 10 中的变化

Android 10 引入了几项与识别和提取媒体文件中的数据相关的改进,具体说明如下:

  • 使用文件的 MIME 类型的第一部分来确定文件内容类型。例如,操作系统知道 image/pngimage/x-newly-invented-format 都是图片,因此可以准确地向最终用户描述相关权限。

  • 仅使用文件扩展名来确定 MIME 类型(而不使用内容嗅探功能,以避免安全问题)。

  • 使用上游 Debian Linux 和 Android 映射的组合来确定任意文件的 MIME 类型。

  • video/*audio/* 文件(通过 MediaMetadataRetriever)以及 image/* 文件(通过 ExifInterface)返回相关数据。

Android 11 中的变化

在 Android 11 中,MediaProvider 模块基于在 Android 10 中做出的更改构建,并且进行了以下改进:

  • 改进了索引编制。现在,MediaProvider 模块通过对照 MediaStore 公共 API 协调可用的元数据来将元数据编入索引。更改包括:

    • 新增了 is_favorite 列和 QUERY_ARG_MATCH_FAVORITE 参数,可让图库式应用根据此列快速过滤媒体。

    • 将颜色空间元数据编入索引。

    • 新增了“is_trashed”列和 QUERY_ARG_MATCH_TRASHED 参数,可让图库式应用根据此列过滤。

    • 新增了 API,支持通过单个用户对话框提示来批量修改多项内容,包括 createDeleteRequest()createFavoriteRequest()createTrashRequest()createWriteRequest()

    • 新增了 GENERATION_ADDEDGENERATION_MODIFIED 列,用于快速可靠地检测自上一个同步点以来发生的更改。

    • 新增了 GROUP BY 公共 API,用于上文未提及的其他元数据列。

  • 改进了 ExifInterface,以从 PNG 和 WebP 容器中提取元数据。

  • 改进了 SystemUI,以将 DateTimeOriginal 元数据写入屏幕截图。

此外,您现在还可以自定义 MediaProvider,方法是添加新的媒体格式、标记应将哪些存储设备编入索引,甚至替换 MTP 堆栈。如需了解详情,请参阅自定义

模块边界

Android 11 将 packages/providers/MediaProvider 中的所有代码迁移到了一个新位置,但与 MTP 相关的逻辑是一个值得注意的特例。此外,frameworks/base/core/java/android/provider/MediaStore.java 现在位于 packages/providers/MediaProvider 处的模块边界内。

软件包格式

MediaProvider 模块采用“APEX 中的 APK”格式。

依赖项

MediaProvider 依赖项与自定义相关(也就是说,如果您自定义 MediaProvider,则必须确保实现满足与自定义关联的依赖项要求)。

  • 使用自定义或非标准媒体文件格式(例如,由供应商专属相机应用生成的格式)时,您必须向 MimeUtils 和媒体提取器模块注册每种自定义格式,才能让 MediaProvider 将相应内容编入索引。

  • 如需确保 MediaProvider 将 StorageManagerService 实现中使用的一组自定义存储设备(如 SD 卡插槽和 USB 端口)编入索引,请设置 VolumeInfo.MOUNT_FLAG_INDEXABLE 标志。

  • 使用自定义(非 AOSP)MTP 实现时,请确保该实现仅依赖于公共 API 和系统 API,以使其能够与 MediaStore 进行交互。

自定义

您现在可以添加新的媒体格式、控制将哪些存储设备编入索引,以及替换 MTP 堆栈。

  • 自定义媒体格式。对于每种新的自定义媒体格式,您必须提供从唯一文件扩展名到 MIME 类型的映射。我们强烈建议您遵循 IANA 注册流程

    • 您无法重新定义已在 AOSP 中定义的扩展名或 MIME 类型。

    • 对于 video/*audio/* 文件,MediaProvider 继续咨询 MediaMetadataRetriever。您可以使用 Android 10 媒体提取器返回自定义格式的元数据。

    • 对于 image/* 文件,MediaProvider 继续使 Exif 对元数据进行标准化。您可以扩展 android.media.ExifInterface 以提取并返回任何自定义图片格式的 Exif 元数据。

  • 存储设备编入索引标志 - MediaProvider 会将 StorageManager.getStorageVolumes() 返回的所有卷(其中,StorageVolume.getMediaStoreVolumeName() 为非 null 值)编入索引。您可以自定义返回的卷列表以控制将哪些卷编入索引,但我们建议不要包含瞬态卷(如 USB OTG 驱动器)。

  • MTP 堆栈替换 - Android 11 将 MTP 堆栈完全放置在模块边界之外,并确保它对照公共 API 运行。

测试

您可以使用以下测试来验证 MediaProvider 的功能:

  • 如需验证 MediaStore 公共 API 的功能,请使用 Android 兼容性测试套件 (CTS) 的 CtsProviderTestCases 软件包中的测试。

  • 如需验证 MediaProvider 内部构件的功能,请使用 MediaProviderTests 中的测试。

如需同时运行这两组测试,请使用以下 atest 命令:

atest --test-mapping packages/providers/MediaProvider