实现 IMS

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

Ims服务概述

图 1. ImsService 概述

通过使用 ImsService 接口,IMS 实现者可以向平台提供重要的信令信息,例如 IMS 注册信息、SMS over IMS 集成以及 MmTel 功能集成以提供语音和视频呼叫。 ImsService API 也是一个 Android 系统 API,这意味着它可以直接针对 Android SDK 而不是针对源代码进行构建。设备上预安装的 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意图过滤器操作,而不是android.telephony.ims.ImsService操作。

然后,该框架将使用 Android 9 中提供的兼容层绑定到 ImsService,以与旧的ImsService实现配合使用。

ImsService 向框架注册

ImsService API 作为服务实现,Android 框架将其绑定到该服务以便与 IMS 实现进行通信。向框架注册实现 ImsService 的应用程序需要三个步骤。首先,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" :允许在用户解锁设备之前通过telephony发现并运行服务。在用户解锁设备之前,服务无法访问设备加密存储。有关详细信息,请参阅支持直接启动模式基于文件的加密
  • persistent="true" :允许该服务持久运行,不会被系统杀死以回收内存。仅当应用程序构建为系统应用程序时,此属性才有效。
  • permission="android.permission.BIND_IMS_SERVICE" :确保只有已授予其BIND_IMS_SERVICE权限的进程才能绑定到应用程序。这可以防止恶意应用程序绑定到服务,因为框架只能向系统应用程序授予权限。

该服务还必须通过操作android.telephony.ims.ImsService指定intent-filter元素。这允许框架找到ImsService

IMS功能规范

在 AndroidManifest.xml 中将 ImsService 定义为 Android 服务后,ImsService 必须定义它支持哪些 IMS 功能。 Android 目前支持 MmTel 和 RCS 功能,但只有 MmTel 集成到框架中。尽管框架中没有集成 RCS API,但将其声明为 ImsService 的功能仍然有优势。

以下是 ImsService 可以提供的android.telephony.ims.ImsFeature中定义的有效功能,以及 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 卡时才会绑定。这是使用以下配置的
  2. 设备“默认”ImsService:这是由 OEM 加载到设备上的默认 ImsService,应设计为在运营商 ImsService 不可用时的所有情况下提供 IMS 服务,并且在设备没有 SIM 卡的情况下很有用已插入或插入的 SIM 卡未安装运营商 ImsService。这是使用以下配置在设备覆盖层中定义的:

Android 不支持具有第三方可下载 ImsService 实现的应用程序,因此此处定义的任何 ImsService 实现都必须是系统应用程序,并且必须驻留在 /system/priv-app/ 或 /product/priv-app/ 文件夹中以授予适当的权限权限(即电话、麦克风、位置、相机和联系人权限)。通过验证 IMS 实现的包名称是否与上面定义的 CarrierConfig 或设备覆盖值匹配,仅绑定受信任的预安装应用程序。

定制化

实现 ImsService 的应用程序仅绑定在配置为运营商“覆盖”ImsService 或设备“默认”ImsService 配置以实现 MMTEL 或 RCS 功能的设备上。 ImsService 还允许使用ImsService#onUpdateSupportedImsFeatures方法通过更新动态启用或禁用它支持的 IMS 功能(MMTEL 和 RCS)。这会触发框架重新计算绑定了哪些 ImsService 以及它们支持哪些功能。如果 IMS 应用程序更新了不支持任何功能的框架,则 ImsService 将解除绑定,直到手机重新启动或插入与 IMS 应用程序匹配的新 SIM 卡。

多个 ImsService 的绑定优先级

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

  1. 当插入 SIM 卡时,由 CarrierConfig 值config_ims_[mmtel/rcs]_package_override_string定义的 ImsService 包名称。
  2. config_ims_[mmtel/rcs]_package的设备覆盖值中定义的 ImsService 包名称,包括未插入 SIM 卡的情况。此 ImsService 必须支持紧急 MmTel 功能。

您必须在将使用该套餐的每个运营商的 CarrierConfig 中定义 ImsService 的套餐名称,或者如果您的 ImsService 将是默认值(如上所述),则必须在设备覆盖层中定义该名称。

让我们针对每个功能进行分解。对于加载单 SIM 卡的设备(单或多 SIM 卡),可以使用两种 IMS 功能:MMTel 和 RCS。框架将尝试按照上面定义的顺序绑定每个功能,如果该功能不可用于运营商配置覆盖中定义的 ImsService,则框架将回退到默认的 ImsService。例如,下表描述了框架将使用哪些 IMS 功能,假设系统上安装了三个实现 ImsServices 的 IMS 应用程序,且具有以下功能:

  • 运营商 A ImsService 支持 RCS
  • 运营商 B ImsService 支持 RCS 和 MMTel
  • OEM ImsService 支持 RCS 和 MMTel
SIM 卡已插入RCS特性MM电话功能
运营商A运营商A代加工
运营商B运营商B运营商B
无 SIM 卡代加工代加工

验证

由于 IMS 规范非常庞大并且使用特殊的验证设备,因此不包括用于验证 IMS 实施本身的工具。测试只能验证电话框架是否正确响应 ImsService API。

开发 IMS 应用程序

在开发与 Android 电话堆栈接口的 IMS 应用程序时,我们建议指定该应用程序可以侦听或修改为特定运营商订阅附加的 ImsService 实例的状态。

要侦听或修改 MMTEL 和 RCS 功能的 ImsService 状态,请使用ImsManager类获取ImsMmTelManagerImsRcsManager或 IMS 特定的ProvisioningManager类的实例。然后,该应用程序可以侦听特定于 IMS 的服务和配置状态,例如:

  • 已启用且可用的 MMTEL 或 RCS 功能
  • 当 IMS 注册状态更改时更新
  • IMS功能开通状态
  • 用户已启用的 IMS 功能

使用 ImsStateCallback

尽管 ImsService 是持久绑定的服务,但当新的 SIM 卡或嵌入式订阅变为活动状态或运营商配置更改时,绑定的服务可能会发生更改。由于 ImsService 不是电话流程的一部分,因此,如果 ImsService 由于订阅或配置更改而无形地崩溃或解除绑定,则应用程序在尝试访问 IMS API 时可能会遇到意外异常。

在运行 Android 13 或更高版本的设备上,要监视关联订阅的 ImsService 实例是否可用,应用可以使用ImsStateCallback类。获取ImsMmTelManagerImsRcsManager的实例时,我们建议应用程序首先使用ImsMmTelManager#registerImsStateCallbackImsRcsManager#registerImsStateCallback注册 IMS 状态回调。要在 ImsService 再次可用时继续接收特定订阅的回调更新,应用程序必须取消注册或丢弃通过ImsMmTelManagerImsRcsManagerProvisioningManager注册的现有回调;并注册新的回调。

如果存在不支持 IMS 的订阅,框架将调用ImsStateCallback#onUnavailable ,原因为REASON_NO_IMS_SERVICE_CONFIGURED 。这意味着 ImsService 和 IMS 相关的 API 不可用于订阅。

万一电话进程崩溃,应用程序会收到ImsStateCallback#onError并且不再接收已注册ImsStateCallback实例的更新。要从此情况中恢复,请通过调用ImsMmTelManager#registerImsStateCallbackImsRcsManager#registerImsStateCallback重新注册关联订阅的ImsStateCallback实例。