Panoramica dell'emulazione della carta basata su host

Molti dispositivi Android che offrono funzionalità NFC supportano già l'emulazione della scheda NFC. Nella maggior parte dei casi, la carta viene emulata da un chip separato nel dispositivo, chiamato elemento sicuro. Molte schede SIM fornite dagli operatori wireless contengono anche un elemento di sicurezza.

Android 4.4 e versioni successive forniscono un metodo aggiuntivo di emulazione della carta che non prevede un elemento sicuro, chiamato emulazione della carta basata sull'host. In questo modo, qualsiasi applicazione Android può emulare una carta e comunicare direttamente con il lettore NFC. Questo argomento descrive il funzionamento dell'emulazione di carte basata su host (HCE) su Android e come puoi sviluppare un'app che emula una carta NFC utilizzando questa tecnica.

Emulazione della carta con un elemento sicuro

Quando l'emulazione della carta NFC viene fornita utilizzando un elemento sicuro, la carta da emulare viene configurata nell'elemento sicuro sul dispositivo tramite un'applicazione Android. Quando l'utente tiene il dispositivo sopra un terminale NFC, il controller NFC nel dispositivo inoltra tutti i dati dal lettore direttamente all'elemento di sicurezza. La Figura 1 illustra questo concetto:

Diagramma con un lettore NFC che passa attraverso un controller NFC per recuperare informazioni da un elemento sicuro
Figura 1. Emulazione di una carta NFC con un elemento sicuro.

L'elemento sicuro stesso esegue la comunicazione con il terminale NFC e nella transazione non è coinvolta alcuna applicazione Android. Al termine della transazione, un'applicazione Android può eseguire query sull'elemento sicuro direttamente per lo stato della transazione e inviare una notifica all'utente.

Emulazione di carte basata sull'host

Quando una carta NFC viene emulata utilizzando l'emulazione della carta basata sull'host, i dati vengono inoltrati direttamente alla CPU dell'host anziché a un elemento sicuro. La Figura 2 illustra il funzionamento dell'emulazione della carta basata sull'host:

Diagramma con il lettore NFC che passa attraverso un controller NFC per recuperare le informazioni dalla CPU
Figura 2. Emulazione di una carta NFC senza un elemento sicuro.

Carte e protocolli NFC supportati

Diagramma che mostra la pila di protocolli HCE
Figura 3. La pila di protocolli HCE di Android.

Gli standard NFC offrono il supporto di molti protocolli diversi e esistono diversi tipi di carte che puoi emulare.

Android 4.4 e versioni successive supportano diversi protocolli comuni oggi sul mercato. Molte carte contactless esistenti si basano già su questi protocolli, come le carte di pagamento contactless. Questi protocolli sono supportati anche da molti lettori NFC attualmente in commercio, inclusi i dispositivi NFC Android che funzionano come lettori (vedi la classe IsoDep). In questo modo puoi creare ed eseguire il deployment di una soluzione NFC end-to-end basata su HCE utilizzando solo dispositivi Android.

Nello specifico, Android 4.4 e versioni successive supportano l'emulazione di carte basate sulla specifica ISO-DEP del forum NFC (basata su ISO/IEC 14443-4) e gestiscono le unità di dati del protocollo di applicazione (APDU) come definito nella specifica ISO/IEC 7816-4. Android richiede l'emulazione di ISO-DEP solo sulla tecnologia Nfc-A (ISO/IEC 14443-3 di tipo A). Il supporto della tecnologia Nfc-B (ISO/IEC 14443-4 di tipo B) è facoltativo. La figura 3 illustra la stratificazione di tutte queste specifiche.

Servizi HCE

L'architettura HCE in Android si basa sui componenti Android Service (noti come servizi HCE). Uno dei principali vantaggi di un servizio è che può essere eseguito in background senza interfaccia utente. Questa è una soluzione ideale per molte applicazioni HCE, come le tessere fedeltà o per il trasporto pubblico, per le quali l'utente non deve avviare un'app. Se invece tocchi il dispositivo contro il lettore NFC, viene avviato il servizio corretto se non è già in esecuzione ed eseguito la transazione in background. Naturalmente, puoi scegliere di lanciare un'interfaccia utente aggiuntiva (ad esempio le notifiche utente) dal tuo servizio, se opportuno.

Selezione del servizio

Quando l'utente avvicina un dispositivo a un lettore NFC, il sistema Android deve sapere con quale servizio HCE vuole comunicare il lettore NFC. La specifica ISO/IEC 7816-4 definisce un modo per selezionare le applicazioni, incentrato su un ID applicazione (AID). Un AID è costituito da un massimo di 16 byte. Se stai emulando le carte per un'infrastruttura di lettori NFC esistente, gli AID che questi lettori cercano sono in genere ben noti e registrati pubblicamente (ad esempio gli AID delle reti di pagamento come Visa e MasterCard).

Se vuoi implementare una nuova infrastruttura di lettori per la tua applicazione, devi registrare i tuoi AID. La procedura di registrazione degli AID è definita nella specifica ISO/IEC 7816-5. Ti consigliamo di registrare un AID come da 7816-5 se stai implementando un'applicazione HCE per Android, in quanto evita collisioni con altre applicazioni.

Gruppi AID

In alcuni casi, un servizio HCE potrebbe dover registrare più AID ed essere impostato come gestore predefinito per tutti gli AID per implementare una determinata applicazione. Alcuni AID del gruppo che rimandano a un altro servizio non sono supportati.

Un elenco di AID raggruppati è chiamato gruppo AID. Per tutti gli AID in un gruppo AID, Android garantisce una delle seguenti opzioni:

  • Tutti gli AID del gruppo vengono indirizzati a questo servizio HCE.
  • Nessun AID del gruppo viene instradato a questo servizio HCE (ad esempio perché l'utente ha preferito un altro servizio che ha richiesto anche uno o più AID nel gruppo).

In altre parole, non esiste uno stato intermedio in cui alcuni AID del gruppo possono essere indirizzati a un servizio HCE e altri a un altro.

Gruppi e categorie di annunci adattabili

Puoi associare ogni gruppo AID a una categoria. In questo modo Android può raggruppare i servizi HCE per categoria e, a sua volta, l'utente può impostare le impostazioni predefinite a livello di categoria anziché a livello di AID. Evita di menzionare gli AID nelle parti della tua applicazione rivolte agli utenti, perché non hanno alcun significato per l'utente medio.

Android 4.4 e versioni successive supportano due categorie:

Implementare un servizio HCE

Per emulare una carta NFC utilizzando l'emulazione di carte basata su host, devi creare un componente Service che gestisca le transazioni NFC.

Verificare il supporto HCE

L'applicazione può verificare se un dispositivo supporta HCE controllando la funzionalità FEATURE_NFC_HOST_CARD_EMULATION. Utilizza il tag <uses-feature> nel file manifest della tua applicazione per dichiarare che la tua app utilizza la funzionalità HCE e se è necessaria o meno per il funzionamento dell'app.

Implementazione del servizio

Android 4.4 e versioni successive forniscono una comoda classe Service che puoi utilizzare come base per l'implementazione di un servizio HCE: la classe HostApduService.

Il primo passaggio consiste nell'estendere HostApduService, come mostrato nel seguente esempio di codice:

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 dichiara due metodi astratti che devi override e implementare. Uno di questi, processCommandApdu(), viene chiamato ogni volta che un lettore NFC invia un'unità di dati del protocollo di applicazione (APDU) al tuo servizio. Gli APDU sono definiti nella specifica ISO/IEC 7816-4. Gli APDU sono i pacchetti a livello di applicazione scambiati tra il lettore NFC e il tuo servizio HCE. Questo protocollo a livello di applicazione è half-duplex: il lettore NFC ti invia un comando APDU e attende che tu invii una risposta APDU.

Come accennato in precedenza, Android utilizza l'AID per determinare con quale servizio HCE il lettore vuole comunicare. In genere, il primo APDU inviato da un lettore NFC al tuo dispositivo è un APDU SELECT AID; questo APDU contiene l'AID con cui il lettore vuole comunicare. Android estrae l'AID dall'APDU, lo risolve in un servizio HCE e poi inoltra l'APDU al servizio risolto.

Puoi inviare un APDU di risposta restituendo i byte dell'APDU di risposta da processCommandApdu(). Tieni presente che questo metodo viene chiamato nel thread principale della tua applicazione, che non devi bloccare. Se non riesci a calcolare e restituire immediatamente un APDU di risposta, restituisci null. Puoi quindi eseguire le operazioni necessarie su un altro thread e utilizzare il metodo sendResponseApdu() definito nella classe HostApduService per inviare la risposta al termine.

Android continua a inoltrare nuovi APDU dal lettore al tuo servizio finché non si verifica uno dei seguenti eventi:

  • Il lettore NFC invia un altro APDU SELECT AID, che il sistema operativo risolve in un servizio diverso.
  • Il collegamento NFC tra il lettore NFC e il dispositivo è interrotto.

In entrambi i casi, l'implementazione della classe onDeactivated() viene chiamata con un argomento che indica quale delle due si è verificata.

Se utilizzi l'infrastruttura dei lettori esistente, devi implementare il protocollo a livello di applicazione esistente previsto dai lettori nel tuo servizio HCE.

Se stai implementando anche una nuova infrastruttura di lettori che controlli, puoi definire il tuo protocollo e la sequenza APDU. Cerca di limitare la quantità di APDU e le dimensioni dei dati da scambiare: in questo modo, gli utenti dovranno solo tenere il dispositivo sopra il lettore NFC per poco tempo. Un valore limite superiore ragionevole è di circa 1 KB di dati, che in genere possono essere scambiati entro 300 ms.

Dichiarazione del manifest del servizio e registrazione AID

Devi dichiarare il servizio nel file manifest come di consueto, ma devi anche aggiungere alcuni elementi aggiuntivi alla dichiarazione del servizio:

  1. Per indicare alla piattaforma che si tratta di un servizio HCE che implementa un'interfaccia HostApduService, aggiungi un filtro per intent per l'azione SERVICE_INTERFACE alla dichiarazione del servizio.

  2. Per indicare alla piattaforma quali gruppi di AID sono richiesti da questo servizio, includi un tag SERVICE_META_DATA <meta-data> nella dichiarazione del servizio, che rimandi a una risorsa XML con informazioni aggiuntive sul servizio HCE.

  3. Imposta l'attributo android:exported su true e richiedi l'autorizzazione android.permission.BIND_NFC_SERVICE nella dichiarazione del servizio. Il primo garantisce che il servizio possa essere associato da applicazioni esterne. Quest'ultimo impone che solo le applicazioni esterne che dispongono dell'autorizzazioneandroid.permission.BIND_NFC_SERVICE possano eseguire il binding al tuo servizio. Poiché android.permission.BIND_NFC_SERVICE è un'autorizzazione di sistema, viene effettivamente imposto che solo il sistema operativo Android possa associarsi al tuo servizio.

Di seguito è riportato un esempio di dichiarazione del file manifest di 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>

Questo tag dei metadati punta a un file apduservice.xml. Di seguito è riportato un esempio di un file di questo tipo con una singola dichiarazione di gruppo AID contenente due AID proprietari:

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

Il tag <host-apdu-service> deve contenere un attributo <android:description> che contiene una descrizione del servizio facile da comprendere che puoi mostrare nell'interfaccia utente dell'app. Puoi utilizzare l'attributo requireDeviceUnlock per specificare che il dispositivo è sbloccato prima di invocare questo servizio per gestire gli APDU.

<host-apdu-service> deve contenere uno o più tag <aid-group>. Ogni <aid-group> tag deve:

  • Contengono un attributo android:description che contiene una descrizione di facile utilizzo del gruppo AID, adatta per la visualizzazione nell'interfaccia utente.
  • Avere l'attributo android:category impostato per indicare la categoria a cui appartiene il gruppo AID, ad esempio le costanti di stringa definite da CATEGORY_PAYMENT o CATEGORY_OTHER.
  • Contengono uno o più tag <aid-filter>, ciascuno dei quali contiene un singolo AID. Specifica l'AID in formato esadecimale e assicurati che contenga un numero pari di caratteri.

L'applicazione deve inoltre disporre dell'autorizzazione NFC per la registrazione come servizio HCE.

Risoluzione dei conflitti AID

È possibile installare più componenti HostApduService su un singolo dispositivo e lo stesso AID può essere registrato da più servizi. Android determina quale servizio chiamare seguendo i seguenti passaggi:

  1. Se l'app wallet predefinita selezionata dall'utente ha registrato l'AID, viene richiamata questa app.
  2. Se l'app Wallet predefinita non ha registrato l'AID, viene invocato il servizio che lo ha registrato.
  3. Se più di un servizio ha registrato l'AID, Android chiede all'utente quale servizio chiamare.

Preferenza per i servizi in primo piano

Le app in primo piano possono richiamare setPreferredService per specificare quale servizio di emulazione delle carte deve essere preferito quando un'attività specifica è in primo piano. Questa preferenza per le app in primo piano sostituisce la risoluzione dei conflitti AID. Questa è la pratica consigliata quando l'app prevede che l'utente possa utilizzare l'emulazione della carta NFC.

Android 13 e versioni successive

Per adattare meglio l'elenco di selezione dei pagamenti predefiniti nell'interfaccia utente delle impostazioni, modifica il requisito del banner in un'icona quadrata. Idealmente, dovrebbe essere identico al design dell'icona del programma di avvio. Questo aggiustamento crea più coerenza e un aspetto più pulito.

Android 12 e versioni precedenti

Imposta le dimensioni del banner del servizio su 260 x 96 dp, quindi imposta le dimensioni del banner del servizio nel file XML dei metadati aggiungendo l'attributo android:apduServiceBanner al tag <host-apdu-service> che rimanda alla risorsa drawable. Di seguito è riportato un esempio:

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

Applicazioni Wallet

Android 15 e versioni successive includono un ruolo predefinito per l'app Wallet che l'utente può selezionare andando a Impostazioni > App > App predefinite. Definisce l'applicazione Wallet predefinita da richiamare quando viene toccato un terminale di pagamento. Android considera come app di portafoglio i servizi HCE che hanno dichiarato un gruppo AID con la categoria di pagamento.

Controllare se la tua app è l'app Wallet predefinita

Le app possono verificare se sono l'app Wallet predefinita passando RoleManager.ROLE_WALLET a RoleManager.isRoleHeld().

Se la tua app non è quella predefinita, puoi richiedere il ruolo del portafoglio predefinito passando RoleManager.ROLE_WALLET a RoleManager.createRequestRoleIntent().

Asset obbligatori per le applicazioni Wallet

Per offrire un'esperienza utente più accattivante, le applicazioni wallet HCE devono fornire un banner di servizio.

Modalità di osservazione

Android 15 introduce la funzionalità Modalità di osservazione. Se abilitata, la modalità di osservazione consente al dispositivo di osservare i loop di polling NFC e di inviare notifiche al riguardo ai componenti HostApduService appropriati in modo che possano prepararsi a interagire con un determinato terminale NFC. Un HostApduService può mettere il dispositivo in modalità di monitoraggio passando true a setObserveModeEnabled(). Questo indica allo stack NFC di non consentire transazioni NFC e di osservare passivamente i loop di polling.

Filtri del ciclo di polling

Puoi registrare i filtri del loop di polling per un HostApduService utilizzando uno dei seguenti metodi:

Quando un filtro del loop di polling corrisponde a frame di polling non standard, lo stack NFC indirizza questi frame di polling all'HostApduService corrispondente chiamando il relativo metodo processPollingFrames(). In questo modo, il servizio può adottare tutti i passaggi necessari per assicurarsi che l'utente sia pronto a effettuare transazioni e intenda farlo, ad esempio autenticandolo. Se un lettore NFC utilizza solo frame standard nel proprio loop di polling, la pila NFC inoltra questi frame di polling al servizio in primo piano preferito se questo servizio è in primo piano o al detentore del ruolo del portafoglio predefinito.

Le notifiche del frame di polling includono anche una misurazione specifica del fornitore dell'intensità del campo che puoi recuperare chiamando getVendorSpecificGain(). I fornitori possono fornire misurazioni utilizzando la propria scala, purché rientrino in un singolo byte.

Rispondere ai loop di polling ed uscire dalla modalità di osservazione

Quando il servizio è pronto per effettuare transazioni, può uscire dalla modalità di osservazione passando false a setObserveModeEnabled(). Lo stack NFC consentirà quindi alle transazioni di procedere.

I componenti HostApduService possono indicare che la modalità di osservazione deve essere attivata ogni volta che sono il servizio di pagamento preferito impostando shouldDefaultToObserveMode su true nel manifest o chiamando CardEmulation.setShouldDefaultToObserveModeForService().

I componenti HostApduService e OffHostApduService possono anche indicare che i filtri del loop di polling che corrispondono ai frame del loop di polling ricevuti devono disattivare automaticamente la modalità di osservazione e consentire il proseguimento delle transazioni impostando autoTransact su true nella dichiarazione PollingLoopFilter nel manifest.

Preferenza per i servizi in primo piano

Le app in primo piano possono richiamare setPreferredService per specificare quale servizio di emulazione delle carte deve essere preferito quando un'attività specifica è in primo piano. Questa preferenza per le app in primo piano sostituisce lo stato della modalità di osservazione del dispositivo corrispondente al valore di shouldDefaultToObserveMode per un determinato servizio, che può essere impostato in uno dei seguenti modi:

Comportamento con lo schermo spento e nella schermata di blocco

Il comportamento dei servizi HCE varia in base alla versione di Android in esecuzione sul dispositivo.

Android 15 e versioni successive

Se l'app Wallet predefinita attiva la modalità di osservazione su un dispositivo che la supporta, l'app sostituisce il comportamento di sblocco e di spegnimento dello schermo, perché controlla quando può procedere una transazione. Alcune app di portafoglio potrebbero richiedere lo sblocco del dispositivo prima che una transazione possa essere eseguita se la modalità di osservazione non ha rilevato un pattern di loop di polling identificabile.

Gli sviluppatori sono invitati a utilizzare i propri dispositivi di lettura per emettere pattern di loop di polling identificabili e registrarsi per gestirli dalla propria app.

Android 12 e versioni successive

Nelle app che hanno come target Android 12 (livello API 31) e versioni successive, puoi attivare i pagamenti NFC senza che lo schermo del dispositivo sia acceso impostando requireDeviceScreenOn su false.

Android 10 e versioni successive

I dispositivi con Android 10 (livello API 29) o versioni successive supportano NFC sicuro. Quando l'NFC sicuro è attivo, tutti gli emulatori di carte (applicazioni host e off-host) non sono disponibili quando lo schermo del dispositivo è spento. Quando l'NFC sicuro è disattivato, le applicazioni off-host sono disponibili quando lo schermo del dispositivo è spento. Puoi verificare il supporto dell'NFC sicuro utilizzando isSecureNfcSupported().

Sui dispositivi con Android 10 e versioni successive, si applica la stessa funzionalità per l'impostazione di android:requireDeviceUnlock su true come per i dispositivi con Android 9 e versioni precedenti, ma solo se il protocollo NFC sicuro è disattivato. In altre parole, se il protocollo NFC sicuro è attivo, i servizi HCE non possono funzionare dalla schermata di blocco indipendentemente dall'impostazione di android:requireDeviceUnlock.

Android 9 e versioni precedenti

Sui dispositivi con Android 9 (livello API 28) e versioni precedenti, il controller NFC e l'elaborazione delle applicazioni vengono disattivati completamente quando lo schermo del dispositivo è spento. Pertanto, i servizi HCE non funzionano quando lo schermo è spento.

Anche su Android 9 e versioni precedenti, i servizi HCE possono funzionare dalla schermata di blocco. Tuttavia, questo valore è controllato dall'attributo android:requireDeviceUnlock nel tag <host-apdu-service> del servizio HCE. Per impostazione predefinita, lo sblocco del dispositivo non è obbligatorio e il servizio viene richiamato anche se il dispositivo è bloccato.

Se imposti l'attributo android:requireDeviceUnlock su true per il tuo servizio HCE, Android chiede all'utente di sbloccare il dispositivo quando si verificano le seguenti condizioni:

  • L'utente tocca un lettore NFC.
  • Il lettore NFC seleziona un AID risolto nel tuo servizio.

Dopo lo sblocco, Android mostra una finestra di dialogo che chiede all'utente di toccare di nuovo per completare la transazione. Questo è necessario perché l'utente potrebbe aver allontanato il dispositivo dal lettore NFC per sbloccarlo.

Coesistenza con le carte con Secure Element

Questa sezione è di interesse per gli sviluppatori che hanno implementato un'applicazione che si basa su un elemento sicuro per l'emulazione della carta. L'implementazione HCE di Android è progettata per funzionare in parallelo con altri metodi di implementazione dell'emulazione della carta, incluso l'utilizzo di elementi sicuri.

Questa coesistenza si basa su un principio chiamato indirizzamento AID. Il controller NFC mantiene una tabella di routing costituita da un elenco (finito) di regole di routing. Ogni regola di routing contiene un AID e una destinazione. La destinazione può essere la CPU host, su cui sono in esecuzione le app per Android, o un elemento protetto collegato.

Quando il lettore NFC invia un APDU con un SELECT AID, il controller NFC lo analizza e controlla se gli AID corrispondono a quelli presenti nella tabella di routing. Se la corrispondenza viene trovata, l'APDU e tutte le APDU successive vengono inviate alla destinazione associata all'AID, fino a quando non viene ricevuta un'altra APDU SELECT AID o il link NFC viene interrotto.

La Figura 4 illustra questa architettura:

Diagramma con il lettore NFC che comunica sia con un elemento sicuro sia con la CPU
Figura 4. Android che funziona sia con il secure element sia con l'emulazione della carta host.

In genere, il controller NFC contiene anche una route predefinita per gli APDU. Quando un ID annuncio non viene trovato nella tabella di routing, viene utilizzata la route predefinita. Sebbene questa impostazione possa variare da un dispositivo all'altro, i dispositivi Android devono assicurarsi che gli AID registrati dalla tua app vengano instradati correttamente all' host.

Le applicazioni Android che implementano un servizio HCE o che utilizzano un elemento di sicurezza non devono preoccuparsi di configurare la tabella di routing, poiché viene gestita automaticamente da Android. Android deve solo sapere quali AID possono essere gestiti dai servizi HCE e quali dall'elemento sicuro. La tabella di routing viene configurata automaticamente in base ai servizi installati e a quelli configurati dall'utente come preferiti.

La sezione seguente spiega come dichiarare gli AID per le applicazioni che utilizzano un elemento di sicurezza per l'emulazione della carta.

Registrazione AID del Secure Element

Le applicazioni che utilizzano un elemento sicuro per l'emulazione della carta possono dichiarare un servizio off-host nel file manifest. La dichiarazione di un servizio di questo tipo è quasi identica alla dichiarazione di un servizio HCE. Le eccezioni sono riportate di seguito:

  • L'azione utilizzata nel filtro per intent deve essere impostata su SERVICE_INTERFACE.
  • L'attributo del nome dei metadati deve essere impostato su SERVICE_META_DATA.
  • Il file XML dei metadati deve utilizzare il tag principale <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>

Di seguito è riportato un esempio del file apduservice.xml corrispondente che registra due 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>

L'attributo android:requireDeviceUnlock non si applica ai servizi off-host, perché la CPU dell'host non è coinvolta nella transazione e pertanto non può impedire all'elemento sicuro di eseguire transazioni quando il dispositivo è bloccato.

L'attributo android:apduServiceBanner è obbligatorio per i servizi off-host che sono applicazioni di pagamento e per essere selezionabili come applicazioni di pagamento predefinite.

Invocazione di servizi off-host

Android non avvia né si lega mai a un servizio dichiarato come "off-host", perché le transazioni effettive vengono eseguite dall'elemento di sicurezza e non dal servizio Android. La dichiarazione di servizio consente semplicemente alle applicazioni di registrare gli AID presenti nel secure element.

HCE e sicurezza

L'architettura HCE fornisce un elemento di sicurezza fondamentale: poiché il servizio è protetto dall'autorizzazione di sistema BIND_NFC_SERVICE, solo il sistema operativo può associarsi al servizio e comunicare con esso. In questo modo, qualsiasi APDU che ricevi è effettivamente un APDU ricevuto dal sistema operativo dal controller NFC e qualsiasi APDU che invii viene inviato solo al sistema operativo, che a sua volta inoltra direttamente le APDU al controller NFC.

L'ultimo problema riguarda la fonte dei dati inviati dall'app al lettore NFC. Questo è intenzionalmente disaccoppiato nel design HCE; non è importante da dove provengono i dati, ma solo che vengano trasportati in sicurezza al controller NFC e al lettore NFC.

Per archiviare e recuperare in modo sicuro i dati che vuoi inviare dal tuo servizio HCE, puoi, ad esempio, fare affidamento sulla sandbox delle applicazioni Android, che isola i dati della tua app da quelli di altre app. Per ulteriori dettagli sulla sicurezza di Android, leggi i suggerimenti per la sicurezza.

Parametri e dettagli del protocollo

Questa sezione è di interesse per gli sviluppatori che vogliono capire quali parametri di protocollo vengono utilizzati dai dispositivi HCE durante le fasi di anticollisione e attivazione dei protocolli NFC. In questo modo è possibile creare un'infrastruttura di lettori compatibile con i dispositivi Android HCE.

Protocollo NFC-A (ISO/IEC 14443 tipo A) anticollisione e attivazione

Nell'ambito dell'attivazione del protocollo Nfc-A vengono scambiati più frame.

Nella prima parte dello scambio, il dispositivo HCE presenta il proprio UID. Si deve presumere che i dispositivi HCE abbiano un UID casuale. Ciò significa che a ogni tocco, l'UID presentato al lettore è un UID generato in modo casuale. Per questo motivo, i lettori NFC non devono dipendere dall'UID dei dispositivi HCE come forma di autenticazione o identificazione.

Il lettore NFC può quindi selezionare il dispositivo HCE inviando un comando SEL_REQ. La risposta SEL_RES del dispositivo HCE ha almeno il 6° bit impostato (0x20), a indicare che il dispositivo supporta ISO-DEP. Tieni presente che potrebbero essere impostati anche altri bit in SEL_RES, ad esempio per indicare il supporto del protocollo NFC-DEP (p2p). Poiché potrebbero essere impostati altri bit, i lettori che vogliono interagire con i dispositivi HCE devono controllare esplicitamente solo il sesto bit e non confrontare il SEL_RES completo con un valore di 0x20.

Attivazione ISO-DEP

Dopo l'attivazione del protocollo Nfc-A, il lettore NFC avvia l'attivazione del protocollo ISO-DEP. Invia un comando RATS (Request for Answer To Select). Il controller NFC genera la risposta RATS, l'ATS; l'ATS non è configurabile dai servizi HCE. Tuttavia, le implementazioni HCE devono soddisfare i requisiti del Forum NFC per la risposta ATS, in modo che i lettori NFC possano contare su questi parametri impostati in conformità con i requisiti del Forum NFC per qualsiasi dispositivo HCE.

La sezione seguente fornisce ulteriori dettagli sui singoli byte della risposta ATS fornita dal controller NFC su un dispositivo HCE:

  • TL: lunghezza della risposta dell'ATS. Non deve indicare una lunghezza superiore a 20 byte.
  • T0: i bit 5, 6 e 7 devono essere impostati su tutti i dispositivi HCE, a indicare che TA(1), TB(1) e TC(1) sono inclusi nella risposta ATS. I bit da 1 a 4 indicano l'FSCI, che codifica le dimensioni massime del frame. Sui dispositivi HCE, il valore di FSCI deve essere compreso tra 0 e 8 ore.
  • T(A)1: definisce le velocità in bit tra il lettore e l'emulatore e se possono essere asimmetriche. Non sono previsti requisiti o garanzie per la velocità in bit per i dispositivi HCE.
  • T(B)1: i bit da 1 a 4 indicano l'intero tempo di guardia del frame di avvio (SFGI). Sui dispositivi HCE, il valore SFGI deve essere <= 8 ore. I bit da 5 a 8 indicano il numero intero del tempo di attesa del frame (FWI) e codificano il tempo di attesa del frame (FWT). Sui dispositivi HCE, il valore FWI deve essere <= 8 ore.
  • T(C)1: il bit 5 indica il supporto delle "Funzionalità del protocollo avanzato". I dispositivi HCE possono supportare o meno le "funzionalità del protocollo avanzato". Il bit 2 indica il supporto per DID. I dispositivi HCE possono supportare o meno i DID. Il bit 1 indica il supporto per NAD. I dispositivi HCE non devono supportare NAD e impostare il bit 1 su zero.
  • Byte storici: i dispositivi HCE possono restituire fino a 15 byte storici. I lettori NFC che vogliono interagire con i servizi HCE non devono fare supposizioni sui contenuti dei byte storici o sulla loro presenza.

Tieni presente che molti dispositivi HCE sono probabilmente conformi ai requisiti di protocollo che le reti di pagamento unite in EMVCo hanno specificato nella loro specifica "Protocollo di comunicazione contactless". In particolare:

  • Il valore FSCI in T0 deve essere compreso tra 2 e 8 ore.
  • T(A)1 deve essere impostato su 0x80, a indicare che è supportata solo la velocità in bit di 106 kbit/s e che le velocità in bit asimmetriche tra lettore ed emulatore non sono supportate.
  • Il tempo di primo contatto in T(B)1 deve essere <= 7 ore.

Scambio di dati APDU

Come indicato in precedenza, le implementazioni HCE supportano un solo canale logico. Il tentativo di selezionare applicazioni su canali logici diversi non funziona su un dispositivo HCE.