am 987ac90d: am ed8d921a: am eec66178: am 73c1681b: Merge "Docs: Clean up HCE dev guide" into klp-docs

* commit '987ac90d60b8a0b5ae909ce80b5234c1e5c41068':
  Docs: Clean up HCE dev guide
This commit is contained in:
Trevor Johns
2013-12-16 23:05:48 +00:00
committed by Android Git Automerger

View File

@ -118,7 +118,7 @@ sense.</p>
<h3 id="ServiceSelection">Service selection</h3>
<p>When the user taps a device to an NFC reader, the Android system needs to
know which HCE service the NFC reader actually wants to talk to.
know which HCE service the NFC reader actually wants to talk to.
This is where the ISO/IEC 7816-4 specification comes in: it defines a way to
select applications, centered around an Application ID (AID). An AID
consists of up to 16 bytes. If you are emulating cards for an existing NFC reader
@ -163,11 +163,17 @@ mentioning AIDs in any user-facing parts of your application: they do not mean
anything to the average user.</p>
<p>Android 4.4 supports two categories: {@link
android.nfc.cardemulation.CardEmulation#CATEGORY_PAYMENT} (covering payment
android.nfc.cardemulation.CardEmulation#CATEGORY_PAYMENT} (covering industry-standard payment
apps) and {@link android.nfc.cardemulation.CardEmulation#CATEGORY_OTHER}
(for all other HCE apps).</p>
<div class="note">
<p><strong>Note:</strong>
Only one AID group in the {@link
android.nfc.cardemulation.CardEmulation#CATEGORY_PAYMENT} category may be enabled in the system at any given time. Typically, this will be an app that understands major credit card payment protcols and which can work at any merchant.</p>
<p>For <em>closed-loop</em> payment apps that only work at one merchant (such as stored-value cards), you should use {@link
android.nfc.cardemulation.CardEmulation#CATEGORY_OTHER}. AID groups in this category can be always active, and can be given priority by NFC readers during AID selection if necessary.</p>
</div>
<h2 id="ImplementingService">Implementing an HCE Service</h2>
@ -178,7 +184,7 @@ apps) and {@link android.nfc.cardemulation.CardEmulation#CATEGORY_OTHER}
<p>Your application can check whether a device supports HCE by checking for the
{@link android.content.pm.PackageManager#FEATURE_NFC_HOST_CARD_EMULATION} feature. You should use the
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature>}</a> tag in the manifest of your application to declare that your app
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a> tag in the manifest of your application to declare that your app
uses the HCE feature, and whether it is required for the app to function or not.</p>
<h3 id="ServiceImplementation">Service implementation</h3>
@ -205,7 +211,7 @@ public class MyHostApduService extends HostApduService {
declares two abstract methods that need to be overridden and implemented.</p>
<p>{@link android.nfc.cardemulation.HostApduService#processCommandApdu processCommandApdu()}
is called whenever a NFC reader sends an Application
is called whenever a NFC reader sends an Application
Protocol Data Unit (APDU) to your service. APDUs are defined in the ISO/IEC
7816-4 specification as well. APDUs are the application-level packets being
exchanged between the NFC reader and your HCE service. That application-level
@ -230,8 +236,7 @@ then forwards that APDU to the resolved service.</p>
Note that this method will be called on the main thread of
your application, which shouldn't be blocked. So if you can't compute and return
a response APDU immediately, return null. You can then do the necessary work on
another thread, and use the {@link android.nfc.cardemulation.HostApduService#sendResponseApdu
sendResponseApdu()} method defined
another thread, and use the {@link android.nfc.cardemulation.HostApduService#sendResponseApdu sendResponseApdu()} method defined
in the {@link android.nfc.cardemulation.HostApduService} class to send the response when you are done.</p>
<p>Android will keep forwarding new APDUs from the reader to your service, until
@ -244,8 +249,8 @@ different service;</li>
</ol>
<p>In both of these cases, your class's
{@link android.nfc.cardemulation.HostApduService#onDeactivated onDeactivated()}
implementation is
{@link android.nfc.cardemulation.HostApduService#onDeactivated onDeactivated()}
implementation is
called with an argument indicating which of the two happened.</p>
<p>If you are working with existing reader infrastructure, you need to
@ -272,7 +277,7 @@ intent filter for the {@link android.nfc.cardemulation.HostApduService#SERVICE_I
<p>Additionally, to tell the platform which AIDs groups are requested by this
service, a {@link android.nfc.cardemulation.HostApduService#SERVICE_META_DATA}
<code>&lt;meta-data></code> tag must be included in
<code>&lt;meta-data&gt;</code> tag must be included in
the declaration of the service, pointing to an XML resource with additional
information about the HCE service.</p>
@ -280,21 +285,21 @@ information about the HCE service.</p>
{@code "android.permission.BIND_NFC_SERVICE"} permission in your service declaration.
The former ensures that the service can be bound to by external applications.
The latter then enforces that only external applications that hold the
{@code ""android.permission.BIND_NFC_SERVICE"} permission can bind to your service. Since
{@code ""android.permission.BIND_NFC_SERVICE"} is a system permission, this effectively
{@code "android.permission.BIND_NFC_SERVICE"} permission can bind to your service. Since
{@code "android.permission.BIND_NFC_SERVICE"} is a system permission, this effectively
enforces that only the Android OS can bind to your service. </p>
<p>Here's an example of a {@link android.nfc.cardemulation.HostApduService} manifest declaration:</p>
<pre>
&lt;service android:name=".MyHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
&lt;intent-filter>
&lt;action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
&lt;/intent-filter>
android:permission="android.permission.BIND_NFC_SERVICE"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/&gt;
&lt;/intent-filter&gt;
&lt;meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice"/>
&lt;/service>
android:resource="@xml/apduservice"/&gt;
&lt;/service&gt;
</pre>
<p>This meta-data tag points to an {@code apduservice.xml} file. An example of such a file
@ -304,50 +309,52 @@ below:</p>
<pre>
&lt;host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc"
android:requireDeviceUnlock="false">
android:requireDeviceUnlock="false"&gt;
&lt;aid-group android:description="@string/aiddescription"
android:category="other">
&lt;aid-filter android:name="F0010203040506"/>
&lt;aid-filter android:name="F0394148148100"/>
&lt;/aid-group>
&lt;/host-apdu-service>
android:category="other"&gt;
&lt;aid-filter android:name="F0010203040506"/&gt;
&lt;aid-filter android:name="F0394148148100"/&gt;
&lt;/aid-group&gt;
&lt;/host-apdu-service&gt;
</pre>
<p>The <code>&lt;host-apdu-service></code> tag is required to contain a <code>&lt;android:description></code>
<p>The <code>&lt;host-apdu-service&gt;</code> tag is required to contain a <code>&lt;android:description&gt;</code>
attribute that contains a user-friendly description of the service that may be
shown in UI. The <code>&lt;requireDeviceUnlock></code> attribute can be used to specify that the
shown in UI. The <code>requireDeviceUnlock</code> attribute can be used to specify that the
device must be unlocked before this service can be invoked to handle APDUs.</p>
<p>The <code>&lt;host-apdu-service></code> must contain one or more <code>&lt;aid-group></code> tags. Each
<code>&lt;aid-group></code> tag is required to contain a <code>android:description</code> attribute that
contains a user-friendly description of the AID group that may be shown in UI.
Each <code>&lt;aid-group></code> tag must also have the android:category attribute set to
<p>The <code>&lt;host-apdu-service&gt;</code> must contain one or more <code>&lt;aid-group&gt;</code> tags. Each
<code>&lt;aid-group&gt;</code> tag is required to:</p>
<ul>
<li>Contain an <code>android:description</code> attribute that
contains a user-friendly description of the AID group, suitable for display in UI.</li>
<li>Have its <code>android:category</code> attribute set to
indicate the category the AID group belongs to, e.g. the string constants
defined by CardEmulation.CATEGORY_PAYMENT or CardEmulation.CATEGORY_OTHER. Each
<code>&lt;aid-group></code> must contain one or more <code>&lt;aid-filter></code> tags, each of which contains a
single AID. The AID must be specified in hexadecimal format, and contain an even
number of characters.</p>
<p>As a final note, your application also needs to hold the NFC permission,
{@link android.Manifest.permission#NFC} to be able to register as a HCE service.</p>
defined by {@link android.nfc.cardemulation.CardEmulation#CATEGORY_PAYMENT}
or {@link android.nfc.cardemulation.CardEmulation#CATEGORY_OTHER}.</li>
<li>Each <code>&lt;aid-group&gt;</code> must contain one or more
<code>&lt;aid-filter&gt;</code> tags, each of which contains a single AID. The AID
must be specified in hexadecimal format, and contain an even number of characters.</li>
</ul>
<p>As a final note, your application also needs to hold the
{@link android.Manifest.permission#NFC} permission to be able to register as a HCE service.</p>
<h2 id="AidConflicts">AID Conflict Resolution</h2>
<p>Multiple {@link android.nfc.cardemulation.HostApduService} components
may be installed on a single device, and the same AID
may be installed on a single device, and the same AID
can be registered by more than one service. The Android platform resolves AID
conflicts depending on which category an AID belongs to. Each category may have
a different conflict resolution policy. </p>
a different conflict resolution policy.</p>
<p>For example, for some categories (like payment) the user may be able to select a
default service in the Android settings UI. For other categories, the policy may
be to always ask the user which service is to be invoked in case of conflict. To
query the conflict resolution policy for a certain category, see
{@link android.nfc.cardemulation.CardEmulation#getSelectionModeForCategory
getSelectionModeForCategory()}.</p>
getSelectionModeForCategory()}.</p>
<h3 id="CheckingIfDefault">Checking if your service is the default</h3>
@ -358,8 +365,6 @@ certain category by using the
<p>If your service is not the default, you can request it to be made the default.
See {@link android.nfc.cardemulation.CardEmulation#ACTION_CHANGE_DEFAULT}.</p>
<h2 id="PaymentApps">Payment Applications</h2>
<p>Android considers HCE services that have declared an AID group with the
@ -376,20 +381,20 @@ service banner.</p>
<p>This asset should be sized 260x96 dp, and can be specified in your meta-data XML
file by adding the <code>android:apduServiceBanner</code> attribute to the
<code>&lt;host-apdu-service></code> tag, which points to the drawable resource. An example is
<code>&lt;host-apdu-service&gt;</code> tag, which points to the drawable resource. An example is
shown below:</p>
<pre>
&lt;host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc"
android:requireDeviceUnlock="false"
android:apduServiceBanner="@drawable/my_banner">
android:apduServiceBanner="@drawable/my_banner"&gt;
&lt;aid-group android:description="@string/aiddescription"
android:category="payment">
&lt;aid-filter android:name="F0010203040506"/>
&lt;aid-filter android:name="F0394148148100"/>
&lt;/aid-group>
&lt;/host-apdu-service>
android:category="payment"&gt;
&lt;aid-filter android:name="F0010203040506"/&gt;
&lt;aid-filter android:name="F0394148148100"/&gt;
&lt;/aid-group&gt;
&lt;/host-apdu-service&gt;
</pre>
@ -401,11 +406,11 @@ processor off completely when the screen of the device is turned off. HCE
services will therefore not work when the screen is off.</p>
<p>HCE services can function from the lock-screen however: this is controlled by
the <code>android:requireDeviceUnlock</code> attribute in the <code>&lt;host-apdu-service></code> tag of your
the <code>android:requireDeviceUnlock</code> attribute in the <code>&lt;host-apdu-service&gt;</code> tag of your
HCE service. By default, device unlock is not required, and your service will be
invoked even if the device is locked.</p>
<p>If you set the <code>&lt;android:requireDeviceUnlock</code> attribute to "true" for your HCE
<p>If you set the <code>android:requireDeviceUnlock</code> attribute to "true" for your HCE
service, Android will prompt the user to unlock the device when you tap an NFC
reader that selects an AID that is resolved to your service. After unlocking,
Android will show a dialog prompting the user to tap again to complete the
@ -429,13 +434,13 @@ either be the host CPU (where Android apps are running), or a connected secure
element.</p>
<p>When the NFC reader sends an APDU with a "SELECT AID", the NFC controller parses
it and checks whether the AIDs matchesNo converter for: FOOTNOTE with any AID in
its routing table. If it matches, that APDU and all APDUs following it will be
sent to the destination associated with the AID, until another "SELECT AID" APDU
is received or the NFC link is broken.</p>
it and checks whether the AIDs matches with any AID in its routing table. If it
matches, that APDU and all APDUs following it will be sent to the destination
associated with the AID, until another "SELECT AID" APDU is received or the NFC
link is broken.</p>
<p class="note"><strong>Note:</strong>
While ISO/IEC 7816-4 defines the concept of “partial matches” as well, this is currently not supported by Android HCE devices.</p>
While ISO/IEC 7816-4 defines the concept of “partial matches” as well, this is currently not supported by Android HCE devices.</p>
<p>This architecture is illustrated in figure 4.</p>
@ -471,20 +476,20 @@ almost identical to the declaration of a HCE service. The exceptions are:</p>
<ul>
<li>The action used in the intent-filter must be set to
{@link android.nfc.cardemulation.OffHostApduService#SERVICE_INTERFACE}</li>
{@link android.nfc.cardemulation.OffHostApduService#SERVICE_INTERFACE}.</li>
<li>The meta-data name attribute must be set to
{@link android.nfc.cardemulation.OffHostApduService#SERVICE_META_DATA}</li>
<li><p>The meta-data XML file must use the <code>&lt;offhost-apdu-service></code> root tag</p>
{@link android.nfc.cardemulation.OffHostApduService#SERVICE_META_DATA}.</li>
<li><p>The meta-data XML file must use the <code>&lt;offhost-apdu-service&gt;</code> root tag.</p>
<pre>
&lt;service android:name=".MyOffHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
&lt;intent-filter>
&lt;action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/>
&lt;/intent-filter>
android:permission="android.permission.BIND_NFC_SERVICE"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/&gt;
&lt;/intent-filter&gt;
&lt;meta-data android:name="android.nfc.cardemulation.off_host_apdu_ervice"
android:resource="@xml/apduservice"/>
&lt;/service>
android:resource="@xml/apduservice"/&gt;
&lt;/service&gt;
</pre>
</li>
</ul>
@ -493,12 +498,12 @@ almost identical to the declaration of a HCE service. The exceptions are:</p>
<pre>
&lt;offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc">
&lt;aid-group android:description="@string/subscription" android:category="other">
&lt;aid-filter android:name="F0010203040506"/>
&lt;aid-filter android:name="F0394148148100"/>
&lt;/aid-group>
&lt;/offhost-apdu-service>
android:description="@string/servicedesc"&gt;
&lt;aid-group android:description="@string/subscription" android:category="other"&gt;
&lt;aid-filter android:name="F0010203040506"/&gt;
&lt;aid-filter android:name="F0394148148100"/&gt;
&lt;/aid-group&gt;
&lt;/offhost-apdu-service&gt;
</pre>
<p>The <code>android:requireDeviceUnlock</code> attribute does not apply to off host services,
@ -527,13 +532,13 @@ receive is actually an APDU that was received by the OS from the NFC controller,
and that any APDU you send back will only go to the OS, which in turn directly
forwards the APDUs to the NFC controller.</p>
<p>The core remaining piece is where you get the data from that you're sending back
<p>The core remaining piece is where you get your data that your app sends
to the NFC reader. This is intentionally decoupled in the HCE design: it does
not care where the data comes from, it just makes sure that it is safely
transported to the NFC controller and out to the NFC reader.</p>
<p>For securely storing and retrieving the data that you want to send from your HCE
service, you can for example rely on the Android Application Sandbox, which
service, you can, for example, rely on the Android Application Sandbox, which
isolates your app's data from other apps. For more details on Android security,
read
<a href="{@docRoot}training/articles/security-tips.html">Security Tips</a>
@ -542,8 +547,8 @@ read
<h2 id="ProtocolParams">Protocol parameters and details</h2>
<p>This section is of interest for developers that want to understand what protocol
parameters HCE devices use during the anti-collision and activations phases of
the NFC protocols. This allows them to build a reader infrastructure that is
parameters HCE devices use during the anti-collision and activation phases of
the NFC protocols. This allows building a reader infrastructure that is
compatible with Android HCE devices.</p>
<h3 id="AntiCollisionAct">Nfc-A (ISO/IEC 14443 type A) protocol anti-collision and activation</h3>