许多支持 NFC 功能的 Android 设备已支持 NFC 卡模拟。在大多数情况下,卡模拟由设备中的一个独立芯片(称为安全单元)完成。许多无线运营商提供的 SIM 卡也包含安全单元。
Android 4.4 及更高版本提供了一种不涉及安全单元的额外卡模拟方法,称为基于主机的卡模拟。这允许任何 Android 应用模拟卡并直接与 NFC 读卡器通信。本主题介绍基于主机的卡模拟 (HCE) 在 Android 上的工作原理,以及如何使用此技术开发模拟 NFC 卡的应用。
使用安全单元进行卡模拟
当使用安全单元提供 NFC 卡模拟时,要模拟的卡通过 Android 应用配置到设备上的安全单元中。然后,当用户将设备靠近 NFC 终端时,设备中的 NFC 控制器会将来自读卡器的所有数据直接路由到安全单元。图 1 说明了此概念
图 1. 使用安全单元的 NFC 卡模拟。
安全单元本身执行与 NFC 终端的通信,Android 应用不参与此交易。交易完成后,Android 应用可以直接向安全单元查询交易状态并通知用户。
基于主机的卡模拟
当使用基于主机的卡模拟来模拟 NFC 卡时,数据会直接路由到主机 CPU,而不是路由到安全单元。图 2 说明了基于主机的卡模拟的工作原理
图 2. 不使用安全单元的 NFC 卡模拟。
支持的 NFC 卡和协议
图 3. Android 的 HCE 协议栈。
NFC 标准支持许多不同的协议,并且您可以模拟不同类型的卡。
Android 4.4 及更高版本支持当今市场上常见的几种协议。许多现有的非接触式卡(例如非接触式支付卡)已基于这些协议。当今市场上的许多 NFC 读卡器也支持这些协议,包括充当读卡器本身的 Android NFC 设备(请参阅 IsoDep
类)。这使您可以使用仅支持 Android 的设备构建和部署围绕 HCE 的端到端 NFC 解决方案。
具体来说,Android 4.4 及更高版本支持模拟基于 NFC Forum ISO-DEP 规范(基于 ISO/IEC 14443-4)并按照 ISO/IEC 7816-4 规范处理应用协议数据单元 (APDU) 的卡。Android 要求仅在 Nfc-A (ISO/IEC 14443-3 Type A) 技术之上模拟 ISO-DEP。对 Nfc-B (ISO/IEC 14443-4 Type B) 技术的支持是可选的。图 3 说明了所有这些规范的分层。
HCE 服务
Android 中的 HCE 架构围绕 Android Service
组件构建(称为HCE 服务)。服务的一个主要优势是它可以在后台运行而无需任何用户界面。这非常适合许多 HCE 应用,例如会员卡或交通卡,用户无需启动应用即可使用。相反,将设备轻触 NFC 读卡器会在服务尚未运行时启动正确的服务,并在后台执行交易。当然,您可以在适当的时候从您的服务启动额外的 UI(例如用户通知)。
服务选择
当用户将设备轻触 NFC 读卡器时,Android 系统需要知道 NFC 读卡器想要与哪个 HCE 服务通信。ISO/IEC 7816-4 规范定义了一种以应用 ID (AID) 为中心的选择应用的方式。一个 AID 由最多 16 个字节组成。如果您正在为现有的 NFC 读卡器基础设施模拟卡,这些读卡器寻找的 AID 通常是众所周知且公开注册的(例如,Visa 和 MasterCard 等支付网络的 AID)。
如果您想为自己的应用部署新的读卡器基础设施,则必须注册您自己的 AID。AID 的注册过程在 ISO/IEC 7816-5 规范中定义。如果您正在为 Android 部署 HCE 应用,我们建议按照 7816-5 进行 AID 注册,因为这可以避免与其他应用发生冲突。
AID 组
在某些情况下,为了实现特定应用,HCE 服务可能需要注册多个 AID 并将其设置为所有这些 AID 的默认处理程序。不支持组中的某些 AID 转到另一个服务。
一组保持在一起的 AID 列表称为一个 AID 组。对于一个 AID 组中的所有 AID,Android 保证以下任一情况发生
- 组中的所有 AID 都被路由到此 HCE 服务。
- 组中的 AID 都没有被路由到此 HCE 服务(例如,因为用户偏好另一个服务,而该服务也请求了您组中的一个或多个 AID)。
换句话说,不存在中间状态,即组中的某些 AID 可以路由到一个 HCE 服务,而另一些 AID 可以路由到另一个服务。
AID 组和类别
您可以将每个 AID 组与一个类别关联起来。这使得 Android 可以按类别对 HCE 服务进行分组,进而允许用户在类别级别而不是 AID 级别设置默认值。避免在应用面向用户的任何部分提及 AID,因为它们对普通用户没有任何意义。
Android 4.4 及更高版本支持两个类别
CATEGORY_PAYMENT
(涵盖行业标准支付应用)CATEGORY_OTHER
(适用于所有其他 HCE 应用)
在 CATEGORY_PAYMENT
下注册 AID 的应用只有在以下情况下才能处理交易
- 用户将该应用设置为默认支付应用(在 Android 15+ 设备上持有钱包角色),或者
- 应用处于前台并调用了
setPreferredService
。
实现 HCE 服务
要使用基于主机的卡模拟来模拟 NFC 卡,您需要创建一个处理 NFC 交易的 Service
组件。
检查 HCE 支持
您的应用可以通过检查 FEATURE_NFC_HOST_CARD_EMULATION
功能来检查设备是否支持 HCE。在您应用的清单中使用 <uses-feature>
标签声明您的应用使用了 HCE 功能,并说明该功能对于应用是否必需。
服务实现
Android 4.4 及更高版本提供了一个便利的 Service
类,您可以将其用作实现 HCE 服务的基础:即 HostApduService
类。
第一步是扩展 HostApduService
,如以下代码示例所示
Kotlin
class MyHostApduService : HostApduService() { override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray { ... } override fun onDeactivated(reason: Int) { ... } }
Java
public class MyHostApduService extends HostApduService { @Override public byte[] processCommandApdu(byte[] apdu, Bundle extras) { ... } @Override public void onDeactivated(int reason) { ... } }
HostApduService
声明了两个必须覆盖并实现的抽象方法。其中之一,processCommandApdu()
,每当 NFC 读卡器向您的服务发送一个应用协议数据单元 (APDU) 时就会被调用。APDU 在 ISO/IEC 7816-4 规范中定义。APDU 是 NFC 读卡器和您的 HCE 服务之间交换的应用级数据包。该应用级协议是半双工的:NFC 读卡器向您发送一个命令 APDU,然后等待您返回一个响应 APDU。"
如前所述,Android 使用 AID 来确定读卡器想要与哪个 HCE 服务通信。通常,NFC 读卡器发送给您设备的第一个 APDU 是 SELECT AID
APDU;此 APDU 包含读卡器想要通信的 AID。Android 从该 APDU 中提取 AID,将其解析到 HCE 服务,然后将该 APDU 转发到已解析的服务。
您可以通过从 processCommandApdu()
返回响应 APDU 的字节来发送响应 APDU。请注意,此方法在应用的主线程上调用,您不应阻塞它。如果您无法立即计算并返回响应 APDU,请返回 null。然后,您可以在另一个线程上完成必要的工作,并使用 HostApduService
类中定义的 sendResponseApdu()
方法在完成后发送响应。
Android 会持续将来自读卡器的新 APDU 转发到您的服务,直到发生以下任一情况
- NFC 读卡器发送另一个
SELECT AID
APDU,操作系统将其解析到不同的服务。 - NFC 读卡器与您的设备之间的 NFC 链接断开。
在这两种情况下,都会调用您类的 onDeactivated()
实现,并带有一个参数,指示发生了哪种情况。
如果您正在使用现有的读卡器基础设施,则必须在您的 HCE 服务中实现读卡器期望的现有应用级协议。
如果您正在部署您也控制的新读卡器基础设施,则可以定义自己的协议和 APDU 序列。尝试限制 APDU 的数量和交换数据的大小:这可确保您的用户只需将设备在 NFC 读卡器上方短暂停留即可。合理的最大值约为 1 KB 的数据,通常可以在 300 ms 内交换完成。
服务清单声明和 AID 注册
您必须像往常一样在清单中声明您的服务,但还必须在服务声明中添加一些额外的内容
要告诉平台这是一个实现了
HostApduService
接口的 HCE 服务,请在您的服务声明中添加针对SERVICE_INTERFACE
操作的意图过滤器。要告诉平台此服务请求哪些 AID 组,请在服务声明中包含一个
SERVICE_META_DATA
<meta-data>
标签,指向一个包含有关 HCE 服务的附加信息的 XML 资源。将
android:exported
属性设置为true
,并在您的服务声明中要求android.permission.BIND_NFC_SERVICE
权限。前者确保该服务可以由外部应用绑定。后者则强制只有持有android.permission.BIND_NFC_SERVICE
权限的外部应用才能绑定到您的服务。由于android.permission.BIND_NFC_SERVICE
是系统权限,这实际上强制只有 Android OS 可以绑定到您的服务。
以下是一个 HostApduService
清单声明的示例
<service android:name=".MyHostApduService" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE"> <intent-filter> <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/> </intent-filter> <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/apduservice"/> </service>
此 meta-data 标签指向一个 apduservice.xml
文件。以下是此类文件的一个示例,其中包含一个 AID 组声明,该组包含两个专有 AID
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc" android:requireDeviceUnlock="false"> <aid-group android:description="@string/aiddescription" android:category="other"> <aid-filter android:name="F0010203040506"/> <aid-filter android:name="F0394148148100"/> </aid-group> </host-apdu-service>
<host-apdu-service>
标签必须包含一个 <android:description>
属性,该属性包含服务的用户友好描述,您可以在应用 UI 中显示该描述。您可以使用 requireDeviceUnlock
属性指定设备在您调用此服务处理 APDU 之前必须解锁。
<host-apdu-service>
必须包含一个或多个 <aid-group>
标签。每个 <aid-group>
标签都必须执行以下操作
- 包含一个
android:description
属性,其中包含 AID 组的用户友好描述,适合在 UI 中显示。 - 将其
android:category
属性设置为指示 AID 组所属的类别,例如由CATEGORY_PAYMENT
或CATEGORY_OTHER
定义的字符串常量。 - 包含一个或多个
<aid-filter>
标签,每个标签包含一个单独的 AID。以十六进制格式指定 AID,并确保它包含偶数个字符。
您的应用还需要持有 NFC
权限才能注册为 HCE 服务。
AID 冲突解决
一个设备上可以安装多个 HostApduService
组件,同一个 AID 可以由多个服务注册。Android 使用以下步骤确定调用哪个服务
- 如果用户选择的默认钱包应用注册了该 AID,则调用该应用。
- 如果默认钱包应用未注册该 AID,则调用注册了该 AID 的服务。
- 如果有多个服务注册了该 AID,则 Android 会询问用户要调用哪个服务。
前台服务偏好设置
处于前台的应用可以调用 setPreferredService
,以指定当特定 Activity 处于前台时应优先使用哪个卡模拟服务。此在前台应用偏好设置会覆盖 AID 冲突解决。当应用预期用户可能使用 NFC 卡模拟时,建议采用此做法。
Android 13 及更高版本
为了更好地适应“设置”UI 中的默认支付选择列表,请将横幅要求调整为方形图标。理想情况下,它应与应用启动器图标设计相同。此调整可带来更好的一致性和更简洁的外观。
Android 12 及更低版本
将服务横幅的大小设置为 260x96 dp,然后通过将 android:apduServiceBanner
属性添加到 <host-apdu-service>
标签(该属性指向可绘制资源)来在您的元数据 XML 文件中设置服务横幅的大小。以下是一个示例
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc" android:requireDeviceUnlock="false" android:apduServiceBanner="@drawable/my_banner"> <aid-group android:description="@string/aiddescription" android:category="payment"> <aid-filter android:name="F0010203040506"/> <aid-filter android:name="F0394148148100"/> </aid-group> </host-apdu-service>
钱包应用
Android 15 及更高版本包含一个默认钱包应用角色,用户可以通过导航到 设置 > 应用 > 默认应用 来选择该角色。这定义了在轻触支付终端时要调用的默认钱包应用。Android 将声明了包含支付类别的 AID 组的 HCE 服务视为钱包应用。
检查您的应用是否为默认钱包应用
应用可以通过将 RoleManager.ROLE_WALLET
传递给 RoleManager.isRoleHeld()
来检查它们是否是默认钱包应用。
如果您的应用不是默认应用,您可以通过将 RoleManager.ROLE_WALLET
传递给 RoleManager.createRequestRoleIntent()
来请求默认钱包角色。
钱包应用所需的资源
为了提供更具视觉吸引力的用户体验,HCE 钱包应用需要提供一个服务横幅。
观察模式
Android 15 引入了观察模式功能。启用后,观察模式允许设备观察 NFC 轮询循环并向相应的 HostApduService
组件发送关于它们的通知,以便它们可以准备与给定 NFC 终端进行交互。一个 HostApduService
可以通过向 setObserveModeEnabled()
传递 true
来将设备置于观察模式。这会指示 NFC 堆栈不允许 NFC 交易,而是被动观察轮询循环。
轮询循环过滤器
您可以使用以下任一方法为 HostApduService
注册轮询循环过滤器
- 对于必须精确匹配轮询帧的过滤器,使用
registerPollingLoopFilterForService()
。 - 对于匹配轮询帧正则表达式的过滤器,使用
registerPollingLoopPatternFilterForService()
。
当轮询循环过滤器匹配非标准轮询帧时,NFC 堆栈会通过调用相应的 HostApduService
的 processPollingFrames()
方法将这些轮询帧路由到该服务。这使得服务能够采取任何必要的步骤来确保用户准备好进行交易并打算进行交易——例如,对用户进行身份验证。如果 NFC 读卡器在其轮询循环中仅使用标准帧,NFC 堆栈会将这些轮询帧路由到优先的前台服务(如果该服务在前台),否则路由到默认钱包角色持有者。
轮询帧通知还包含供应商特定的场强测量值,您可以通过调用 getVendorSpecificGain()
来检索该值。供应商可以使用他们自己的比例提供测量值,只要该值适合单个字节。
响应轮询循环并退出观察模式
当服务准备好进行交易时,可以通过向 setObserveModeEnabled()
传递 false
来退出观察模式。NFC 堆栈随后将允许交易继续进行。
HostApduService
组件可以通过在清单中将 shouldDefaultToObserveMode
设置为 true
,或者通过调用 CardEmulation.setShouldDefaultToObserveModeForService()
来指示当它们是优先支付服务时应启用观察模式。
HostApduService
和 OffHostApduService
组件还可以通过在清单中的 PollingLoopFilter
声明中将 autoTransact
设置为 true
来指示,与接收到的轮询循环帧匹配的轮询循环过滤器应自动禁用观察模式并允许交易继续进行。
前台服务偏好设置
处于前台的应用可以调用 setPreferredService
,以指定当特定 Activity 处于前台时应优先使用哪个卡模拟服务。此在前台应用偏好设置会覆盖设备对应的给定服务的 shouldDefaultToObserveMode
值的观察模式状态,该值可以通过以下任一方式设置
- 在清单中为该服务设置
shouldDefaultToObserveMode
的状态。 - 使用相应的服务和状态调用
CardEmulation.setShouldDefaultToObserveModeForService()
。
息屏和锁屏行为
HCE 服务的行为因设备上运行的 Android 版本而异。
Android 15 及更高版本
如果默认钱包应用在支持它的设备上开启观察模式,则该应用会覆盖解锁和息屏行为,因为它控制着交易何时可以进行。如果观察模式未检测到可识别的轮询循环模式,某些钱包应用可能要求设备在交易继续之前先解锁。
建议开发者与其读卡器设备合作,以发出可识别的轮询循环模式,并从其应用中注册以处理这些模式。
Android 12 及更高版本
在以 Android 12(API 级别 31)及更高版本为目标的应用中,您可以通过将 requireDeviceScreenOn
设置为 false
来在设备息屏时启用 NFC 支付。
Android 10 及更高版本
运行 Android 10(API 级别 29)或更高版本的设备支持安全 NFC。开启安全 NFC 时,设备息屏后,所有卡模拟器(主机应用和非主机应用)都不可用。关闭安全 NFC 时,设备息屏后,非主机应用可用。您可以使用 isSecureNfcSupported()
检查是否支持安全 NFC。
在运行 Android 10 及更高版本的设备上,将 android:requireDeviceUnlock
设置为 true
的功能与运行 Android 9 及更低版本的设备相同,但仅在安全 NFC 关闭时适用。也就是说,如果安全 NFC 开启,无论 android:requireDeviceUnlock
的设置如何,HCE 服务都无法从锁屏状态下运行。
Android 9 及更低版本
在运行 Android 9(API 级别 28)及更低版本的设备上,设备息屏后,NFC 控制器和应用处理器会完全关闭。因此,HCE 服务在息屏时无法工作。
此外,在 Android 9 及更低版本上,HCE 服务可以在锁屏状态下工作。但是,这由您的 HCE 服务的 <host-apdu-service>
标签中的 android:requireDeviceUnlock
属性控制。默认情况下,不需要设备解锁,即使设备锁定,您的服务也会被调用。
如果您将 HCE 服务的 android:requireDeviceUnlock
属性设置为 true
,则在发生以下情况时,Android 会提示用户解锁设备
- 用户轻触 NFC 读卡器。
- NFC 读卡器选择一个解析到您的服务的 AID。
解锁后,Android 会显示一个对话框,提示用户再次轻触以完成交易。这是必要的,因为用户可能为了解锁而将设备从 NFC 读卡器移开了。
与安全单元卡共存
本节对已部署依赖于安全单元进行卡模拟的应用的开发者很有帮助。Android 的 HCE 实现旨在与实现卡模拟的其他方法(包括使用安全单元)并行工作。
这种共存基于一种称为AID 路由的原则。NFC 控制器维护一个路由表,其中包含(有限的)路由规则列表。每条路由规则包含一个 AID 和一个目标。目标可以是运行 Android 应用的主机 CPU,也可以是连接的安全单元。
当 NFC 读卡器发送包含 SELECT AID
的 APDU 时,NFC 控制器会解析它并检查 AID 是否与路由表中的任何 AID 匹配。如果匹配,则该 APDU 和随后的所有 APDU 都将发送到与该 AID 关联的目标,直到接收到另一个 SELECT AID
APDU 或 NFC 链接断开。
图 4 说明了此架构
图 4. Android 同时使用安全单元和主机卡模拟。
NFC 控制器通常还包含一个用于 APDU 的默认路由。当在路由表中找不到 AID 时,将使用默认路由。虽然此设置可能因设备而异,但 Android 设备必须确保您的应用注册的 AID 正确路由到主机。
实现 HCE 服务或使用安全单元的 Android 应用无需担心配置路由表;这由 Android 自动处理。Android 只需知道哪些 AID 可以由 HCE 服务处理,哪些 AID 可以由安全单元处理。路由表会根据安装的服务以及用户配置为首选的服务自动配置。
下一节解释了如何为使用安全单元进行卡模拟的应用声明 AID。
安全单元 AID 注册
使用安全单元进行卡模拟的应用可以在其清单中声明一个非主机服务。此类服务的声明几乎与 HCE 服务的声明完全相同。例外情况如下
- 意图过滤器中使用的操作必须设置为
SERVICE_INTERFACE
。 - meta-data 的 name 属性必须设置为
SERVICE_META_DATA
。 meta-data XML 文件必须使用
<offhost-apdu-service>
根标签。<service android:name=".MyOffHostApduService" android:secureElementName="eSE" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE"> <intent-filter> <action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/> </intent-filter> <meta-data android:name="android.nfc.cardemulation.off_host_apdu_service" android:resource="@xml/apduservice"/> </service>
以下是相应的 apduservice.xml
文件注册两个 AID 的示例
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc"> <aid-group android:description="@string/subscription" android:category="other"> <aid-filter android:name="F0010203040506"/> <aid-filter android:name="F0394148148100"/> </aid-group> </offhost-apdu-service>
android:requireDeviceUnlock
属性不适用于非主机服务,因为主机 CPU 不参与交易,因此无法阻止安全单元在设备锁定时执行交易。
android:apduServiceBanner
属性对于是支付应用的非主机服务以及可被选为默认支付应用的服务是必需的。
非主机服务调用
Android 从不启动或绑定声明为“非主机”的服务,因为实际交易由安全单元执行,而不是由 Android 服务执行。服务声明仅允许应用注册安全单元上存在的 AID。
HCE 和安全性
HCE 架构提供了一个核心安全特性:由于您的服务受 BIND_NFC_SERVICE
系统权限保护,只有操作系统可以绑定到您的服务并与之通信。这确保了您收到的任何 APDU 实际上是操作系统从 NFC 控制器接收到的 APDU,并且您发送回的任何 APDU 只会发送给操作系统,而操作系统又会将这些 APDU 直接转发给 NFC 控制器。
最后剩下的顾虑是您的应用发送给 NFC 读卡器的数据从何而来。这在 HCE 设计中有意解耦;它不关心数据来自何处,它只确保数据安全地传输到 NFC 控制器并发送到 NFC 读卡器。
为了安全地存储和检索您希望从 HCE 服务发送的数据,例如,您可以依靠 Android 应用沙盒,该沙盒将您的应用数据与其他应用隔离。有关 Android 安全性的更多详细信息,请阅读安全提示。
协议参数和详细信息
本节对于希望了解 HCE 设备在 NFC 协议的防冲突和激活阶段使用哪些协议参数的开发者很有帮助。这使得构建与 Android HCE 设备兼容的读卡器基础设施成为可能。
Nfc-A (ISO/IEC 14443 A 型) 协议防冲突和激活
作为 Nfc-A 协议激活的一部分,会交换多个帧。
在交换的第一部分,HCE 设备会呈现其 UID;应假定 HCE 设备具有随机 UID。这意味着在每次轻触时,呈现给读卡器的 UID 都是随机生成的 UID。因此,NFC 读卡器不应依赖 HCE 设备的 UID 作为身份验证或识别的形式。
NFC 读卡器随后可以通过发送 SEL_REQ
命令来选择 HCE 设备。HCE 设备的 SEL_RES
响应至少设置了第 6 位 (0x20),表明该设备支持 ISO-DEP。请注意,SEL_RES
中的其他位也可能被设置,例如指示支持 NFC-DEP (p2p) 协议。由于其他位可能被设置,希望与 HCE 设备交互的读卡器应只显式检查第 6 位,而不要将完整的 SEL_RES
与值 0x20 进行比较。
ISO-DEP 激活
Nfc-A 协议激活后,NFC 读卡器会启动 ISO-DEP 协议激活。它发送 RATS (Request for Answer To Select) 命令。NFC 控制器生成 RATS 响应,即 ATS;ATS 不可由 HCE 服务配置。然而,HCE 实现必须满足 NFC Forum 对 ATS 响应的要求,因此 NFC 读卡器可以指望任何 HCE 设备都根据 NFC Forum 的要求设置这些参数。
以下部分提供了有关 HCE 设备上 NFC 控制器提供的 ATS 响应中各个字节的更多详细信息
- TL:ATS 响应的长度。不得指示长度大于 20 字节。
- T0:在所有 HCE 设备上,位 5、6 和 7 必须设置,表示 ATS 响应中包含 TA(1)、TB(1) 和 TC(1)。位 1 到 4 表示 FSCI,编码最大帧大小。在 HCE 设备上,FSCI 的值必须在 0h 到 8h 之间。
- T(A)1:定义读卡器和模拟器之间的比特率,以及它们是否可以不对称。HCE 设备没有比特率要求或保证。
- T(B)1:位 1 到 4 表示启动帧保护时间整数 (SFGI)。在 HCE 设备上,SFGI 必须 <= 8h。位 5 到 8 表示帧等待时间整数 (FWI),并编码帧等待时间 (FWT)。在 HCE 设备上,FWI 必须 <= 8h。
- T(C)1:位 5 表示支持“高级协议特性”。HCE 设备可能支持或不支持“高级协议特性”。位 2 表示支持 DID。HCE 设备可能支持或不支持 DID。位 1 表示支持 NAD。HCE 设备不得支持 NAD 并将位 1 设置为零。
- 历史字节:HCE 设备最多可返回 15 个历史字节。愿意与 HCE 服务交互的 NFC 读卡器不应对历史字节的内容或其存在性做任何假设。
请注意,许多 HCE 设备很可能符合 EMVCo 联合支付网络在其“非接触式通信协议”规范中指定的协议要求。特别是
- T0 中的 FSCI 必须在 2h 和 8h 之间。
- T(A)1 必须设置为 0x80,表示仅支持 106 kbit/s 的比特率,并且不支持读卡器和模拟器之间的不对称比特率。
- T(B)1 中的 FWI 必须 <= 7h。
APDU 数据交换
如前所述,HCE 实现仅支持单个逻辑通道。在不同逻辑通道上尝试选择应用在 HCE 设备上不起作用。