Loading api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -15261,6 +15261,7 @@ package android.nfc.cardemulation { public final class CardEmulationManager { method public static synchronized android.nfc.cardemulation.CardEmulationManager getInstance(android.nfc.NfcAdapter); method public int getSelectionModeForCategory(java.lang.String); method public boolean isDefaultServiceForAid(android.content.ComponentName, java.lang.String); method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String); field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.ACTION_CHANGE_DEFAULT"; Loading @@ -15268,6 +15269,9 @@ package android.nfc.cardemulation { field public static final java.lang.String CATEGORY_PAYMENT = "payment"; field public static final java.lang.String EXTRA_CATEGORY = "category"; field public static final java.lang.String EXTRA_SERVICE_COMPONENT = "component"; field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1 field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2 field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0 } public abstract class HostApduService extends android.app.Service { core/java/android/nfc/cardemulation/ApduServiceInfo.java +18 −2 Original line number Diff line number Diff line Loading @@ -74,17 +74,23 @@ public final class ApduServiceInfo implements Parcelable { */ final HashMap<String, AidGroup> mCategoryToGroup; /** * Whether this service should only be started when the device is unlocked. */ final boolean mRequiresDeviceUnlock; /** * @hide */ public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, ArrayList<AidGroup> aidGroups) { ArrayList<AidGroup> aidGroups, boolean requiresUnlock) { this.mService = info; this.mDescription = description; this.mAidGroups = aidGroups; this.mAids = new ArrayList<String>(); this.mCategoryToGroup = new HashMap<String, AidGroup>(); this.mOnHost = onHost; this.mRequiresDeviceUnlock = requiresUnlock; for (AidGroup aidGroup : aidGroups) { this.mCategoryToGroup.put(aidGroup.category, aidGroup); this.mAids.addAll(aidGroup.aids); Loading Loading @@ -132,12 +138,16 @@ public final class ApduServiceInfo implements Parcelable { mService = info; mDescription = sa.getString( com.android.internal.R.styleable.HostApduService_description); mRequiresDeviceUnlock = sa.getBoolean( com.android.internal.R.styleable.HostApduService_requireDeviceUnlock, false); } else { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.OffHostApduService); mService = info; mDescription = sa.getString( com.android.internal.R.styleable.OffHostApduService_description); mRequiresDeviceUnlock = false; } mAidGroups = new ArrayList<AidGroup>(); Loading Loading @@ -226,6 +236,10 @@ public final class ApduServiceInfo implements Parcelable { return mOnHost; } public boolean requiresUnlock() { return mRequiresDeviceUnlock; } public CharSequence loadLabel(PackageManager pm) { return mService.loadLabel(pm); } Loading Loading @@ -287,6 +301,7 @@ public final class ApduServiceInfo implements Parcelable { if (mAidGroups.size() > 0) { dest.writeTypedList(mAidGroups); } dest.writeInt(mRequiresDeviceUnlock ? 1 : 0); }; public static final Parcelable.Creator<ApduServiceInfo> CREATOR = Loading @@ -301,7 +316,8 @@ public final class ApduServiceInfo implements Parcelable { if (numGroups > 0) { source.readTypedList(aidGroups, AidGroup.CREATOR); } return new ApduServiceInfo(info, onHost, description, aidGroups); boolean requiresUnlock = (source.readInt() != 0) ? true : false; return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock); } @Override Loading core/java/android/nfc/cardemulation/CardEmulationManager.java +93 −8 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.nfc.INfcCardEmulation; import android.nfc.NfcAdapter; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import java.util.HashMap; Loading Loading @@ -78,19 +79,68 @@ public final class CardEmulationManager { */ public static final String CATEGORY_OTHER = "other"; static boolean sIsInitialized = false; static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap(); static INfcCardEmulation sService; /** * Return value for {@link #getSelectionModeForCategory(String)}. * * <p>In this mode, the user has set a default service for this * AID category. If a remote reader selects any of the AIDs * that the default service has registered in this category, * that service will automatically be bound to to handle * the transaction. * * <p>There are still cases where a service that is * not the default for a category can selected: * <p> * If a remote reader selects an AID in this category * that is not handled by the default service, and there is a set * of other services {S} that do handle this AID, the * user is asked if he wants to use any of the services in * {S} instead. * <p> * As a special case, if the size of {S} is one, containing a single service X, * and all AIDs X has registered in this category are not * registered by any other service, then X will be * selected automatically without asking the user. * <p>Example: * <ul> * <li>Service A registers AIDs "1", "2" and "3" in the category * <li>Service B registers AIDs "3" and "4" in the category * <li>Service C registers AIDs "5" and "6" in the category * </ul> * In this case, the following will happen when service A * is the default: * <ul> * <li>Reader selects AID "1", "2" or "3": service A is invoked automatically * <li>Reader selects AID "4": the user is asked to confirm he * wants to use service B, because its AIDs overlap with service A. * <li>Reader selects AID "5" or "6": service C is invoked automatically, * because all AIDs it has asked for are only registered by C, * and there is no overlap. * </ul> * */ public static final int SELECTION_MODE_PREFER_DEFAULT = 0; /** * @hide * Return value for {@link #getSelectionModeForCategory(String)}. * * <p>In this mode, whenever an AID of this category is selected, * the user is asked which service he wants to use to handle * the transaction, even if there is only one matching service. */ public static final String PAYMENT_MODE_AUTO = "auto"; public static final int SELECTION_MODE_ALWAYS_ASK = 1; /** * @hide * Return value for {@link #getSelectionModeForCategory(String)}. * * <p>In this mode, the user will only be asked to select a service * if the selected AID has been registered by multiple applications. */ public static final String PAYMENT_MODE_MANUAL = "manual"; public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; static boolean sIsInitialized = false; static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap(); static INfcCardEmulation sService; final Context mContext; Loading @@ -113,7 +163,7 @@ public final class CardEmulationManager { throw new UnsupportedOperationException(); } try { if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) { if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) { Log.e(TAG, "This device does not support card emulation"); throw new UnsupportedOperationException(); } Loading @@ -137,6 +187,10 @@ public final class CardEmulationManager { * Allows an application to query whether a service is currently * the default service to handle a card emulation category. * * <p>Note that if {@link #getSelectionModeForCategory(String)} * returns {@link #SELECTION_MODE_ALWAYS_ASK}, this method will always * return false. * * @param service The ComponentName of the service * @param category The category * @return whether service is currently the default service for the category. Loading @@ -147,6 +201,10 @@ public final class CardEmulationManager { } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service, category); Loading Loading @@ -185,6 +243,33 @@ public final class CardEmulationManager { } } /** * Returns the application selection mode for the passed in category. * Valid return values are: * <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default * application for this category, which will be preferred. * <p>{@link #SELECTION_MODE_ALWAYS_ASK} the user has requested to be asked * every time what app he would like to use in this category. * <p>{@link #SELECTION_MODE_ASK_IF_CONFLICT} the user will only be asked * to pick a service if there is a conflict. * @param category The category, for example {@link #CATEGORY_PAYMENT} * @return */ public int getSelectionModeForCategory(String category) { if (CATEGORY_PAYMENT.equals(category)) { String defaultComponent = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT); if (defaultComponent != null) { return SELECTION_MODE_PREFER_DEFAULT; } else { return SELECTION_MODE_ALWAYS_ASK; } } else { // All other categories are in "only ask if conflict" mode return SELECTION_MODE_ASK_IF_CONFLICT; } } /** * @hide */ Loading core/java/android/nfc/cardemulation/HostApduService.java +0 −2 Original line number Diff line number Diff line Loading @@ -4,13 +4,11 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; Loading core/java/android/provider/Settings.java +0 −6 Original line number Diff line number Diff line Loading @@ -4284,12 +4284,6 @@ public final class Settings { */ public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component"; /** * Whether to automatically invoke NFC payment app or manually select on tap. * @hide */ public static final String NFC_PAYMENT_MODE = "nfc_payment_mode"; /** * Name of a package that the current user has explicitly allowed to see all of that * user's notifications. Loading Loading
api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -15261,6 +15261,7 @@ package android.nfc.cardemulation { public final class CardEmulationManager { method public static synchronized android.nfc.cardemulation.CardEmulationManager getInstance(android.nfc.NfcAdapter); method public int getSelectionModeForCategory(java.lang.String); method public boolean isDefaultServiceForAid(android.content.ComponentName, java.lang.String); method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String); field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.ACTION_CHANGE_DEFAULT"; Loading @@ -15268,6 +15269,9 @@ package android.nfc.cardemulation { field public static final java.lang.String CATEGORY_PAYMENT = "payment"; field public static final java.lang.String EXTRA_CATEGORY = "category"; field public static final java.lang.String EXTRA_SERVICE_COMPONENT = "component"; field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1 field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2 field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0 } public abstract class HostApduService extends android.app.Service {
core/java/android/nfc/cardemulation/ApduServiceInfo.java +18 −2 Original line number Diff line number Diff line Loading @@ -74,17 +74,23 @@ public final class ApduServiceInfo implements Parcelable { */ final HashMap<String, AidGroup> mCategoryToGroup; /** * Whether this service should only be started when the device is unlocked. */ final boolean mRequiresDeviceUnlock; /** * @hide */ public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, ArrayList<AidGroup> aidGroups) { ArrayList<AidGroup> aidGroups, boolean requiresUnlock) { this.mService = info; this.mDescription = description; this.mAidGroups = aidGroups; this.mAids = new ArrayList<String>(); this.mCategoryToGroup = new HashMap<String, AidGroup>(); this.mOnHost = onHost; this.mRequiresDeviceUnlock = requiresUnlock; for (AidGroup aidGroup : aidGroups) { this.mCategoryToGroup.put(aidGroup.category, aidGroup); this.mAids.addAll(aidGroup.aids); Loading Loading @@ -132,12 +138,16 @@ public final class ApduServiceInfo implements Parcelable { mService = info; mDescription = sa.getString( com.android.internal.R.styleable.HostApduService_description); mRequiresDeviceUnlock = sa.getBoolean( com.android.internal.R.styleable.HostApduService_requireDeviceUnlock, false); } else { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.OffHostApduService); mService = info; mDescription = sa.getString( com.android.internal.R.styleable.OffHostApduService_description); mRequiresDeviceUnlock = false; } mAidGroups = new ArrayList<AidGroup>(); Loading Loading @@ -226,6 +236,10 @@ public final class ApduServiceInfo implements Parcelable { return mOnHost; } public boolean requiresUnlock() { return mRequiresDeviceUnlock; } public CharSequence loadLabel(PackageManager pm) { return mService.loadLabel(pm); } Loading Loading @@ -287,6 +301,7 @@ public final class ApduServiceInfo implements Parcelable { if (mAidGroups.size() > 0) { dest.writeTypedList(mAidGroups); } dest.writeInt(mRequiresDeviceUnlock ? 1 : 0); }; public static final Parcelable.Creator<ApduServiceInfo> CREATOR = Loading @@ -301,7 +316,8 @@ public final class ApduServiceInfo implements Parcelable { if (numGroups > 0) { source.readTypedList(aidGroups, AidGroup.CREATOR); } return new ApduServiceInfo(info, onHost, description, aidGroups); boolean requiresUnlock = (source.readInt() != 0) ? true : false; return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock); } @Override Loading
core/java/android/nfc/cardemulation/CardEmulationManager.java +93 −8 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.nfc.INfcCardEmulation; import android.nfc.NfcAdapter; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import java.util.HashMap; Loading Loading @@ -78,19 +79,68 @@ public final class CardEmulationManager { */ public static final String CATEGORY_OTHER = "other"; static boolean sIsInitialized = false; static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap(); static INfcCardEmulation sService; /** * Return value for {@link #getSelectionModeForCategory(String)}. * * <p>In this mode, the user has set a default service for this * AID category. If a remote reader selects any of the AIDs * that the default service has registered in this category, * that service will automatically be bound to to handle * the transaction. * * <p>There are still cases where a service that is * not the default for a category can selected: * <p> * If a remote reader selects an AID in this category * that is not handled by the default service, and there is a set * of other services {S} that do handle this AID, the * user is asked if he wants to use any of the services in * {S} instead. * <p> * As a special case, if the size of {S} is one, containing a single service X, * and all AIDs X has registered in this category are not * registered by any other service, then X will be * selected automatically without asking the user. * <p>Example: * <ul> * <li>Service A registers AIDs "1", "2" and "3" in the category * <li>Service B registers AIDs "3" and "4" in the category * <li>Service C registers AIDs "5" and "6" in the category * </ul> * In this case, the following will happen when service A * is the default: * <ul> * <li>Reader selects AID "1", "2" or "3": service A is invoked automatically * <li>Reader selects AID "4": the user is asked to confirm he * wants to use service B, because its AIDs overlap with service A. * <li>Reader selects AID "5" or "6": service C is invoked automatically, * because all AIDs it has asked for are only registered by C, * and there is no overlap. * </ul> * */ public static final int SELECTION_MODE_PREFER_DEFAULT = 0; /** * @hide * Return value for {@link #getSelectionModeForCategory(String)}. * * <p>In this mode, whenever an AID of this category is selected, * the user is asked which service he wants to use to handle * the transaction, even if there is only one matching service. */ public static final String PAYMENT_MODE_AUTO = "auto"; public static final int SELECTION_MODE_ALWAYS_ASK = 1; /** * @hide * Return value for {@link #getSelectionModeForCategory(String)}. * * <p>In this mode, the user will only be asked to select a service * if the selected AID has been registered by multiple applications. */ public static final String PAYMENT_MODE_MANUAL = "manual"; public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; static boolean sIsInitialized = false; static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap(); static INfcCardEmulation sService; final Context mContext; Loading @@ -113,7 +163,7 @@ public final class CardEmulationManager { throw new UnsupportedOperationException(); } try { if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) { if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) { Log.e(TAG, "This device does not support card emulation"); throw new UnsupportedOperationException(); } Loading @@ -137,6 +187,10 @@ public final class CardEmulationManager { * Allows an application to query whether a service is currently * the default service to handle a card emulation category. * * <p>Note that if {@link #getSelectionModeForCategory(String)} * returns {@link #SELECTION_MODE_ALWAYS_ASK}, this method will always * return false. * * @param service The ComponentName of the service * @param category The category * @return whether service is currently the default service for the category. Loading @@ -147,6 +201,10 @@ public final class CardEmulationManager { } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service, category); Loading Loading @@ -185,6 +243,33 @@ public final class CardEmulationManager { } } /** * Returns the application selection mode for the passed in category. * Valid return values are: * <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default * application for this category, which will be preferred. * <p>{@link #SELECTION_MODE_ALWAYS_ASK} the user has requested to be asked * every time what app he would like to use in this category. * <p>{@link #SELECTION_MODE_ASK_IF_CONFLICT} the user will only be asked * to pick a service if there is a conflict. * @param category The category, for example {@link #CATEGORY_PAYMENT} * @return */ public int getSelectionModeForCategory(String category) { if (CATEGORY_PAYMENT.equals(category)) { String defaultComponent = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT); if (defaultComponent != null) { return SELECTION_MODE_PREFER_DEFAULT; } else { return SELECTION_MODE_ALWAYS_ASK; } } else { // All other categories are in "only ask if conflict" mode return SELECTION_MODE_ASK_IF_CONFLICT; } } /** * @hide */ Loading
core/java/android/nfc/cardemulation/HostApduService.java +0 −2 Original line number Diff line number Diff line Loading @@ -4,13 +4,11 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; Loading
core/java/android/provider/Settings.java +0 −6 Original line number Diff line number Diff line Loading @@ -4284,12 +4284,6 @@ public final class Settings { */ public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component"; /** * Whether to automatically invoke NFC payment app or manually select on tap. * @hide */ public static final String NFC_PAYMENT_MODE = "nfc_payment_mode"; /** * Name of a package that the current user has explicitly allowed to see all of that * user's notifications. Loading