Loading api/current.txt +7 −7 Original line number Diff line number Diff line Loading @@ -15264,12 +15264,12 @@ package android.nfc { package android.nfc.cardemulation { public final class CardEmulationManager { method public static synchronized android.nfc.cardemulation.CardEmulationManager getInstance(android.nfc.NfcAdapter); public final class CardEmulation { method public static synchronized android.nfc.cardemulation.CardEmulation 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"; field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; field public static final java.lang.String CATEGORY_OTHER = "other"; field public static final java.lang.String CATEGORY_PAYMENT = "payment"; field public static final java.lang.String EXTRA_CATEGORY = "category"; Loading @@ -15289,15 +15289,15 @@ package android.nfc.cardemulation { method public final void sendResponseApdu(byte[]); field public static final int DEACTIVATION_DESELECTED = 1; // 0x1 field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0 field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.HostApduService"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.HostApduService"; field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service"; } public abstract class OffHostApduService extends android.app.Service { ctor public OffHostApduService(); method public abstract android.os.IBinder onBind(android.content.Intent); field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.OffHostApduService"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.OffHostApduService"; field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.cardemulation.off_host_apdu_service"; } } core/java/android/nfc/cardemulation/ApduServiceInfo.java +9 −5 Original line number Diff line number Diff line Loading @@ -104,10 +104,14 @@ public final class ApduServiceInfo implements Parcelable { try { if (onHost) { parser = si.loadXmlMetaData(pm, HostApduService.SERVICE_META_DATA); if (parser == null) { Log.d(TAG, "Didn't find service meta-data, trying legacy."); parser = si.loadXmlMetaData(pm, HostApduService.OLD_SERVICE_META_DATA); if (parser == null) { throw new XmlPullParserException("No " + HostApduService.SERVICE_META_DATA + " meta-data"); } } } else { parser = si.loadXmlMetaData(pm, OffHostApduService.SERVICE_META_DATA); if (parser == null) { Loading Loading @@ -170,12 +174,12 @@ public final class ApduServiceInfo implements Parcelable { com.android.internal.R.styleable.AidGroup_description); String groupCategory = groupAttrs.getString( com.android.internal.R.styleable.AidGroup_category); if (!CardEmulationManager.CATEGORY_PAYMENT.equals(groupCategory)) { groupCategory = CardEmulationManager.CATEGORY_OTHER; if (!CardEmulation.CATEGORY_PAYMENT.equals(groupCategory)) { groupCategory = CardEmulation.CATEGORY_OTHER; } currentGroup = mCategoryToGroup.get(groupCategory); if (currentGroup != null) { if (!CardEmulationManager.CATEGORY_OTHER.equals(groupCategory)) { if (!CardEmulation.CATEGORY_OTHER.equals(groupCategory)) { Log.e(TAG, "Not allowing multiple aid-groups in the " + groupCategory + " category"); currentGroup = null; Loading core/java/android/nfc/cardemulation/CardEmulation.java 0 → 100644 +343 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.nfc.cardemulation; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.ActivityThread; import android.content.ComponentName; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; 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; import java.util.List; public final class CardEmulation { static final String TAG = "CardEmulation"; /** * Activity action: ask the user to change the default * card emulation service for a certain category. This will * show a dialog that asks the user whether he wants to * replace the current default service with the service * identified with the ComponentName specified in * {@link #EXTRA_SERVICE_COMPONENT}, for the category * specified in {@link #EXTRA_CATEGORY} */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; /** * The category extra for {@link #ACTION_CHANGE_DEFAULT} * * @see #ACTION_CHANGE_DEFAULT */ public static final String EXTRA_CATEGORY = "category"; /** * The ComponentName object passed in as a parcelable * extra for {@link #ACTION_CHANGE_DEFAULT} * * @see #ACTION_CHANGE_DEFAULT */ public static final String EXTRA_SERVICE_COMPONENT = "component"; /** * The payment category can be used to indicate that an AID * represents a payment application. */ public static final String CATEGORY_PAYMENT = "payment"; /** * If an AID group does not contain a category, or the * specified category is not defined by the platform version * that is parsing the AID group, all AIDs in the group will * automatically be categorized under the {@link #CATEGORY_OTHER} * category. */ public static final String CATEGORY_OTHER = "other"; /** * 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; /** * 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 int SELECTION_MODE_ALWAYS_ASK = 1; /** * 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 int SELECTION_MODE_ASK_IF_CONFLICT = 2; static boolean sIsInitialized = false; static HashMap<Context, CardEmulation> sCardEmus = new HashMap(); static INfcCardEmulation sService; final Context mContext; private CardEmulation(Context context, INfcCardEmulation service) { mContext = context.getApplicationContext(); sService = service; } public static synchronized CardEmulation getInstance(NfcAdapter adapter) { if (adapter == null) throw new NullPointerException("NfcAdapter is null"); Context context = adapter.getContext(); if (context == null) { Log.e(TAG, "NfcAdapter context is null."); throw new UnsupportedOperationException(); } if (!sIsInitialized) { IPackageManager pm = ActivityThread.getPackageManager(); if (pm == null) { Log.e(TAG, "Cannot get PackageManager"); throw new UnsupportedOperationException(); } try { if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) { Log.e(TAG, "This device does not support card emulation"); throw new UnsupportedOperationException(); } } catch (RemoteException e) { Log.e(TAG, "PackageManager query failed."); throw new UnsupportedOperationException(); } sIsInitialized = true; } CardEmulation manager = sCardEmus.get(context); if (manager == null) { // Get card emu service INfcCardEmulation service = adapter.getCardEmulationService(); manager = new CardEmulation(context, service); sCardEmus.put(context, manager); } return manager; } /** * 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. */ public boolean isDefaultServiceForCategory(ComponentName service, String category) { try { return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service, category); } 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); } catch (RemoteException ee) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } } } /** * * Allows an application to query whether a service is currently * the default handler for a specified ISO7816-4 Application ID. * * @param service The ComponentName of the service * @param aid The ISO7816-4 Application ID * @return */ public boolean isDefaultServiceForAid(ComponentName service, String aid) { try { return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * 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 */ public boolean setDefaultServiceForCategory(ComponentName service, String category) { try { return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service, category); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service, category); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * @hide */ public boolean setDefaultForNextTap(ComponentName service) { try { return sService.setDefaultForNextTap(UserHandle.myUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.setDefaultForNextTap(UserHandle.myUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * @hide */ public List<ApduServiceInfo> getServices(String category) { try { return sService.getServices(UserHandle.myUserId(), category); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return null; } try { return sService.getServices(UserHandle.myUserId(), category); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return null; } } } void recoverService() { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); sService = adapter.getCardEmulationService(); } } core/java/android/nfc/cardemulation/CardEmulationManager.java +4 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,10 @@ import android.util.Log; import java.util.HashMap; import java.util.List; /** * TODO Remove when calling .apks are upgraded * @hide */ public final class CardEmulationManager { static final String TAG = "CardEmulationManager"; Loading core/java/android/nfc/cardemulation/HostApduService.java +19 −1 Original line number Diff line number Diff line Loading @@ -40,13 +40,31 @@ public abstract class HostApduService extends Service { */ @SdkConstant(SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE"; /** * The name of the meta-data element that contains * more information about this service. */ public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service"; /** * The {@link Intent} that must be declared as handled by the service. * TODO Remove * @hide */ public static final String OLD_SERVICE_INTERFACE = "android.nfc.HostApduService"; /** * The name of the meta-data element that contains * more information about this service. * * TODO Remove * @hide */ public static final String SERVICE_META_DATA = "android.nfc.HostApduService"; public static final String OLD_SERVICE_META_DATA = "android.nfc.HostApduService"; /** * Reason for {@link #onDeactivated(int)}. Loading Loading
api/current.txt +7 −7 Original line number Diff line number Diff line Loading @@ -15264,12 +15264,12 @@ package android.nfc { package android.nfc.cardemulation { public final class CardEmulationManager { method public static synchronized android.nfc.cardemulation.CardEmulationManager getInstance(android.nfc.NfcAdapter); public final class CardEmulation { method public static synchronized android.nfc.cardemulation.CardEmulation 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"; field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; field public static final java.lang.String CATEGORY_OTHER = "other"; field public static final java.lang.String CATEGORY_PAYMENT = "payment"; field public static final java.lang.String EXTRA_CATEGORY = "category"; Loading @@ -15289,15 +15289,15 @@ package android.nfc.cardemulation { method public final void sendResponseApdu(byte[]); field public static final int DEACTIVATION_DESELECTED = 1; // 0x1 field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0 field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.HostApduService"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.HostApduService"; field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service"; } public abstract class OffHostApduService extends android.app.Service { ctor public OffHostApduService(); method public abstract android.os.IBinder onBind(android.content.Intent); field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.OffHostApduService"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.OffHostApduService"; field public static final java.lang.String SERVICE_INTERFACE = "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"; field public static final java.lang.String SERVICE_META_DATA = "android.nfc.cardemulation.off_host_apdu_service"; } }
core/java/android/nfc/cardemulation/ApduServiceInfo.java +9 −5 Original line number Diff line number Diff line Loading @@ -104,10 +104,14 @@ public final class ApduServiceInfo implements Parcelable { try { if (onHost) { parser = si.loadXmlMetaData(pm, HostApduService.SERVICE_META_DATA); if (parser == null) { Log.d(TAG, "Didn't find service meta-data, trying legacy."); parser = si.loadXmlMetaData(pm, HostApduService.OLD_SERVICE_META_DATA); if (parser == null) { throw new XmlPullParserException("No " + HostApduService.SERVICE_META_DATA + " meta-data"); } } } else { parser = si.loadXmlMetaData(pm, OffHostApduService.SERVICE_META_DATA); if (parser == null) { Loading Loading @@ -170,12 +174,12 @@ public final class ApduServiceInfo implements Parcelable { com.android.internal.R.styleable.AidGroup_description); String groupCategory = groupAttrs.getString( com.android.internal.R.styleable.AidGroup_category); if (!CardEmulationManager.CATEGORY_PAYMENT.equals(groupCategory)) { groupCategory = CardEmulationManager.CATEGORY_OTHER; if (!CardEmulation.CATEGORY_PAYMENT.equals(groupCategory)) { groupCategory = CardEmulation.CATEGORY_OTHER; } currentGroup = mCategoryToGroup.get(groupCategory); if (currentGroup != null) { if (!CardEmulationManager.CATEGORY_OTHER.equals(groupCategory)) { if (!CardEmulation.CATEGORY_OTHER.equals(groupCategory)) { Log.e(TAG, "Not allowing multiple aid-groups in the " + groupCategory + " category"); currentGroup = null; Loading
core/java/android/nfc/cardemulation/CardEmulation.java 0 → 100644 +343 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.nfc.cardemulation; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.ActivityThread; import android.content.ComponentName; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; 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; import java.util.List; public final class CardEmulation { static final String TAG = "CardEmulation"; /** * Activity action: ask the user to change the default * card emulation service for a certain category. This will * show a dialog that asks the user whether he wants to * replace the current default service with the service * identified with the ComponentName specified in * {@link #EXTRA_SERVICE_COMPONENT}, for the category * specified in {@link #EXTRA_CATEGORY} */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; /** * The category extra for {@link #ACTION_CHANGE_DEFAULT} * * @see #ACTION_CHANGE_DEFAULT */ public static final String EXTRA_CATEGORY = "category"; /** * The ComponentName object passed in as a parcelable * extra for {@link #ACTION_CHANGE_DEFAULT} * * @see #ACTION_CHANGE_DEFAULT */ public static final String EXTRA_SERVICE_COMPONENT = "component"; /** * The payment category can be used to indicate that an AID * represents a payment application. */ public static final String CATEGORY_PAYMENT = "payment"; /** * If an AID group does not contain a category, or the * specified category is not defined by the platform version * that is parsing the AID group, all AIDs in the group will * automatically be categorized under the {@link #CATEGORY_OTHER} * category. */ public static final String CATEGORY_OTHER = "other"; /** * 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; /** * 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 int SELECTION_MODE_ALWAYS_ASK = 1; /** * 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 int SELECTION_MODE_ASK_IF_CONFLICT = 2; static boolean sIsInitialized = false; static HashMap<Context, CardEmulation> sCardEmus = new HashMap(); static INfcCardEmulation sService; final Context mContext; private CardEmulation(Context context, INfcCardEmulation service) { mContext = context.getApplicationContext(); sService = service; } public static synchronized CardEmulation getInstance(NfcAdapter adapter) { if (adapter == null) throw new NullPointerException("NfcAdapter is null"); Context context = adapter.getContext(); if (context == null) { Log.e(TAG, "NfcAdapter context is null."); throw new UnsupportedOperationException(); } if (!sIsInitialized) { IPackageManager pm = ActivityThread.getPackageManager(); if (pm == null) { Log.e(TAG, "Cannot get PackageManager"); throw new UnsupportedOperationException(); } try { if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) { Log.e(TAG, "This device does not support card emulation"); throw new UnsupportedOperationException(); } } catch (RemoteException e) { Log.e(TAG, "PackageManager query failed."); throw new UnsupportedOperationException(); } sIsInitialized = true; } CardEmulation manager = sCardEmus.get(context); if (manager == null) { // Get card emu service INfcCardEmulation service = adapter.getCardEmulationService(); manager = new CardEmulation(context, service); sCardEmus.put(context, manager); } return manager; } /** * 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. */ public boolean isDefaultServiceForCategory(ComponentName service, String category) { try { return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service, category); } 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); } catch (RemoteException ee) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } } } /** * * Allows an application to query whether a service is currently * the default handler for a specified ISO7816-4 Application ID. * * @param service The ComponentName of the service * @param aid The ISO7816-4 Application ID * @return */ public boolean isDefaultServiceForAid(ComponentName service, String aid) { try { return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * 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 */ public boolean setDefaultServiceForCategory(ComponentName service, String category) { try { return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service, category); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service, category); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * @hide */ public boolean setDefaultForNextTap(ComponentName service) { try { return sService.setDefaultForNextTap(UserHandle.myUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.setDefaultForNextTap(UserHandle.myUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * @hide */ public List<ApduServiceInfo> getServices(String category) { try { return sService.getServices(UserHandle.myUserId(), category); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return null; } try { return sService.getServices(UserHandle.myUserId(), category); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return null; } } } void recoverService() { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); sService = adapter.getCardEmulationService(); } }
core/java/android/nfc/cardemulation/CardEmulationManager.java +4 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,10 @@ import android.util.Log; import java.util.HashMap; import java.util.List; /** * TODO Remove when calling .apks are upgraded * @hide */ public final class CardEmulationManager { static final String TAG = "CardEmulationManager"; Loading
core/java/android/nfc/cardemulation/HostApduService.java +19 −1 Original line number Diff line number Diff line Loading @@ -40,13 +40,31 @@ public abstract class HostApduService extends Service { */ @SdkConstant(SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE"; /** * The name of the meta-data element that contains * more information about this service. */ public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service"; /** * The {@link Intent} that must be declared as handled by the service. * TODO Remove * @hide */ public static final String OLD_SERVICE_INTERFACE = "android.nfc.HostApduService"; /** * The name of the meta-data element that contains * more information about this service. * * TODO Remove * @hide */ public static final String SERVICE_META_DATA = "android.nfc.HostApduService"; public static final String OLD_SERVICE_META_DATA = "android.nfc.HostApduService"; /** * Reason for {@link #onDeactivated(int)}. Loading