diff options
| -rw-r--r-- | api/current.txt | 9 | ||||
| -rw-r--r-- | core/java/android/nfc/INfcCardEmulation.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/nfc/NfcAdapter.java | 27 | ||||
| -rw-r--r-- | core/java/android/nfc/cardemulation/CardEmulation.java | 104 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 9 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 6 |
6 files changed, 154 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt index 2230e61dab59..0ac2c44141bc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -99,6 +99,7 @@ package android { field public static final String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS"; field public static final String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS"; field public static final String NFC = "android.permission.NFC"; + field public static final String NFC_PREFERRED_PAYMENT_INFO = "android.permission.NFC_PREFERRED_PAYMENT_INFO"; field public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT"; field public static final String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS"; field @Deprecated public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY"; @@ -30708,6 +30709,7 @@ package android.nfc { method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...); field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED"; field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; + field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED"; field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; field public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED"; field @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) public static final String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED"; @@ -30716,6 +30718,7 @@ package android.nfc { field public static final String EXTRA_DATA = "android.nfc.extra.DATA"; field public static final String EXTRA_ID = "android.nfc.extra.ID"; field public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; + field public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON"; field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME"; field public static final String EXTRA_TAG = "android.nfc.extra.TAG"; @@ -30726,6 +30729,9 @@ package android.nfc { field public static final int FLAG_READER_NFC_V = 8; // 0x8 field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100 field public static final int FLAG_READER_SKIP_NDEF_CHECK = 128; // 0x80 + field public static final int PREFERRED_PAYMENT_CHANGED = 2; // 0x2 + field public static final int PREFERRED_PAYMENT_LOADED = 1; // 0x1 + field public static final int PREFERRED_PAYMENT_UPDATED = 3; // 0x3 field public static final int STATE_OFF = 1; // 0x1 field public static final int STATE_ON = 3; // 0x3 field public static final int STATE_TURNING_OFF = 4; // 0x4 @@ -30781,8 +30787,11 @@ package android.nfc.cardemulation { public final class CardEmulation { method public boolean categoryAllowsForegroundPreference(String); + method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService(); method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String); + method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getDescriptionForPreferredPaymentService(); method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter); + method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService(); method public int getSelectionModeForCategory(String); method public boolean isDefaultServiceForAid(android.content.ComponentName, String); method public boolean isDefaultServiceForCategory(android.content.ComponentName, String); diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl index dd2c0d4f9ee5..848b6d52c47f 100644 --- a/core/java/android/nfc/INfcCardEmulation.aidl +++ b/core/java/android/nfc/INfcCardEmulation.aidl @@ -39,4 +39,5 @@ interface INfcCardEmulation boolean setPreferredService(in ComponentName service); boolean unsetPreferredService(); boolean supportsAidPrefixRegistration(); + ApduServiceInfo getPreferredPaymentService(int userHandle); } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index bc698f97738a..7ab984fc9275 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -151,7 +151,7 @@ public final class NfcAdapter { public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; /** - * Broadcast Action: Intent to notify an application that an transaction event has occurred + * Broadcast Action: Intent to notify an application that a transaction event has occurred * on the Secure Element. * * <p>This intent will only be sent if the application has requested permission for @@ -164,6 +164,18 @@ public final class NfcAdapter { "android.nfc.action.TRANSACTION_DETECTED"; /** + * Broadcast Action: Intent to notify if the preferred payment service changed. + * + * <p>This intent will only be sent to the application has requested permission for + * {@link android.Manifest.permission#NFC_PREFERRED_PAYMENT_INFO} and if the application + * has the necessary access to Secure Element which witnessed the particular event. + */ + @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PREFERRED_PAYMENT_CHANGED = + "android.nfc.action.PREFERRED_PAYMENT_CHANGED"; + + /** * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED * @hide */ @@ -231,6 +243,17 @@ public final class NfcAdapter { */ public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME"; + /** + * Mandatory String extra field in {@link #ACTION_PREFERRED_PAYMENT_CHANGED} + * Indicates the condition when trigger this event. + */ + public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = + "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON"; + + public static final int PREFERRED_PAYMENT_LOADED = 1; + public static final int PREFERRED_PAYMENT_CHANGED = 2; + public static final int PREFERRED_PAYMENT_UPDATED = 3; + public static final int STATE_OFF = 1; public static final int STATE_TURNING_ON = 2; public static final int STATE_ON = 3; @@ -1410,7 +1433,7 @@ public final class NfcAdapter { /** * Enable foreground dispatch to the given Activity. * - * <p>This will give give priority to the foreground activity when + * <p>This will give priority to the foreground activity when * dispatching a discovered {@link Tag} to an application. * * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index aa93611062f5..f1c74a6331c4 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -17,6 +17,7 @@ package android.nfc.cardemulation; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -657,6 +658,109 @@ public final class CardEmulation { } /** + * Retrieves the registered AIDs for the preferred payment service. + * + * @return The list of AIDs registered for this category, or null if it couldn't be found. + */ + @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) + @Nullable + public List<String> getAidsForPreferredPaymentService() { + try { + ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId()); + return (serviceInfo != null ? serviceInfo.getAids() : null); + } catch (RemoteException e) { + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return null; + } + try { + ApduServiceInfo serviceInfo = + sService.getPreferredPaymentService(mContext.getUserId()); + return (serviceInfo != null ? serviceInfo.getAids() : null); + } catch (RemoteException ee) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return null; + } + } + } + + /** + * Retrieves the route destination for the preferred payment service. + * + * @return The route destination secure element name of the preferred payment service. + * HCE payment: "Host" + * OffHost payment: prefix SIM or prefix eSE string. + * "OffHost" if the payment service does not specify secure element + * name. + */ + @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) + @Nullable + public String getRouteDestinationForPreferredPaymentService() { + try { + ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId()); + if (serviceInfo != null) { + if (!serviceInfo.isOnHost()) { + return serviceInfo.getOffHostSecureElement() == null ? + "OffHost" : serviceInfo.getOffHostSecureElement(); + } + return "Host"; + } + return null; + } catch (RemoteException e) { + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return null; + } + try { + ApduServiceInfo serviceInfo = + sService.getPreferredPaymentService(mContext.getUserId()); + if (serviceInfo != null) { + if (!serviceInfo.isOnHost()) { + return serviceInfo.getOffHostSecureElement() == null ? + "Offhost" : serviceInfo.getOffHostSecureElement(); + } + return "Host"; + } + return null; + + } catch (RemoteException ee) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return null; + } + } + } + + /** + * Returns a user-visible description of the preferred payment service. + * + * @return the preferred payment service description + */ + @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) + @Nullable + public String getDescriptionForPreferredPaymentService() { + try { + ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId()); + return (serviceInfo != null ? serviceInfo.getDescription() : null); + } catch (RemoteException e) { + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return null; + } + try { + ApduServiceInfo serviceInfo = + sService.getPreferredPaymentService(mContext.getUserId()); + return (serviceInfo != null ? serviceInfo.getDescription() : null); + } catch (RemoteException ee) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return null; + } + } + } + + /** * @hide */ public boolean setDefaultServiceForCategory(ComponentName service, String category) { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 9ce29e35752e..31ac2bc7407f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -306,6 +306,7 @@ <protected-broadcast android:name="android.net.nsd.STATE_CHANGED" /> <protected-broadcast android:name="android.nfc.action.ADAPTER_STATE_CHANGED" /> + <protected-broadcast android:name="android.nfc.action.PREFERRED_PAYMENT_CHANGED" /> <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" /> <protected-broadcast android:name="com.android.nfc.action.LLCP_UP" /> <protected-broadcast android:name="com.android.nfc.action.LLCP_DOWN" /> @@ -1767,6 +1768,14 @@ <p>Protection level: normal --> <permission android:name="android.permission.NFC_TRANSACTION_EVENT" + android:protectionLevel="normal" /> + + <!-- Allows applications to receive NFC preferred payment service information. + <p>Protection level: normal + --> + <permission android:name="android.permission.NFC_PREFERRED_PAYMENT_INFO" + android:description="@string/permdesc_preferredPaymentInfo" + android:label="@string/permlab_preferredPaymentInfo" android:protectionLevel="normal" /> <!-- @deprecated This permission used to allow too broad access to sensitive methods and all its diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index fdfedea4bd13..4aa44fc6ebaa 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1392,6 +1392,12 @@ connections with paired devices.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_preferredPaymentInfo">Preferred NFC Payment Service Information</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_preferredPaymentInfo">Allows the app to get preferred nfc payment service information like + registered aids and route destination.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_nfc">control Near Field Communication</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_nfc">Allows the app to communicate |