Android 5.1 引入了一种机制,即如果 API 与通用集成电路卡 (UICC) 应用的所有者相关,则可以向 API 授予特殊权限。Android 平台会加载存储在 UICC 上的证书,并向由这些证书签名的应用授予权限,允许其调用一些特殊的 API。
Android 7.0 对此功能进行了扩展,以支持从其他存储源读取 UICC 运营商权限规则,从而大幅增加可以使用这类 API 的运营商数量。如需查看 API 参考文档,请参阅 CarrierConfigManager;如需查看相关说明,请参阅运营商配置。
运营商拥有对 UICC 的完全控制权,因此,此机制不仅提供了一种安全而灵活的方式来管理移动网络运营商 (MNO) 在通用应用分发渠道(如 Google Play)上托管的应用,同时运营商还保留对设备的特殊权限,无需使用针对单个设备的平台证书对应用进行签名,也无需作为系统应用进行预安装。
UICC 规则
UICC 上的存储空间遵循 GlobalPlatform 安全元件访问控制规范。卡上的应用标识符 (AID) 为 A00000015141434C00
,并使用标准 GET DATA
命令来获取存储在卡上的规则。您可以通过卡无线下载 (OTA) 更新来更新这些规则。
数据层次结构
UICC 规则使用以下数据层次结构(括号中由字母和数字组成的二个字符组合是对象标记)。每个规则均为 REF-AR-DO
(E2
),并包含 REF-DO
与 AR-DO
的串联。
REF-DO
(E1
) 包含一个DeviceAppID-REF-DO
或DeviceAppID-REF-DO
与PKG-REF-DO
的串联。DeviceAppID-REF-DO
(C1
) 存储 SHA-1(20 字节)或 SHA-256(32 字节)证书签名。PKG-REF-DO
(CA
) 是在清单中定义的完整文件包名称字符串,为 ASCII 编码,最大长度是 127 字节。
AR-DO
(E3
) 已扩展为包含PERM-AR-DO
(DB
),后者是一个 8 字节的位掩码,表示 64 个独立的权限。
如果 PKG-REF-DO
不存在,则由相关证书签名的任何应用均获得访问权限;否则,证书和文件包名称需相匹配。
规则示例
应用名称为 com.google.android.apps.myapp
,并且 SHA-1 证书的十六进制字符串形式为:
AB:CD:92:CB:B1:56:B2:80:FA:4E:14:29:A6:EC:EE:B6:E5:C1:BF:E4
UICC 上规则的十六进制字符串形式为:
E243 <= 43 is value length in hex E135 C114 ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4 CA1D 636F6D2E676F6F676C652E616E64726F69642E617070732E6D79617070 E30A DB08 0000000000000001
访问规则文件支持
Android 7.0 增加了对从访问规则文件 (ARF) 中读取运营商授权规则的支持。
Android 平台会首先尝试选择访问规则应用 (ARA) AID A00000015141434C00
。如果在 UICC 上找不到 AID,Android 会通过选择 PKCS15 AID A000000063504B43532D3135
回退到 ARF。然后,Android 会读取 0x4300
处的访问控制规则文件 (ACRF),并查找 AID 为 FFFFFFFFFFFF
的条目。具有不同 AID 的条目将被忽略,从而确保其他用例的规则可以同时存在。
十六进制字符串形式的 ACRF 内容示例:
30 10 A0 08 04 06 FF FF FF FF FF FF 30 04 04 02 43 10
访问控制条件文件 (ACCF) 内容示例:
30 16 04 14 61 ED 37 7E 85 D3 86 A8 DF EE 6B 86 4B D8 5B 0B FA A5 AF 81
在上面的示例中,0x4310
是 ACCF 的地址,该地址包含证书哈希值 61:ED:37:7E:85:D3:86:A8:DF:EE:6B:86:4B:D8:5B:0B:FA:A5:AF:81
。由此证书签名的应用获得了运营商权限。
已启用的 API
Android 支持以下 API。
TelephonyManager
- 用于允许运营商应用向 UICC 请求质询/响应的方法:
getIccAuthentication
。 - 用于检查发起调用的应用是否已获得运营商权限的方法:
hasCarrierPrivileges
。 - 用于覆盖品牌和号码的方法:
- 用于进行直接 UICC 通信的方法:
- 用于将设备模式设置为全局的方法:
setPreferredNetworkTypeToGlobal
。 - 用于获取设备或网络身份的方法:
- 国际移动设备识别码 (IMEI):
getImei
- 移动设备标识符 (MEID):
getMeid
- 网络访问标识符 (NAI):
getNai
- SIM卡序列号:
getSimSerialNumber
- 国际移动设备识别码 (IMEI):
- 用于获取运营商配置的方法:
getCarrierConfig
- 用于获取数据传输的网络类型的方法:
getDataNetworkType
- 用于获取语音服务的网络类型的方法:
getVoiceNetworkType
- 用于获取 UICC SIM (USIM) 应用相关信息的方法:
- SIM 卡序列号:
getSimSerialNumber
- 卡信息:
getUiccCardsInfo
- GID1(组 ID 级别 1):
getGroupIdLevel1
- 第 1 行的电话号码字符串:
getLine1Number
- 禁止使用的公共陆地移动网络 (PLMN):
getForbiddenPlmns
- 等效本地 PLMN:
getEquivalentHomePlmns
- SIM 卡序列号:
- 用于获取或设置语音信箱号码的方法:
- 用于发送特殊拨号器代码的方法:
sendDialerSpecialCode
- 用于重置无线装置调制解调器的方法:
rebootModem
- 用于获取或设置网络选择模式的方法:
- 用于请求网络扫描的方法:
requestNetworkScan
- 用于获取或设置允许的/首选网络类型的方法:
- 用于检查是否按用户设置启用移动流量或漫游的方法:
- 用于检查或设置数据连接及原因的方法:
- 用于获取紧急电话号码列表的方法:
getEmergencyNumberList
- 用于控制机会网络的方法:
- 用于设置或清除移动网络信号强度更新请求的方法:
TelephonyCallback
TelephonyCallback
包含的接口具有一个回调方法,用于在注册状态发生变化时通知发起调用的应用:
- 消息等待指示已更改:
onMessageWaitingIndicatorChanged
- 来电转接指示已更改:
onCallForwardingIndicatorChanged
- IP 多媒体系统 (IMS) 通话中断原因已更改:
onImsCallDisconnectCauseChanged
- 确切的数据连接状态已更改:
onPreciseDataConnectionStateChanged
- 当前的紧急电话号码列表已更改:
onEmergencyNumberListChanged
- 活跃数据订阅 ID 已更改:
onActiveDataSubscriptionIdChanged
- 运营商网络已更改:
onCarrierNetworkChange
- 网络注册或位置/路由/跟踪区域更新失败:
onRegistrationFailed
- 限制信息已更改:
onBarringInfoChanged
- 当前物理通道配置已更改:
onPhysicalChannelConfigChanged
SubscriptionManager
- 用于获取各种订阅信息的方法:
- 用于获取有效订阅数量的方法:
getActiveSubscriptionInfoCount
- 用于管理订阅组的方法:
- 用于获取或设置运营商与特定订阅者之间的结算关系方案说明的方法:
- 用于暂时覆盖运营商和特定订阅者之间的结算关系方案(这样才能将其视为不按流量计费)的方法:
setSubscriptionOverrideUnmetered
- 用于暂时覆盖运营商和特定订阅者之间的结算关系方案(这样才能将其视为拥挤)的方法:
setSubscriptionOverrideCongested
- 用于检查具有给定上下文的应用是否有权根据指定订阅的元数据管理该订阅的方法:
canManageSubscription
SmsManager
- 用于允许调用方创建新的传入短信的方法:
injectSmsPdu
。 - 用于在不写入短信提供程序的情况下发送短信的方法:
sendTextMessageWithoutPersisting
CarrierConfigManager
- 用于通知配置已更改的方法:
notifyConfigChangedForSubId
。 - 用于获取默认订阅的运营商配置的方法:
getConfig
- 用于获取指定订阅的运营商配置的方法:
getConfigForSubId
有关说明,请参阅运营商配置。
BugreportManager
用于启动连接 bug 报告的方法,该报告是仅包含用于调试连接相关问题的信息的 bug 报告的专用版本:startConnectivityBugreport
NetworkStatsManager
- 用于查询网络使用情况摘要的方法:
querySummary
- 用于查询网络使用情况历史记录的方法:
queryDetails
- 用于注册或取消注册网络使用情况回调的方法:
ImsMmTelManager
- 用于注册或取消注册 IMS MmTel 注册回调的方法:
ImsRcsManager
- 用于注册或取消注册 IMS RCS 注册回调的方法:
- 用于获取 IMS 注册状态或传输类型的方法:
ProvisioningManager
- 用于注册和取消注册 IMS 功能配置更新回调的方法:
- 与 IMS MmTel 或 RCS 功能的配置状态相关的方法:
EuiccManager
用于切换到(启用)指定订阅的方法:switchToSubscription
CarrierMessagingService
此服务的用途是在用户发送或接收新的短信和彩信时接收来自系统的调用。如需扩展此类,请在您的清单文件中声明该服务具有 android.Manifest.permission#BIND_CARRIER_MESSAGING_SERVICE
权限,并包含一个具有 #SERVICE_INTERFACE
操作的 intent 过滤器。方法包括:
- 用于过滤入站短信的方法:
onFilterSms
- 用于拦截从设备发送的短信的方法:
onSendTextSms
- 用于拦截从设备发送的二进制短信的方法:
onSendDataSms
- 用于拦截从设备发送的长短信的方法:
onSendMultipartTextSms
- 用于拦截从设备发送的彩信的方法:
onSendMms
- 用于下载收到的彩信的方法:
onDownloadMms
CarrierService
该服务向系统公开运营商专属功能。如需扩展此类,请在应用清单文件中声明该服务具有 android.Manifest.permission#BIND_CARRIER_SERVICES
权限,并包含一个具有 CARRIER_SERVICE_INTERFACE
操作的 intent 过滤器。如果该服务具有长期绑定,请在该服务的元数据中将 android.service.carrier.LONG_LIVED_BINDING
设置为 true
。
平台使用特殊标志绑定 CarrierService
,以允许运营商服务进程在特殊的应用待机存储分区中运行。这样可以免除运营商服务应用受到应用空闲限制的影响,并且更有可能在设备内存不足时保持活动状态。不过,如果运营商服务应用因任何原因而崩溃,它会在应用重启并重新建立绑定之前丧失上述所有权限。因此,确保运营商服务应用保持稳定至关重要。
CarrierService
中的方法包括:
- 如需覆盖和设置运营商专属配置,请使用以下方法:
onLoadConfig
- 如需告知系统运营商应用即将有意更改运营商网络,请使用以下方法:
notifyCarrierNetworkChange
TelephonyProvider
这是允许对电话数据库进行修改(插入、删除、更新和查询)的内容提供程序 API。值字段在 Telephony.Carriers
中定义;如需了解详情,请参阅 Telephony
类参考文档
WifiNetworkSuggestion
构建 WifiNetworkSuggestion
对象时,请使用以下方法来设置订阅 ID 或订阅组:
- 用于设置订阅 ID 的方法:
setSubscriptionId
- 用于设置订阅组的方法:
setSubscriptionGroup
Android 平台
Android 平台会在检测到的 UICC 上构建内部 UICC 对象,此类对象会将运营商权限规则作为 UICC 的一部分包含在内。UiccCarrierPrivilegeRules.java
会加载规则、在 UICC 卡上对规则进行解析,并将它们缓存在内存中。如果需要进行权限检查,UiccCarrierPrivilegeRules
会将调用方证书与其自身的规则逐一对比。如果 UICC 被移除,规则会连同 UICC 对象一起被销毁。
验证
如需使用 CtsCarrierApiTestCases.apk
通过兼容性测试套件 (CTS) 验证实现,您必须先获得一个开发者 UICC,且该 UICC 应具备正确的 UICC 规则或 ARF 支持。您可以要求您选择的 SIM 卡供应商为您准备一个开发者 UICC,且该 UICC 具有如本节所述的正确 ARF,然后使用该 UICC 运行测试。UICC 不需要有效移动网络服务来通过 CTS 测试。
准备 UICC
对于 Android 11 及更低版本,CtsCarrierApiTestCases.apk
由 aosp-testkey
签名,哈希值为 61:ED:37:7E:85:D3:86:A8:DF:EE:6B:86:4B:D8:5B:0B:FA:A5:AF:81
。
从 Android 12 开始,CtsCarrierApiTestCases.apk
由 cts-uicc-2021-testkey
哈希值 CE:7B:2B:47:AE:2B:75:52:C8:F9:2C:C2:91:24:27:98:83:04:1F:B6:23:A5:F1:94:A8:2C:9B:F1:5D:49:2A:A0
签名。
如需在 Android 12 中运行 CTS 运营商 API 测试,设备需要使用具备 CTS 运营商权限的 SIM 卡,该 SIM 卡满足最新版第三方 GSMA TS.48 测试配置文件规范中规定的要求。
同一 SIM 卡也可以用于 Android 12 之前的版本。
修改 CTS SIM 卡配置文件
- 添加:访问规则应用主数据 (ARA-M) 或 ARF 中的 CTS 运营商权限。这两个签名都必须根据运营商权限规则进行编码:
- Hash1(SHA1):
61:ED:37:7E:85:D3:86:A8:DF:EE:6B:86:4B:D8:5B:0B:FA:A5:AF:81
- Hash2(SHA256):
CE:7B:2B:47:AE:2B:75:52:C8:F9:2C:C2:91:24:27:98:83:04:1F:B6:23:A5:F1:94:A8:2C:9B:F1:5D:49:2A:A0
- Hash1(SHA1):
- 创建:TS.48 中不存在且 CTS 需要的 ADF USIM 基本文件 (EF):
- EF_MBDN (6FC7),记录大小:28,记录编号:4
- 内容
- Rec1: 566F696365204D61696CFFFFFFFF06915155555555FF…FF
- Rec2-n: FF…FF
- 内容
- EF_EXT6 (6FC8),记录大小:13,记录编号:1
- 内容:00FF…FF
- EF_MBI (6FC9),记录大小:4,记录编号:1
- 内容:Rec1: 01010101
- EF_MWIS (6FCA),记录大小:5,记录编号:1
- 内容:0000000000
- 内容:00FF…FF
- EF_MBDN (6FC7),记录大小:28,记录编号:4
- 修改:USIM 服务表:启用服务 n°47、n°48
- EF_UST (6F38)
- 内容:
9EFFBF1DFFFE0083410310010400406E01
- 内容:
- EF_UST (6F38)
- 修改:DF-5GS 和 DF-SAIP 文件
- DF-5GS - EF_5GS3GPPLOCI (USIM/5FC0/4F01)
- 内容:
FFFFFFFFFFFFFFFFFFFFFFFFFF42F618FFFFFE01
- 内容:
- DF-5GS - EF_5GSN3GPPLOCI (USIM/5FC0/4F02)
- 内容:
FFFFFFFFFFFFFFFFFFFFFFFFFF42F618FFFFFE01
- 内容:
- DF-5GS - EF SUCI_Calc_Info (USIM/5FC0/4F07)
- 内容:
A0020000FF…FF
- 内容:
- DF-SAIP - EF SUCI_Calc_Info_USIM (USIM/5FD0/4F01)
- 内容:
A0020000FF…FF
- 内容:
- DF-5GS - EF_5GS3GPPLOCI (USIM/5FC0/4F01)
- 修改:在包含此标识的各个 EF 中使用运营商名称字符串 Android CTS:
- EF_SPN (USIM/6F46)
- 内容:
01416E64726F696420435453FF..FF
- 内容:
- EF_PNN (USIM/6FC5)
- 内容:
Rec1 430B83413759FE4E934143EA14FF..FF
- 内容:
- EF_SPN (USIM/6F46)
匹配测试配置文件结构
下载并匹配以下通用测试配置文件结构的最新版本。这些配置文件不会包含个性化的 CTS 运营商权限规则或上面列出的其他修改。
运行测试
为方便起见,CTS 支持使用设备令牌,仅允许在配置了相同令牌的设备上运行测试。运营商 API CTS 测试支持使用设备令牌 sim-card-with-certs
。例如,下面的设备令牌仅允许在 abcd1234
设备上运行运营商 API 测试:
cts-tradefed run cts --device-token abcd1234:sim-card-with-certs
如果在不使用设备令牌的情况下运行测试,则测试将在所有设备上运行。
常见问题解答
如何在 UICC 上更新证书?
答:使用现有的卡 OTA 更新机制。
UICC 是否可以与其他规则共存?
答:在 UICC 上可以出现具有相同 AID 的其他安全规则;Android 平台会自动过滤掉这些规则。
对于依赖 UICC 上的证书的应用,移除 UICC 会发生什么情况?
答:该应用会失去其权限,因为与 UICC 关联的规则会随 UICC 的移除而被销毁。
UICC 上的证书数量是否有限制?
答:Android 平台不限制证书数量,但是由于检查过程是线性的,因此规则太多可能会造成检查延迟。
我们通过该方法可以支持的 API 数量是否有限制?
答:没有限制,但我们规定 API 必须与运营商相关。
有些 API 是否被禁止使用此方法?如果是,你们是如何执行禁用规则的?(也就是说,是否有测试可以验证哪些 API 适用此方法?)
答:请参阅 Android 兼容性定义文档 (CDD) 的 API 行为兼容性部分。我们进行了一些 CTS 测试,以确保 API 的权限模型不会更改。
UICC 如何使用多 SIM 卡功能?
答:它会使用用户设置的默认 SIM 卡。
UICC 是否会与其他 SE 访问技术(例如 SEEK)交互或重叠?
答:举例来说,SEEK 使用 UICC 上的同一 AID。因此,规则可以共存,并由 SEEK 或 UiccCarrierPrivileges
进行过滤。
何时适合检查运营商权限?
答:在 SIM 卡状态加载广播后。
OEM 能否禁用部分运营商 API?
答:不能。我们认为目前的 API 集合已是最小的集合,未来,我们计划使用位掩码来实现更精细的粒度控制。
setOperatorBrandOverride
是否会覆盖所有其他形式的运营商名称字符串?例如 SE13、UICC SPN 或基于网络的 NITZ?
是,运营商品牌覆盖的优先级最高。如果进行了设置,它会覆盖所有其他形式的运营商名称字符串。
injectSmsPdu
方法调用的作用是什么?
答:此方法调用有助于将短信备份到云端或从云端恢复短信。injectSmsPdu
调用会启用恢复功能。
对于短信过滤,onFilterSms
调用是否基于短信 UDH 端口过滤?或者,运营商应用是否有权访问所有的传入短信?
答:运营商有权访问所有短信数据。
DeviceAppID-REF-DO
经扩展可支持 32 字节,这似乎不符合当前的 GP 规范(仅允许 0 或 20 字节),你们为什么要做出这一更改?SHA-1 是否不足以避免冲突?你们是否已向 GP 提出此更改建议,因为此规则可能无法向后兼容现有的 ARA-M/ARF?
答:为了提供能够满足未来需求的安全性,除了 SHA-1 之外,此项扩展还针对 DeviceAppID-REF-DO
引入 SHA-256,而目前 SHA-1 是 GP SEAC 标准中的唯一选项。我们强烈建议使用 SHA-256。
如果 DeviceAppID
为 0(空),你们是否会将该规则应用于特定规则未涵盖的所有设备应用?
答:运营商 API 要求填充 DeviceAppID-REF-DO
。为空仅供满足测试用途,因此我们不建议在操作部署时留空。
根据你们的技术规范,在没有 DeviceAppID-REF-DO
的情况下,不得单独使用 PKG-REF-DO
。但是在该规范的表 6-4 中,你们仍然扩展了 REF-DO
的定义。你们是否有意这样描述?如果在 REF-DO
中仅使用 PKG-REF-DO
,代码会出现什么样的行为?
答:在最新版本中,我们移除了在 REF-DO
中将 PKG-REF-DO
作为单个值项的选项。PKG-REF-DO
只能与 DeviceAppID-REF-DO
结合使用。
假设我们可以授予所有基于运营商的权限,或者可以进行更精细的控制。那么可以用什么来定义位掩码和实际权限之间的映射?每个类一个权限?每种方法一个权限?从长远来看,64 个独立权限是否足够?
答:这是留作将来使用的。此外,欢迎向我们提出建议。
你们能否进一步具体地定义 DeviceAppID
(Android 版)?这是发布者证书的 SHA-1(20 字节)哈希值,而发布者证书是用来为给定应用签名的,因此该名称是否应该反映其用途?(该名称可能会让许多读者感到困惑,因为该规则适用于使用这一发布者证书签名的所有应用。)
答:存储证书的 DeviceAppID
已获得现有规范的支持。我们会尽量减少对规范的更改,以降低采用规范存在的障碍。如需了解详情,请参阅 UICC 规则。