Nhiều thiết bị chạy Android có chức năng NFC đã hỗ trợ tính năng mô phỏng thẻ NFC. Trong hầu hết các trường hợp, thẻ được mô phỏng bằng một khối riêng biệt trong thiết bị, được gọi là phần tử bảo mật. Nhiều thẻ SIM do nhà mạng không dây cung cấp cũng chứa một phần tử bảo mật.
Android 4.4 trở lên cung cấp một phương thức mô phỏng thẻ bổ sung không liên quan đến phần tử bảo mật, được gọi là mô phỏng thẻ dựa trên máy chủ. Điều này cho phép mọi ứng dụng Android mô phỏng một thẻ và giao tiếp trực tiếp với trình đọc NFC. Chủ đề này mô tả cách hoạt động của tính năng mô phỏng thẻ dựa trên máy chủ (HCE) trên Android và cách bạn có thể phát triển một ứng dụng mô phỏng thẻ NFC bằng kỹ thuật này.
Mô phỏng thẻ bằng phần tử bảo mật
Khi mô phỏng thẻ NFC được cung cấp bằng phần tử bảo mật, thẻ cần được mô phỏng sẽ được cấp vào phần tử bảo mật trên thiết bị thông qua một ứng dụng Android. Sau đó, khi người dùng đưa thiết bị lại gần thiết bị thanh toán không tiếp xúc (NFC), trình điều khiển NFC trong thiết bị sẽ định tuyến tất cả dữ liệu từ đầu đọc trực tiếp đến phần tử bảo mật. Hình 1 minh hoạ khái niệm này:
Phần tử bảo mật tự thực hiện việc giao tiếp với thiết bị thanh toán NFC và không có ứng dụng Android nào tham gia vào giao dịch. Sau khi giao dịch hoàn tất, ứng dụng Android có thể truy vấn trực tiếp phần tử bảo mật để biết trạng thái giao dịch và thông báo cho người dùng.
Mô phỏng thẻ dựa trên máy chủ
Khi mô phỏng thẻ NFC bằng tính năng mô phỏng thẻ dựa trên máy chủ, dữ liệu sẽ được định tuyến trực tiếp đến CPU của máy chủ thay vì được định tuyến đến một phần tử bảo mật. Hình 2 minh hoạ cách hoạt động của tính năng mô phỏng thẻ dựa trên máy chủ:
Các giao thức và thẻ NFC được hỗ trợ
Các tiêu chuẩn NFC hỗ trợ nhiều giao thức và bạn có thể mô phỏng nhiều loại thẻ.
Android 4.4 trở lên hỗ trợ một số giao thức phổ biến trên thị trường hiện nay. Nhiều thẻ không tiếp xúc hiện có đã dựa trên các giao thức này, chẳng hạn như thẻ thanh toán không tiếp xúc. Nhiều trình đọc NFC trên thị trường hiện nay cũng hỗ trợ các giao thức này, bao gồm cả các thiết bị NFC Android hoạt động như trình đọc (xem lớp IsoDep
). Điều này cho phép bạn xây dựng và triển khai giải pháp NFC toàn diện xung quanh HCE chỉ bằng các thiết bị chạy Android.
Cụ thể, Android 4.4 trở lên hỗ trợ mô phỏng thẻ dựa trên quy cách ISO-DEP của NFC-Forum (dựa trên ISO/IEC 14443-4) và xử lý các đơn vị dữ liệu giao thức ứng dụng (APDU) như được xác định trong quy cách ISO/IEC 7816-4. Android chỉ yêu cầu mô phỏng ISO-DEP ngoài công nghệ Nfc-A (ISO/IEC 14443-3 Loại A). Không bắt buộc phải hỗ trợ công nghệ Nfc-B (ISO/IEC 14443-4 Loại B). Hình 3 minh hoạ việc phân lớp tất cả các thông số kỹ thuật này.
Dịch vụ HCE
Cấu trúc HCE trong Android dựa trên các thành phần Service
của Android (còn gọi là dịch vụ HCE). Một trong những lợi thế chính của dịch vụ là có thể chạy ở chế độ nền mà không cần giao diện người dùng. Đây là một cách tự nhiên phù hợp với nhiều ứng dụng HCE, chẳng hạn như thẻ khách hàng thân thiết hoặc thẻ đi phương tiện công cộng mà người dùng không cần chạy ứng dụng để sử dụng. Thay vào đó, việc đưa thiết bị chạm vào trình đọc NFC sẽ khởi động dịch vụ chính xác nếu ứng dụng chưa chạy và thực hiện giao dịch trong nền. Tất nhiên, bạn có thể tự do khởi chạy giao diện người dùng bổ sung (chẳng hạn như thông báo cho người dùng) từ dịch vụ của mình khi thích hợp.
Lựa chọn dịch vụ
Khi người dùng nhấn vào một thiết bị để đọc máy đọc NFC, hệ thống Android cần biết dịch vụ HCE mà máy đọc NFC muốn giao tiếp. Quy cách ISO/IEC 7816-4 xác định cách chọn ứng dụng, tập trung vào Mã ứng dụng (AID). AID bao gồm tối đa 16 byte. Nếu bạn đang mô phỏng thẻ cho cơ sở hạ tầng đọc NFC hiện có, thì AID mà độc giả đó tìm kiếm thường là AID phổ biến và được đăng ký công khai (ví dụ: AID của các mạng thanh toán như Visa và MasterCard).
Nếu muốn triển khai cơ sở hạ tầng trình đọc mới cho ứng dụng của riêng mình, bạn phải đăng ký AID của riêng mình. Quy trình đăng ký AID được xác định trong quy cách ISO/IEC 7816-5. Bạn nên đăng ký AID theo 7816-5 nếu đang triển khai ứng dụng HCE cho Android, vì việc này giúp tránh xung đột với các ứng dụng khác.
Nhóm AID
Trong một số trường hợp, dịch vụ HCE có thể cần đăng ký nhiều AID và được đặt làm trình xử lý mặc định cho tất cả AID để triển khai một ứng dụng nhất định. Một số mã nhận dạng ứng dụng trong nhóm chuyển đến một dịch vụ khác không được hỗ trợ.
Danh sách các AID được lưu trữ cùng nhau được gọi là nhóm AID. Đối với tất cả AID trong một nhóm AID, Android đảm bảo một trong những điều sau:
- Tất cả AID trong nhóm được định tuyến đến dịch vụ HCE này.
- Không có mã nhận dạng thiết bị (AID) nào trong nhóm được định tuyến đến dịch vụ HCE này (ví dụ: vì người dùng ưu tiên một dịch vụ khác cũng yêu cầu một hoặc nhiều AID trong nhóm của bạn).
Nói cách khác, không có trạng thái trung gian nào, trong đó một số AID trong nhóm có thể được định tuyến đến một dịch vụ HCE và một số khác đến một dịch vụ khác.
Nhóm và danh mục AID
Bạn có thể liên kết từng nhóm AID với một danh mục. Điều này cho phép Android nhóm các dịch vụ HCE lại với nhau theo danh mục, từ đó cho phép người dùng đặt các giá trị mặc định ở cấp danh mục thay vì cấp AID. Tránh đề cập đến AID trong bất kỳ phần nào của ứng dụng mà người dùng nhìn thấy, vì những từ này không có ý nghĩa gì đối với người dùng thông thường.
Android 4.4 trở lên hỗ trợ hai danh mục:
CATEGORY_PAYMENT
(bao gồm các ứng dụng thanh toán tuân thủ tiêu chuẩn ngành)CATEGORY_OTHER
(dành cho tất cả ứng dụng HCE khác)
Triển khai dịch vụ HCE
Để mô phỏng thẻ NFC bằng tính năng mô phỏng thẻ dựa trên máy chủ, bạn cần tạo một thành phần Service
để xử lý các giao dịch NFC.
Kiểm tra xem thiết bị có hỗ trợ HCE hay không
Ứng dụng của bạn có thể kiểm tra xem thiết bị có hỗ trợ HCE hay không bằng cách kiểm tra tính năng FEATURE_NFC_HOST_CARD_EMULATION
. Sử dụng thẻ <uses-feature>
trong tệp kê khai của ứng dụng để khai báo rằng ứng dụng của bạn sử dụng tính năng HCE và liệu tính năng này có cần thiết để ứng dụng hoạt động hay không.
Triển khai dịch vụ
Android 4.4 trở lên cung cấp một lớp Service
thuận tiện mà bạn có thể sử dụng làm cơ sở để triển khai dịch vụ HCE: lớp HostApduService
.
Bước đầu tiên là mở rộng HostApduService
, như trong mã mẫu sau đây:
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
khai báo 2 phương thức trừu tượng mà bạn phải ghi đè và triển khai. Một trong số đó là processCommandApdu()
, được gọi mỗi khi trình đọc NFC gửi một Đơn vị dữ liệu giao thức ứng dụng (APDU) đến dịch vụ của bạn. APDU được định nghĩa trong thông số kỹ thuật ISO/IEC 7816-4. APDU là các gói cấp ứng dụng được trao đổi giữa trình đọc NFC và dịch vụ HCE. Giao thức cấp ứng dụng đó là giao thức bán song công: đầu đọc NFC sẽ gửi cho bạn một APDU lệnh và chờ bạn gửi lại một APDU phản hồi.
Như đã đề cập trước đó, Android sử dụng AID để xác định dịch vụ HCE mà trình đọc muốn giao tiếp. Thông thường, APDU đầu tiên mà trình đọc NFC gửi tới thiết bị của bạn là APDU SELECT AID
; APDU này chứa AID mà người đọc muốn giao tiếp. Android trích xuất APDU đó từ APDU, phân giải APDU đó thành một dịch vụ HCE, sau đó chuyển tiếp APDU đó đến dịch vụ đã phân giải.
Bạn có thể gửi một APDU phản hồi bằng cách trả về các byte của APDU phản hồi từ processCommandApdu()
. Lưu ý rằng phương thức này được gọi trên luồng chính của ứng dụng mà bạn không nên chặn. Nếu bạn không thể tính toán và trả về APDU phản hồi ngay lập tức, hãy trả về giá trị rỗng. Sau đó, bạn có thể thực hiện công việc cần thiết trên một luồng khác và sử dụng phương thức sendResponseApdu()
được xác định trong lớp HostApduService
để gửi phản hồi khi bạn hoàn tất.
Android sẽ tiếp tục chuyển tiếp các APDU mới từ trình đọc đến dịch vụ của bạn cho đến khi một trong hai trường hợp sau xảy ra:
- Đầu đọc NFC sẽ gửi một APDU
SELECT AID
khác mà hệ điều hành sẽ phân giải thành một dịch vụ khác. - Liên kết NFC giữa trình đọc NFC và thiết bị của bạn bị hỏng.
Trong cả hai trường hợp này, quá trình triển khai onDeactivated()
của lớp sẽ được gọi bằng một đối số cho biết sự kiện nào trong hai sự kiện đã xảy ra.
Nếu đang làm việc với cơ sở hạ tầng của trình đọc hiện có, bạn phải triển khai giao thức cấp ứng dụng hiện có mà trình đọc mong đợi trong dịch vụ HCE của bạn.
Nếu đang triển khai cơ sở hạ tầng đầu đọc mới mà bạn cũng kiểm soát, bạn có thể xác định giao thức và trình tự APDU của riêng mình. Cố gắng giới hạn số lượng APDU và kích thước dữ liệu cần trao đổi: điều này đảm bảo rằng người dùng chỉ cần giữ thiết bị của họ trên đầu đọc NFC trong một khoảng thời gian ngắn. Giới hạn trên hợp lý là khoảng 1 KB dữ liệu, thường có thể được trao đổi trong vòng 300 ms.
Khai báo tệp kê khai dịch vụ và đăng ký AID
Bạn phải khai báo dịch vụ trong tệp kê khai như bình thường, nhưng bạn cũng phải thêm một số phần bổ sung vào nội dung khai báo dịch vụ:
Để cho nền tảng biết rằng đó là dịch vụ HCE triển khai giao diện
HostApduService
, hãy thêm bộ lọc ý định cho thao tácSERVICE_INTERFACE
vào phần khai báo dịch vụ.Để cho nền tảng biết dịch vụ này yêu cầu nhóm AID nào, hãy thêm thẻ
SERVICE_META_DATA
<meta-data>
vào phần khai báo dịch vụ, trỏ đến tài nguyên XML có thêm thông tin về dịch vụ HCE.Đặt thuộc tính
android:exported
thànhtrue
và yêu cầu quyềnandroid.permission.BIND_NFC_SERVICE
trong phần khai báo dịch vụ. Cấu hình trước đảm bảo rằng các ứng dụng bên ngoài có thể liên kết dịch vụ. Sau đó, phần sau sẽ thực thi việc chỉ những ứng dụng bên ngoài có quyềnandroid.permission.BIND_NFC_SERVICE
mới có thể liên kết với dịch vụ của bạn. Vìandroid.permission.BIND_NFC_SERVICE
là quyền hệ thống, nên việc này sẽ thực thi hiệu quả để chỉ hệ điều hành Android mới có thể liên kết với dịch vụ của bạn.
Sau đây là ví dụ về nội dung khai báo tệp kê khai 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>
Thẻ siêu dữ liệu này trỏ đến tệp apduservice.xml
. Sau đây là ví dụ về tệp như vậy với một nội dung khai báo nhóm AID duy nhất chứa 2 AID độc quyền:
<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>
Thẻ <host-apdu-service>
phải chứa thuộc tính <android:description>
chứa nội dung mô tả dễ hiểu về dịch vụ mà bạn có thể hiển thị trong giao diện người dùng của ứng dụng. Bạn có thể sử dụng thuộc tính requireDeviceUnlock
để chỉ định rằng thiết bị đã được mở khoá trước khi bạn gọi dịch vụ này để xử lý APDU.
<host-apdu-service>
phải chứa một hoặc nhiều thẻ <aid-group>
. Mỗi thẻ <aid-group>
bắt buộc phải thực hiện những việc sau:
- Chứa thuộc tính
android:description
chứa nội dung mô tả nhóm AID dễ hiểu cho người dùng, phù hợp để hiển thị trong giao diện người dùng. - Đặt thuộc tính
android:category
để cho biết danh mục của nhóm AID, chẳng hạn như các hằng số chuỗi doCATEGORY_PAYMENT
hoặcCATEGORY_OTHER
xác định. - Chứa một hoặc nhiều thẻ
<aid-filter>
, mỗi thẻ chứa một AID. Hãy chỉ định AID ở định dạng thập lục phân và đảm bảo AID chứa số ký tự chẵn.
Ứng dụng của bạn cũng cần có quyền NFC
để đăng ký làm dịch vụ HCE.
Giải quyết xung đột AID
Bạn có thể cài đặt nhiều thành phần HostApduService
trên một thiết bị và nhiều dịch vụ có thể đăng ký cùng một AID. Android xác định dịch vụ nào sẽ được gọi bằng các bước sau:
- Nếu ứng dụng ví mặc định mà người dùng chọn đã đăng ký AID, thì ứng dụng đó sẽ được gọi.
- Nếu ứng dụng ví mặc định chưa đăng ký AID, thì dịch vụ đã đăng ký AID sẽ được gọi.
- Nếu nhiều dịch vụ đã đăng ký AID, thì Android sẽ hỏi người dùng gọi dịch vụ nào.
Kiểm tra xem ứng dụng của bạn có phải là ứng dụng ví mặc định không
Các ứng dụng có thể kiểm tra xem đó có phải là ứng dụng ví mặc định hay không bằng cách truyền RoleManager.ROLE_WALLET
đến RoleManager.isRoleHeld()
.
Nếu ứng dụng của bạn không phải là ứng dụng mặc định, bạn có thể yêu cầu vai trò ví mặc định bằng cách truyền RoleManager.ROLE_WALLET
đến RoleManager.createRequestRoleIntent()
.
Ứng dụng Wallet
Android coi các dịch vụ HCE đã khai báo một nhóm AID có danh mục thanh toán là ứng dụng ví. Android 15 trở lên có một vai trò ứng dụng ví mặc định mà người dùng có thể chọn bằng cách chuyển đến phần Cài đặt > Ứng dụng > Ứng dụng mặc định. Thao tác này xác định ứng dụng ví mặc định sẽ gọi khi một thiết bị thanh toán được nhấn vào.
Thành phần bắt buộc cho ứng dụng ví
Để mang lại trải nghiệm trực quan hấp dẫn hơn cho người dùng, các ứng dụng ví HCE phải cung cấp biểu ngữ dịch vụ.
Android 13 trở lên
Để vừa hơn với danh sách lựa chọn thông tin thanh toán mặc định trong giao diện người dùng Cài đặt, hãy điều chỉnh yêu cầu về biểu ngữ thành biểu tượng hình vuông. Tốt nhất là thiết kế của biểu tượng phải giống với thiết kế biểu tượng trình chạy ứng dụng. Điều chỉnh này giúp tạo sự nhất quán và giao diện rõ ràng hơn.
Android 12 trở xuống
Đặt kích thước của biểu ngữ dịch vụ thành 260x96 dp, sau đó đặt kích thước của biểu ngữ dịch vụ trong tệp XML siêu dữ liệu bằng cách thêm thuộc tính android:apduServiceBanner
vào thẻ <host-apdu-service>
trỏ đến tài nguyên có thể vẽ. Sau đây là ví dụ:
<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>
Chế độ quan sát
Android 15 giới thiệu tính năng Chế độ quan sát. Khi bật, Chế độ quan sát cho phép thiết bị quan sát các vòng lặp thăm dò NFC và gửi thông báo về các vòng lặp đó đến các thành phần HostApduService
thích hợp để có thể chuẩn bị tương tác với một thiết bị đầu cuối NFC nhất định. HostApduService
có thể đưa thiết bị vào Chế độ quan sát bằng cách truyền true
vào setObserveModeEnabled()
.
Thao tác này sẽ hướng dẫn ngăn xếp NFC không cho phép các giao dịch NFC và thay vào đó là chủ động
quan sát các vòng thăm dò ý kiến.
Bộ lọc vòng lặp thăm dò
Bạn có thể đăng ký bộ lọc vòng lặp thăm dò cho HostApduService
bằng một trong các phương thức sau:
registerPollingLoopFilterForService()
đối với các bộ lọc phải khớp chính xác với khung thăm dò ý kiến.registerPollingLoopPatternFilterForService()
cho các bộ lọc khớp với một biểu thức chính quy so với các khung thăm dò ý kiến.
Khi bộ lọc vòng lặp thăm dò ý kiến khớp với các khung thăm dò ý kiến không chuẩn, ngăn xếp NFC sẽ định tuyến các khung thăm dò ý kiến đó đến HostApduService
tương ứng bằng cách gọi phương thức processPollingFrames()
. Điều này cho phép dịch vụ thực hiện mọi bước cần thiết để đảm bảo rằng người dùng đã sẵn sàng giao dịch và có ý định thực hiện giao dịch đó, ví dụ: xác thực người dùng. Nếu trình đọc NFC chỉ sử dụng các khung tiêu chuẩn trong vòng lặp thăm dò ý kiến, thì ngăn xếp NFC sẽ định tuyến các khung thăm dò ý kiến đó đến dịch vụ trên nền trước ưu tiên nếu dịch vụ đó đang ở nền trước hoặc đến chủ sở hữu vai trò ví mặc định nếu không.
Thông báo khung thăm dò ý kiến cũng bao gồm thông tin đo lường cường độ trường theo nhà cung cấp mà bạn có thể truy xuất bằng cách gọi getVendorSpecificGain()
.
Nhà cung cấp có thể cung cấp số liệu đo lường bằng cách sử dụng thang đo của riêng họ, miễn là thang đo đó vừa với một byte.
Phản hồi các vòng thăm dò ý kiến và chuyển đổi khỏi Chế độ quan sát
Khi đã sẵn sàng giao dịch, dịch vụ có thể thoát khỏi Chế độ quan sát bằng cách truyền false
đến setObserveModeEnabled()
. Sau đó, ngăn xếp NFC sẽ cho phép các giao dịch tiếp tục.
Các thành phần HostApduService
có thể cho biết rằng bạn nên bật Chế độ quan sát bất cứ khi nào chúng là dịch vụ thanh toán ưu tiên bằng cách đặt shouldDefaultToObserveMode
thành true
trong tệp kê khai hoặc bằng cách gọi CardEmulation.setShouldDefaultToObserveModeForService()
.
Các thành phần HostApduService
và OffHostApduService
cũng có thể cho biết rằng các bộ lọc vòng lặp thăm dò ý kiến khớp với các khung vòng lặp thăm dò ý kiến đã nhận được sẽ tự động tắt Chế độ quan sát và cho phép các giao dịch tiếp tục bằng cách đặt autoTransact
thành true
trong phần khai báo PollingLoopFilter
trong tệp kê khai.
Hành vi khi tắt màn hình và khoá màn hình
Hành vi của các dịch vụ HCE sẽ thay đổi tuỳ theo phiên bản Android chạy trên thiết bị.
Android 12 trở lên
Trong các ứng dụng nhắm đến Android 12 (API cấp 31) trở lên, bạn có thể bật tính năng thanh toán NFC mà không cần bật màn hình của thiết bị bằng cách đặt requireDeviceScreenOn
thành false
.
Android 10 trở lên
Các thiết bị chạy Android 10 (API cấp 29) trở lên hỗ trợ NFC bảo mật. Khi chế độ NFC bảo mật đang bật, tất cả trình mô phỏng thẻ (ứng dụng lưu trữ và ứng dụng không lưu trữ) sẽ không hoạt động khi màn hình thiết bị tắt. Khi chế độ NFC bảo mật đang tắt, các ứng dụng không lưu trữ sẽ hoạt động khi màn hình thiết bị tắt. Bạn có thể kiểm tra tính năng hỗ trợ NFC bảo mật bằng cách sử dụng isSecureNfcSupported()
.
Trên các thiết bị chạy Android 10 trở lên, chức năng thiết lập android:requireDeviceUnlock
thành true
cũng áp dụng như với các thiết bị chạy Android 9 trở xuống, nhưng chỉ khi bạn tắt tính năng NFC bảo mật. Tức là nếu bạn bật tính năng NFC bảo mật, các dịch vụ HCE sẽ không thể hoạt động trên màn hình khoá bất kể chế độ cài đặt của android:requireDeviceUnlock
.
Android 9 trở xuống
Trên các thiết bị chạy Android 9 (API cấp 28) trở xuống, bộ điều khiển NFC và bộ xử lý ứng dụng sẽ bị tắt hoàn toàn khi màn hình của thiết bị tắt. Do đó, các dịch vụ HCE không hoạt động khi màn hình tắt.
Ngoài ra, trên Android 9 trở xuống, các dịch vụ HCE có thể hoạt động trên màn hình khoá.
Tuy nhiên, thuộc tính này do thuộc tính android:requireDeviceUnlock
trong thẻ <host-apdu-service>
của dịch vụ HCE kiểm soát. Theo mặc định, bạn không cần phải mở khoá thiết bị và dịch vụ của bạn sẽ được gọi ngay cả khi thiết bị đang khoá.
Nếu bạn đặt thuộc tính android:requireDeviceUnlock
thành true
cho dịch vụ HCE, Android sẽ nhắc người dùng mở khoá thiết bị khi những điều sau xảy ra:
- người dùng nhấn vào một đầu đọc NFC.
- đầu đọc NFC sẽ chọn một AID được phân giải đến dịch vụ của bạn.
Sau khi mở khoá, Android sẽ hiển thị một hộp thoại nhắc người dùng nhấn lại để hoàn tất giao dịch. Điều này là cần thiết vì người dùng có thể đã di chuyển thiết bị ra khỏi máy đọc NFC để mở khoá thiết bị.
Cùng tồn tại với thẻ có phần tử bảo mật
Các nhà phát triển đã triển khai một ứng dụng dựa vào phần tử bảo mật để mô phỏng thẻ sẽ quan tâm đến phần này. Phương thức triển khai HCE của Android được thiết kế để hoạt động song song với các phương thức mô phỏng thẻ khác, bao gồm cả việc sử dụng các phần tử bảo mật.
Việc cùng tồn tại này dựa trên một nguyên tắc có tên là định tuyến AID. Bộ điều khiển NFC lưu giữ một bảng định tuyến bao gồm danh sách (có giới hạn) các quy tắc định tuyến. Mỗi quy tắc định tuyến chứa một AID và một đích đến. Đích đến có thể là CPU lưu trữ, nơi các ứng dụng Android đang chạy hoặc một phần tử bảo mật đã kết nối.
Khi trình đọc NFC gửi một APDU có SELECT AID
, bộ điều khiển NFC sẽ phân tích cú pháp APDU đó và kiểm tra xem các AID có khớp với bất kỳ AID nào trong bảng định tuyến của nó hay không. Nếu khớp, APDU đó và tất cả APDU theo sau sẽ được gửi đến đích liên kết với AID, cho đến khi nhận được APDU SELECT AID
khác hoặc đường liên kết NFC bị ngắt.
Hình 4 minh hoạ cấu trúc này:
Bộ điều khiển NFC thường cũng chứa một tuyến mặc định cho APDU. Khi không tìm thấy AID trong bảng định tuyến, tuyến mặc định sẽ được sử dụng. Mặc dù chế độ cài đặt này có thể khác nhau giữa các thiết bị, nhưng các thiết bị Android bắt buộc phải đảm bảo rằng các AID mà ứng dụng của bạn đăng ký được định tuyến đúng cách đến máy chủ lưu trữ.
Các ứng dụng Android triển khai dịch vụ HCE hoặc sử dụng phần tử bảo mật không phải lo lắng về việc định cấu hình bảng định tuyến; việc này sẽ do Android xử lý tự động. Android chỉ cần biết dịch vụ HCE có thể xử lý AID nào và phần tử bảo mật có thể xử lý AID nào. Bảng định tuyến được định cấu hình tự động dựa trên các dịch vụ đã cài đặt và dịch vụ mà người dùng đã định cấu hình là ưu tiên.
Phần sau đây giải thích cách khai báo AID cho các ứng dụng sử dụng phần tử bảo mật để mô phỏng thẻ.
Đăng ký AID trên phần tử bảo mật
Các ứng dụng sử dụng phần tử bảo mật để mô phỏng thẻ có thể khai báo dịch vụ ngoài máy chủ trong tệp kê khai. Việc khai báo một dịch vụ như vậy gần giống với việc khai báo dịch vụ HCE. Sau đây là các trường hợp ngoại lệ:
- Bạn phải đặt hành động dùng trong bộ lọc ý định thành
SERVICE_INTERFACE
. - Bạn phải đặt thuộc tính tên siêu dữ liệu thành
SERVICE_META_DATA
. Tệp XML siêu dữ liệu phải sử dụng thẻ gốc
<offhost-apdu-service>
.<service android:name=".MyOffHostApduService" 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>
Sau đây là ví dụ về tệp apduservice.xml
tương ứng đăng ký 2 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>
Thuộc tính android:requireDeviceUnlock
không áp dụng cho các dịch vụ ngoài máy chủ lưu trữ, vì CPU của máy chủ lưu trữ không tham gia vào giao dịch và do đó không thể ngăn phần tử bảo mật thực thi giao dịch khi thiết bị bị khoá.
Thuộc tính android:apduServiceBanner
là bắt buộc đối với các dịch vụ bên ngoài máy chủ là ứng dụng thanh toán và có thể được chọn làm ứng dụng thanh toán mặc định.
Lệnh gọi dịch vụ ngoài máy chủ lưu trữ
Android không bao giờ khởi động hoặc liên kết với một dịch vụ được khai báo là "ngoài máy chủ", vì các giao dịch thực tế được thực thi bởi phần tử bảo mật chứ không phải dịch vụ Android. Nội dung khai báo dịch vụ chỉ cho phép các ứng dụng đăng ký AID có trên phần tử bảo mật.
HCE và bảo mật
Kiến trúc HCE cung cấp một phần bảo mật cốt lõi: vì dịch vụ của bạn được bảo vệ bằng quyền hệ thống BIND_NFC_SERVICE
, nên chỉ hệ điều hành mới có thể liên kết và giao tiếp với dịch vụ của bạn.
Điều này đảm bảo rằng mọi APDU bạn nhận được đều thực sự là APDU mà hệ điều hành nhận được từ bộ điều khiển NFC, và mọi APDU bạn gửi lại chỉ chuyển tiếp đến hệ điều hành, sau đó sẽ chuyển tiếp trực tiếp các APDU đó đến bộ điều khiển NFC.
Mối quan tâm cuối cùng còn lại là nơi bạn nhận dữ liệu mà ứng dụng của bạn gửi đến trình đọc NFC. API này được phân tách có chủ đích trong thiết kế HCE; nó không quan tâm đến nguồn gốc của dữ liệu mà chỉ đảm bảo rằng dữ liệu được truyền an toàn tới bộ điều khiển NFC và tới trình đọc NFC.
Ví dụ: để lưu trữ và truy xuất an toàn dữ liệu mà bạn muốn gửi từ dịch vụ HCE, bạn có thể dựa vào Hộp cát ứng dụng Android để tách biệt dữ liệu của ứng dụng với các ứng dụng khác. Để biết thêm thông tin chi tiết về tính bảo mật của Android, hãy đọc bài viết Mẹo bảo mật.
Thông số và thông tin chi tiết về giao thức
Phần này dành cho những nhà phát triển muốn tìm hiểu các tham số giao thức mà thiết bị HCE sử dụng trong các giai đoạn chống xung đột và kích hoạt của giao thức NFC. Điều này cho phép xây dựng một cơ sở hạ tầng đầu đọc tương thích với các thiết bị Android HCE.
Khả năng chống xung đột và kích hoạt giao thức Nfc-A (ISO/IEC 14443 loại A)
Trong quá trình kích hoạt giao thức Nfc-A, nhiều khung hình sẽ được trao đổi.
Trong phần đầu của quá trình trao đổi, thiết bị HCE sẽ hiển thị UID của thiết bị; giả định rằng thiết bị HCE có UID ngẫu nhiên. Tức là mỗi lần nhấn, UID mà trình đọc nhìn thấy sẽ là một UID được tạo ngẫu nhiên. Do đó, trình đọc NFC không nên phụ thuộc vào UID của thiết bị HCE làm phương thức xác thực hoặc nhận dạng.
Sau đó, trình đọc NFC có thể chọn thiết bị HCE bằng cách gửi lệnh SEL_REQ
. Phản hồi SEL_RES
của thiết bị HCE đã đặt ít nhất bit thứ 6 (0x20), cho biết thiết bị hỗ trợ ISO-DEP. Xin lưu ý rằng các bit khác trong SEL_RES
cũng có thể được đặt, chẳng hạn như cho biết hỗ trợ giao thức NFC-DEP (p2p). Vì các bit khác có thể được đặt, nên độc giả muốn tương tác với các thiết bị HCE chỉ nên kiểm tra rõ ràng cho bit thứ 6 và không so sánh SEL_RES
hoàn chỉnh với giá trị 0x20.
Kích hoạt ISO-DEP
Sau khi giao thức Nfc-A được kích hoạt, trình đọc NFC sẽ bắt đầu kích hoạt giao thức ISO-DEP. Lệnh này sẽ gửi một lệnh RATS (Yêu cầu trả lời để chọn). Bộ điều khiển NFC tạo ra phản hồi RATS, ATS; các dịch vụ HCE không thể định cấu hình ATS. Tuy nhiên, việc triển khai HCE phải đáp ứng các yêu cầu của Diễn đàn NFC đối với phản hồi ATS, để trình đọc NFC có thể tin tưởng vào các thông số này được thiết lập theo các yêu cầu của Diễn đàn NFC cho mọi thiết bị HCE.
Phần dưới đây cung cấp thêm thông tin chi tiết về từng byte của phản hồi ATS do bộ điều khiển NFC trên thiết bị HCE cung cấp:
- TL: độ dài của phản hồi ATS. Không được chỉ ra độ dài lớn hơn 20 byte.
- T0: phải đặt bit 5, 6 và 7 trên tất cả thiết bị HCE, cho biết TA(1), TB(1) và TC(1) có trong phản hồi ATS. Các bit từ 1 đến 4 cho biết FSCI, mã hoá kích thước khung hình tối đa. Trên các thiết bị HCE, giá trị của FSCI phải nằm trong khoảng từ 0h đến 8h.
- T(A)1: xác định tốc độ bit giữa trình đọc và trình mô phỏng, cũng như liệu các tốc độ bit đó có thể không đối xứng hay không. Không có yêu cầu hoặc đảm bảo về tốc độ bit đối với thiết bị HCE.
- T(B)1: bit 1 đến 4 cho biết Số nguyên thời gian bảo vệ khung hình khởi động (SFGI). Trên thiết bị HCE, SFGI phải <= 8h. Các bit từ 5 đến 8 cho biết Số nguyên thời gian chờ khung (FWI) và mã hoá Thời gian chờ khung (FWT). Trên thiết bị HCE, FWI phải <= 8h.
- T(C)1: bit 5 biểu thị sự hỗ trợ cho "Các tính năng của giao thức nâng cao". Các thiết bị HCE có thể hỗ trợ hoặc không hỗ trợ "Tính năng giao thức nâng cao". Bit 2 cho biết tính năng hỗ trợ DID. Thiết bị HCE có thể hỗ trợ hoặc không hỗ trợ DID. Bit 1 cho biết khả năng hỗ trợ NAD. Thiết bị HCE không được hỗ trợ NAD và đặt bit 1 thành 0.
- Số byte trước đây: Thiết bị HCE có thể trả về tối đa 15 byte trước đây. Trình đọc NFC sẵn sàng tương tác với các dịch vụ HCE không nên đưa ra giả định về nội dung của các byte trước đây hoặc sự hiện diện của các byte đó.
Xin lưu ý rằng nhiều thiết bị HCE có thể tuân thủ các yêu cầu về giao thức mà các mạng thanh toán hợp nhất trong EMVCo đã chỉ định trong thông số kỹ thuật "Giao thức liên lạc không tiếp xúc". Cụ thể:
- FSCI trong T0 phải nằm trong khoảng từ 2h đến 8h.
- Bạn phải đặt T(A)1 thành 0x80, cho biết chỉ hỗ trợ tốc độ bit 106 kbit/giây và không hỗ trợ tốc độ bit không đối xứng giữa trình đọc và trình mô phỏng.
- FWI trong T(B)1 phải <= 7h.
Trao đổi dữ liệu APDU
Như đã lưu ý trước đó, các phương thức triển khai HCE chỉ hỗ trợ một kênh logic duy nhất. Việc cố gắng chọn ứng dụng trên các kênh logic khác nhau sẽ không hoạt động trên thiết bị HCE.