Tổng quan về mô phỏng thẻ dựa trên máy chủ

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 thẻ và giao tiếp trực tiếp với đầu đọ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 ứng dụng Android. Sau đó, khi người dùng giữ thiết bị trê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:

Sơ đồ có trình đọc NFC đi qua bộ điều khiển NFC để truy xuất thông tin từ một phần tử bảo mật
Hình 1. Mô phỏng thẻ NFC bằng phần tử bảo mật.

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 thẻ NFC được mô phỏng 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 lưu trữ 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ủ:

Sơ đồ với trình đọc NFC đi qua bộ điều khiển NFC để truy xuất thông tin từ CPU
Hình 2. Mô phỏng thẻ NFC không có phần tử bảo mật.

Các giao thức và thẻ NFC được hỗ trợ

Sơ đồ thể hiện ngăn xếp giao thức HCE
Hình 3. Ngăn xếp giao thức HCE của Android.

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 trên 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 lựa chọ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 phải khởi chạy ứng dụng để sử dụng. Thay vào đó, thao tác nhấn thiết bị vào đầu đọc NFC sẽ khởi động đúng dịch vụ nếu dịch vụ đó chưa chạy và thực thi giao dịch ở chế độ nền. Tất nhiên, bạn có thể tự do 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 đầu đọc NFC hiện có, thì các AID mà các đầu đọc đó tìm kiếm thường là các AID nổi tiếng 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 đều được chuyể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:

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 hai 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 xác định 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 đầu đọc NFC và dịch vụ HCE của bạn. 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à đầu đọc NFC gửi đến thiết bị của bạn là APDU SELECT AID; APDU này chứa AID mà đầu đọc muốn giao tiếp. Android trích xuất AID đó từ APDU, phân giải AID đó 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 APDU phản hồi bằng cách trả về các byte của APDU phản hồi từ processCommandApdu(). Xin lưu ý rằng phương thức này được gọi trên luồng chính của ứng dụng và bạn không nên chặn luồng này. 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ừ đầu đọc đến dịch vụ của bạn cho đến khi một trong những điều 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.
  • Đường liên kết NFC giữa máy đọ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ụ:

  1. Để 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ác SERVICE_INTERFACE vào phần khai báo dịch vụ.

  2. Để 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.

  3. Đặt thuộc tính android:exported thành true và yêu cầu quyền android.permission.BIND_NFC_SERVICE trong phần khai báo dịch vụ. Phương thức trước đảm bảo rằng các ứng dụng bên ngoài có thể liên kết với 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ền android.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ề một tệp như vậy với một nội dung khai báo nhóm AID chứa hai 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 mà nhóm AID thuộc về, chẳng hạn như hằng số chuỗi do CATEGORY_PAYMENT hoặc CATEGORY_OTHER xác định.
  • Chứa một hoặc nhiều thẻ <aid-filter>, mỗi thẻ chứa một AID. Chỉ định AID ở định dạng thập lục phân và đảm bảo rằng mã này chứa số lượng 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:

  1. 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.
  2. 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.
  3. Nếu có nhiều dịch vụ đã đăng ký AID, thì Android sẽ hỏi người dùng về dịch vụ nào sẽ được gọi.

Lựa chọn ưu tiên về dịch vụ trên nền trước

Các ứng dụng ở nền trước có thể gọi setPreferredService để chỉ định dịch vụ mô phỏng thẻ nào nên được ưu tiên trong khi một hoạt động cụ thể đang chạy ở nền trước. Lựa chọn ưu tiên về ứng dụng trên nền trước này sẽ ghi đè giải pháp xung đột AID. Đây là phương pháp nên dùng khi ứng dụng dự đoán rằng người dùng có thể sử dụng tính năng mô phỏng thẻ NFC.

Android 13 trở lên

Để phù hợp hơn với danh sách lựa chọn phương thức 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à biểu tượng này 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>

Ứng dụng Wallet

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 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 để gọi khi nhấn vào thiết bị thanh toán. 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í.

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 chúng có phải là ứng dụng ví mặc định hay không bằng cách truyền RoleManager.ROLE_WALLET vào 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().

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ụ.

Chế độ quan sát

Android 15 giới thiệu tính năng Chế độ quan sát. Khi được bật, Chế độ quan sát cho phép thiết bị quan sát các vòng thăm dò ý kiến NFC và gửi thông báo về các vòng này đến các thành phần HostApduService thích hợp để các thành phần này có thể chuẩn bị tương tác với một thiết bị thanh toán NFC nhất định. HostApduService có thể đưa thiết bị vào Chế độ quan sát bằng cách truyền true đến 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ò ý kiến cho HostApduService bằng một trong các phương thức sau:

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 dành riêng cho 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 theo 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 HostApduServiceOffHostApduService 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.

Lựa chọn ưu tiên về dịch vụ trên nền trước

Các ứng dụng ở nền trước có thể gọi setPreferredService để chỉ định dịch vụ mô phỏng thẻ nào nên được ưu tiên trong khi một hoạt động cụ thể đang chạy ở nền trước. Lựa chọn ưu tiên về ứng dụng trên nền trước này sẽ ghi đè trạng thái Chế độ quan sát của thiết bị tương ứng với giá trị của shouldDefaultToObserveMode cho một dịch vụ nhất định. Bạn có thể đặt lựa chọn ưu tiên này theo một trong các cách sau:

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 thay đổi tuỳ theo phiên bản Android đang chạy trên thiết bị.

Android 15 trở lên

Nếu ứng dụng ví mặc định bật Chế độ quan sát trên một thiết bị hỗ trợ chế độ này, thì ứng dụng đó sẽ ghi đè hành vi mở khoá và tắt màn hình vì ứng dụng này kiểm soát thời điểm giao dịch có thể tiếp tục. Một số ứng dụng ví có thể yêu cầu thiết bị được mở khoá trước khi giao dịch có thể tiếp tục nếu Chế độ quan sát không phát hiện được mẫu vòng lặp thăm dò ý kiến có thể nhận dạng được.

Nhà phát triển nên làm việc với thiết bị đọc để phát ra các mẫu vòng lặp thăm dò ý kiến có thể nhận dạng được và đăng ký để xử lý các mẫu đó từ ứng dụng của họ.

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 đặt 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ẽ 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

Phần này dành cho những 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ẻ. 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 triển khai 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:

Sơ đồ có máy đọc NFC giao tiếp với cả phần tử bảo mật và CPU
Hình 4. Android hoạt động với cả phần tử bảo mật và tính năng mô phỏng thẻ dựa trên máy chủ.

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; bảng này do Android tự động xử lý. 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ý hai 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 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 đến hệ điều hành, sau đó hệ điều hành sẽ chuyển tiếp trực tiếp các APDU đến bộ điều khiển NFC.

Mối lo ngại cuối cùng còn lại là nơi bạn lấy dữ liệu mà ứng dụng gửi đến đầu đọc NFC. Điều này được tách biệt một cách có chủ ý trong thiết kế HCE; không quan tâm dữ liệu đến từ đâu, chỉ cần đảm bảo dữ liệu được truyền một cách an toàn đến bộ điều khiển NFC và đến đầu đọc NFC.

Để 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. Điều này có nghĩa là trên mỗi lần nhấn, UID được trình đọc hiển thị là một UID được tạo ngẫu nhiên. Do đó, trình đọc NFC không được phụ thuộc vào UID của thiết bị HCE dưới dạng một hình 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 những trình đọc muốn tương tác với thiết bị HCE chỉ nên kiểm tra rõ ràng 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 NFC Forum đối với phản hồi ATS, vì vậy, trình đọc NFC có thể dựa vào việc các tham số này được đặt theo yêu cầu của NFC Forum đối với 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 cho biết độ 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 các 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 hình (FWI) và mã hoá Thời gian chờ khung hình (FWT). Trên thiết bị HCE, FWI phải <= 8h.
  • T(C)1: bit 5 cho biết khả năng hỗ trợ "Tính năng giao thức nâng cao". 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.
  • Byte trước đây: Thiết bị HCE có thể trả về tối đa 15 byte trước đây. Các đầu đọc NFC sẵn sàng tương tác với các dịch vụ HCE không được đưa ra giả định về nội dung của các byte trong quá khứ 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ể được tạo để 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 giao tiếp 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 các ứ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.