Android 9 引入了一个名为 ImsService 的 SystemApi 接口,以帮助您实施 IP 多媒体子系统 (IMS)。ImsService API 是 Android 平台与供应商或运营商提供的 IMS 实现之间的明确定义的接口。
图 1. ImsService 概览
通过使用 ImsService 接口,IMS 实现者可以向平台提供重要的信令信息,例如 IMS 注册信息、IMS 集成短信以及 MmTel 功能集成(以提供语音和视频通话)。ImsService API 也是 Android System 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
intent-filter action,而不是android.telephony.ims.ImsService
action。
框架随后将使用 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
权限的进程才能绑定到该应用。这可以防止恶意应用绑定到该服务,因为只有系统应用才能被框架授予该权限。
该服务还必须指定包含 action android.telephony.ims.ImsService
的 intent-filter
元素。这允许框架找到 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 PDN 紧急连接之外的所有 IMS 媒体(IR.92 和 IR.94 规范)的支持。任何希望支持 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 的初始化和绑定的更多信息,请参见下图。
图 2. ImsService 初始化和绑定
框架检测和验证 ImsService 实现
在 AndroidManifest.xml 中正确定义 ImsService 后,必须配置平台以在适当的时候(安全地)绑定到 ImsService。框架绑定到两种类型的 ImsService
- 运营商“覆盖”ImsService:这些 ImsService 预加载到设备上,但附加到一个或多个蜂窝运营商,并且仅在插入匹配的 SIM 卡时才会被绑定。这是使用
config_ims_mmtel_package_override_string
CarrierConfig 密钥来配置实现 MMTEL 功能的 ImsService。config_ims_rcs_package_override_string
用于配置实现 RCS 功能的 ImsService。
- 设备“默认”ImsService:这是 OEM 加载到设备上的默认 ImsService,应设计为在运营商 ImsService 不可用时在所有情况下提供 IMS 服务,并且在设备未插入 SIM 卡或插入的 SIM 卡未安装运营商 ImsService 的情况下非常有用。这在设备叠加层中使用以下配置定义
config_ims_mmtel_package
:实现 MMTEL 功能config_ims_rcs_package
:实现 RCS 功能
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),按每个功能的以下顺序绑定
- 当插入 SIM 卡时,由 CarrierConfig 值
config_ims_[mmtel/rcs]_package_override_string
定义的 ImsService 软件包名称。 - 设备叠加层值中为
config_ims_[mmtel/rcs]_package
定义的 ImsService 软件包名称,包括未插入 SIM 卡的情况。此 ImsService 必须支持紧急 MmTel 功能。
您必须将 ImsService 的软件包名称定义在每个将使用该软件包的运营商的 CarrierConfig 中,或者如果您的 ImsService 将是默认的,则定义在设备叠加层中,如上所述。
让我们为每个功能分解一下。对于具有单张 SIM 卡的设备(单 SIM 卡或多 SIM 卡),有两种可能的 IMS 功能:MMTel 和 RCS。框架将尝试按上述定义的顺序为每个功能进行绑定,如果 Carrier Configuration 覆盖中定义的 ImsService 不提供该功能,框架将回退到您的默认 ImsService。因此,例如,下表描述了在具有以下功能的三款安装了实现 ImsService 的 IMS 应用的系统上,框架将使用哪些 IMS 功能
- 运营商 A ImsService 支持 RCS
- 运营商 B ImsService 支持 RCS 和 MMTel
- OEM ImsService 支持 RCS 和 MMTel
插入的 SIM 卡 | RCS 功能 | MMTel 功能 |
---|---|---|
运营商 A | 运营商 A | OEM |
运营商 B | 运营商 B | 运营商 B |
无 SIM 卡 | OEM | OEM |
验证
由于 IMS 规范非常庞大并且使用特殊的验证设备,因此未包含用于验证 IMS 实现本身的工具。这些测试只能验证电话框架是否正确响应 ImsService API。
开发 IMS 应用
在开发与 Android 电话堆栈接口的 IMS 应用时,我们建议指定该应用可以侦听或修改为特定运营商订阅附加的 ImsService 实例的状态。
要侦听或修改 MMTEL 和 RCS 功能的 ImsService 状态,请使用 ImsManager
类来获取 ImsMmTelManager
、ImsRcsManager
或 IMS 特定的 ProvisioningManager
类的实例。然后,应用可以侦听 IMS 特定的服务和配置状态,例如
- 已启用且可用的 MMTEL 或 RCS 功能
- IMS 注册状态更改时的更新
- IMS 功能的配置状态
- 用户已启用的 IMS 功能
使用 ImsStateCallback
虽然 ImsService 是一种持久绑定的服务,但当新的 SIM 卡或嵌入式订阅变为活动状态或运营商配置更改时,绑定的服务可能会更改。由于 ImsService 不是电话进程的一部分,因此如果 ImsService 无形崩溃或由于订阅或配置更改而解除绑定,则应用在尝试访问 IMS API 时可能会遇到意外异常。
在运行 Android 13 或更高版本的设备上,要监视关联订阅的 ImsService 实例是否可用或不可用,应用可以使用 ImsStateCallback
类。在获取 ImsMmTelManager
或 ImsRcsManager
的实例时,我们建议应用首先使用 ImsMmTelManager#registerImsStateCallback
或 ImsRcsManager#registerImsStateCallback
注册 IMS 状态回调。要继续接收有关特定订阅的回调更新(当 ImsService 再次可用时),应用必须取消注册或放弃通过 ImsMmTelManager
、ImsRcsManager
或 ProvisioningManager
注册的现有回调;并注册新的回调。
如果某个订阅不支持 IMS,则框架会使用原因 REASON_NO_IMS_SERVICE_CONFIGURED
调用 ImsStateCallback#onUnavailable
。这意味着 ImsService 和 IMS 相关 API 不适用于该订阅。
在不太可能发生的电话进程崩溃事件中,应用会收到 ImsStateCallback#onError
,并且不再收到有关已注册 ImsStateCallback
实例的更新。要从此情况中恢复,请通过调用 ImsMmTelManager#registerImsStateCallback
或 ImsRcsManager#registerImsStateCallback
为关联的订阅重新注册 ImsStateCallback
实例。