实现 IMS

Android 9 引入了一个名为 ImsService 的新 SystemApi 接口,可帮助您实现 IP 多媒体子系统 (IMS)。ImsService API 是 Android 平台与供应商(即运营商提供的 IMS 实现)之间明确定义的接口。

ImsService 概览

图 1. ImsService 概览

通过使用 ImsService 接口,IMS 实现者可以向平台提供重要的信号信息(例如 IMS 注册信息、基于 IMS 集成的短信以及 MmTel 功能集成),以提供语音通话和视频通话功能。ImsService API 也是一种 Android System API,这意味着您可以直接针对 Android SDK(而不是来源)构建这种 API。预安装在设备上的 IMS 应用也可以配置为可通过 Play 商店更新。

示例和来源

为了便于进行测试和开发,Android 在 AOSP 中提供了一个应用,它可以实现 ImsService API 的某些部分。您可以在以下位置找到该应用:/testapps/ImsTestService

您可以在 ImsService 和该 API 的其他类中找到关于 ImsService API 的文档。

实现

ImsService API 是一种高级 API,它可以让您通过多种方式实现 IMS(具体取决于可用的硬件)。例如,根据 IMS 实现是完全在应用处理器上进行,还是部分或完全分流到调制解调器,实现也会发生相应的变化。Android 不提供用于分流到基带处理器的公共 HAL,因此您必须使用调制解调器的 HAL 扩展来进行所有的分流。

与较早的 IMS 实现之间的兼容性

尽管 Android 9 包含 ImsService API,但使用较早的 IMS 实现的设备无法支持该 API。对于这类设备,较早的 AIDL 接口和封装容器类已迁移至 android.telephony.ims.compat 命名空间。升级到 Android 9 后,旧款设备必须执行以下操作才能继续支持旧版 API。

  • 更改 ImsService 实现的命名空间,以从 android.telephony.ims.compat 命名空间 API 进行扩展。
  • 修改 AndroidManifest.xml 中的 ImsService 服务定义,以使用 android.telephony.ims.compat.ImsService intent-filter 操作(而不是 android.telephony.ims.ImsService 操作)。

随后,框架将使用 Android 9 中提供的兼容性层绑定到 ImsService,以支持传统的 ImsService 实现。

向框架注册 ImsService

ImsService API 是作为服务实现的,Android 框架会绑定到该服务以便与 IMS 实现进行通信。要向框架注册实现了 ImsService 的应用,您必须执行以下 3 个步骤:首先,ImsService 实现必须使用相关应用的 AndroidManifest.xml 向平台自行注册;其次,它必须定义实现支持哪种 IMS 功能(MmTel 还是 RCS);最后,它必须在运营商配置或设备叠加层中验证为受信任的 IMS 实现。

服务定义

IMS 应用可使用以下格式将 service 条目添加到清单中,从而向框架注册 ImsService:

<service
    android:name="com.egcorp.ims.EgImsService"
    android:directBootAware="true"
    Android:persistent="true"
    ...
    android:permission="android.permission.BIND_IMS_SERVICE" >
    ...
    <intent-filter>
        <action android:name="android.telephony.ims.ImsService" />
    </intent-filter>
</service>

AndroidManifest.xml 中的 service 定义对以下属性进行了定义,这些属性是正确运行所必需的属性:

  • directBootAware="true":允许在文件系统被解密之前找到并绑定 service。这意味着 ImsService 不得在访问文件系统时打开任何加密文件。要详细了解文件级加密 (FBE),请参阅文件级加密
  • persistent="true":允许此服务永久运行,不因系统回收内存而终止。只有在相应的应用作为系统应用进行构建时,此属性才有效。
  • permission="android.permission.BIND_IMS_SERVICE":确保只有被授予 BIND_IMS_SERVICE 权限的进程才能绑定到相应的应用。这样可以防止将恶意应用绑定到该服务,因为框架只会向系统应用授予这项权限。

此外,该服务还必须指定 intent-filter 元素以及操作 android.telephony.ims.ImsService。这样一来,框架便可以找到 ImsService

IMS 功能规范

在 AndroidManifest.xml 中将 ImsService 定义为 Android 服务后,ImsService 必须定义它支持的 IMS 功能。Android 目前支持 MmTel 和 RCS 功能,不过只有 MmTel 集成到了框架中。虽然框架中没有集成 RCS API,但将其声明为 ImsService 的功能仍有诸多好处。

下面列出了 android.telephony.ims.ImsFeature 中定义的 ImsService 可以提供的有效功能,并举例说明了为什么 IMS 应用希望实现所有这些功能或其中某个功能。在对各个功能进行定义后,此页面还概述了 ImsService 如何声明它为每个 SIM 卡插槽定义的功能集。

FEATURE_MMTEL

ImsService 可实现 IMS MMTEL 功能,该功能包含对所有 IMS 媒体(IR.92 和 IR.94 规范)的支持(紧急连接到 IMS PDN 以进行紧急呼叫的情况除外)。任何希望支持 MMTEL 功能的 ImsService 实现都应该扩展 android.telephony.ims.MmTelFeature 基类,并在 ImsService#createMmTelFeature 中返回自定义 MmTelFeature 实现。

FEATURE_EMERGENCY_MMTEL

声明这项功能只会向可紧急连接到 IMS PDN 以获取紧急服务的平台发送信号。如果不为您的 ImsService 声明此功能,平台将始终默认将电路域回落用于紧急服务。要定义此功能,您必须先定义 FEATURE_MMTEL 功能。

FEATURE_RCS

ImsService API 不实现任何 IMS RCS 功能,但 android.telephony.ims.RcsFeature 基类仍然非常有用。检测到软件包应提供 RCS 时,框架会自动绑定到 ImsService 并调用 ImsService#createRcsFeature。如果取出与 RCS 服务相关联的 SIM 卡,则框架会自动调用 RcsFeature#onFeatureRemoved,然后清除与 RCS 功能相关联的 ImsService。此功能可以移除某些 RCS 功能必须提供的自定义检测/绑定逻辑。

注册受支持的功能

电话框架会先绑定到 ImsService,以使用 ImsService#querySupportedImsFeatures API 查询它支持的功能。在框架计算出 ImsService 将会支持的功能之后,它会调用 ImsService 将负责的各项功能的 ImsService#create[...]Feature。如果 IMS 应用支持的功能发生更改,您可以使用 ImsService#onUpdateSupportedImsFeatures 向框架发出信号,以重新计算受支持的功能。有关 ImsService 的初始化和绑定的更多信息,请参见下图。

ImsService 初始化和绑定

图 2:ImsService 初始化和绑定

ImsService 的框架检测和验证

在 AndroidManifest.xml 中对 ImsService 进行正确定义后,必须将平台配置为适时(安全地)绑定到 ImsService。框架可绑定到以下两种 ImsService:

  1. 运营商“替换”ImsService:这类 ImsService 会预先加载到设备上,但与一个或多个手机运营商相关联,并且只有在插入匹配的 SIM 卡时才会绑定。该类型是使用 key_config_ims_package_override CarrierConfig 密钥配置的。
  2. 设备“默认”ImsService:该类型是由原始设备制造商 (OEM) 加载到设备上的默认 ImsService。当运营商 ImsService 不可用时,它应该能够在任何情况下提供 IMS 服务。在设备没有插入 SIM 卡或插入的 SIM 卡没有安装运营商 ImsService 的情况下,这种 ImsService 非常有用。该类型是在设备叠加层 config_ims_package 密钥中进行定义的。

这两种类型的 ImsService 实现必须是系统应用,或必须驻留在 /system/priv-app/ 文件夹中,以授予相应的由用户授予的权限(即电话、麦克风、位置、相机和通讯录权限)。通过验证 IMS 实现的软件包名称是否与上文定义的 CarrierConfig 或设备叠加层值匹配,仅绑定受信任的应用。

自定义

ImsService 允许通过更新(使用 ImsService#onUpdateSupportedImsFeatures 方法)以动态的形式启用或停用它支持的 IMS 功能(MMTEL 和 RCS)。这样会触发框架重新计算要绑定哪些 ImsService 以及它们支持哪些功能。如果 IMS 应用在没有任何受支持的功能的情况下更新框架,则在手机重新启动或插入与 IMS 应用匹配的新 SIM 卡之前,ImsService 将处于未绑定状态。

多个 ImsService 的绑定优先级

框架不支持绑定到设备上预装的所有可能的 ImsService,并将按以下顺序绑定到 ImsService(每个 SIM 插槽最多可绑定两个 ImsService,每个功能一个 ImsService):

  1. 由 CarrierConfig 值 key_config_ims_package_override 定义的 ImsService 软件包名称(插入 SIM 卡的情况下)。
  2. config_ims_package 的设备叠加层值中定义的 ImsService 软件包名称,包括没有 SIM 卡插入的情况。此 ImsService 必须支持 Emergency MmTel 功能。

您必须在 CarrierConfig 中为每个将使用 ImsService 软件包的运营商定义您 ImsService 的软件包名称;如果您的 ImsService 是默认类型,则应在设备叠加层中定义(如上所述)。

下面我们针对每种功能进行详细介绍。单 SIM 卡设备可提供两种 IMS 功能:MMTel 和 RCS。框架将尝试按照上文中所述的顺序为每种功能进行绑定;如果相应功能不适用于运营商配置替换中定义的 ImsService,则框架将回退到您的默认 ImsService。例如,下表说明了框架将使用哪种 IMS 功能(假设三个 IMS 应用实现了某个系统上安装的具有以下功能的 ImsService):

  • 运营商 A ImsService 支持 RCS
  • 运营商 B ImsService 支持 RCS 和 MMTel
  • OEM ImsService 支持 RCS、MMTel 和 Emergency MMTel
已插入 SIM 卡 RCS 功能 MMTel 功能 紧急 MMTel 功能
运营商 A 运营商 A OEM OEM
运营商 B 运营商 B 运营商 B OEM
没有 SIM 卡 OEM OEM OEM

验证

ImsService API 包括一个 GTS 测试套件,可验证框架中 ImsService API 的功能以及 IMS 应用服务绑定逻辑。GtsImsServiceTestCases GTS APK 可以作为 GTS 测试套件的一部分运行,以确保 API 表面在所有 Android 9 实现中一致地运行。

由于 IMS 规范非常多且使用的是特殊验证设备,因此测试套件中不包含用于自行验证 IMS 实现的工具。这些测试只能验证电话框架是否正确响应 ImsService API。