Loading api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -29253,8 +29253,10 @@ package android.nfc.cardemulation { method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String); method public boolean registerAidsForService(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>); method public boolean removeAidsForService(android.content.ComponentName, java.lang.String); method public boolean setOffHostForService(android.content.ComponentName, java.lang.String); method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); method public boolean supportsAidPrefixRegistration(); method public boolean unsetOffHostForService(android.content.ComponentName); method public boolean unsetPreferredService(android.app.Activity); 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"; core/java/android/nfc/INfcCardEmulation.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ interface INfcCardEmulation boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category); boolean setDefaultForNextTap(int userHandle, in ComponentName service); boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup); boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement); boolean unsetOffHostForService(int userHandle, in ComponentName service); AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category); boolean removeAidGroupForService(int userHandle, in ComponentName service, String category); List<ApduServiceInfo> getServices(int userHandle, in String category); Loading core/java/android/nfc/cardemulation/ApduServiceInfo.java +62 −8 Original line number Diff line number Diff line Loading @@ -18,11 +18,10 @@ package android.nfc.cardemulation; import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.content.res.TypedArray; Loading @@ -30,7 +29,6 @@ import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.os.ResultReceiver; import android.util.AttributeSet; import android.util.Log; import android.util.Xml; Loading Loading @@ -68,6 +66,18 @@ public final class ApduServiceInfo implements Parcelable { */ final boolean mOnHost; /** * Offhost reader name. * eg: SIM, eSE etc */ String mOffHostName; /** * Offhost reader name from manifest file. * Used for unsetOffHostSecureElement() */ final String mStaticOffHostName; /** * Mapping from category to static AID group */ Loading Loading @@ -104,15 +114,17 @@ public final class ApduServiceInfo implements Parcelable { * @hide */ @UnsupportedAppUsage public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, public ApduServiceInfo(ResolveInfo info, String description, ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups, boolean requiresUnlock, int bannerResource, int uid, String settingsActivityName) { String settingsActivityName, String offHost, String staticOffHost) { this.mService = info; this.mDescription = description; this.mStaticAidGroups = new HashMap<String, AidGroup>(); this.mDynamicAidGroups = new HashMap<String, AidGroup>(); this.mOnHost = onHost; this.mOffHostName = offHost; this.mStaticOffHostName = staticOffHost; this.mOnHost = (offHost == null); this.mRequiresDeviceUnlock = requiresUnlock; for (AidGroup aidGroup : staticAidGroups) { this.mStaticAidGroups.put(aidGroup.category, aidGroup); Loading Loading @@ -174,6 +186,8 @@ public final class ApduServiceInfo implements Parcelable { com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1); mSettingsActivityName = sa.getString( com.android.internal.R.styleable.HostApduService_settingsActivity); mOffHostName = null; mStaticOffHostName = mOffHostName; sa.recycle(); } else { TypedArray sa = res.obtainAttributes(attrs, Loading @@ -186,6 +200,16 @@ public final class ApduServiceInfo implements Parcelable { com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1); mSettingsActivityName = sa.getString( com.android.internal.R.styleable.HostApduService_settingsActivity); mOffHostName = sa.getString( com.android.internal.R.styleable.OffHostApduService_secureElementName); if (mOffHostName != null) { if (mOffHostName.equals("eSE")) { mOffHostName = "eSE1"; } else if (mOffHostName.equals("SIM")) { mOffHostName = "SIM1"; } } mStaticOffHostName = mOffHostName; sa.recycle(); } Loading Loading @@ -289,6 +313,10 @@ public final class ApduServiceInfo implements Parcelable { mService.serviceInfo.name); } public String getOffHostSecureElement() { return mOffHostName; } /** * Returns a consolidated list of AIDs from the AID groups * registered by this service. Note that if a service has both Loading Loading @@ -404,6 +432,20 @@ public final class ApduServiceInfo implements Parcelable { mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup); } @UnsupportedAppUsage public void setOffHostSecureElement(String offHost) { mOffHostName = offHost; } /** * Resets the off host Secure Element to statically defined * by the service in the manifest file. */ @UnsupportedAppUsage public void unsetOffHostSecureElement() { mOffHostName = mStaticOffHostName; } public CharSequence loadLabel(PackageManager pm) { return mService.loadLabel(pm); } Loading Loading @@ -481,6 +523,8 @@ public final class ApduServiceInfo implements Parcelable { mService.writeToParcel(dest, flags); dest.writeString(mDescription); dest.writeInt(mOnHost ? 1 : 0); dest.writeString(mOffHostName); dest.writeString(mStaticOffHostName); dest.writeInt(mStaticAidGroups.size()); if (mStaticAidGroups.size() > 0) { dest.writeTypedList(new ArrayList<AidGroup>(mStaticAidGroups.values())); Loading @@ -503,6 +547,8 @@ public final class ApduServiceInfo implements Parcelable { ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source); String description = source.readString(); boolean onHost = source.readInt() != 0; String offHostName = source.readString(); String staticOffHostName = source.readString(); ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>(); int numStaticGroups = source.readInt(); if (numStaticGroups > 0) { Loading @@ -517,9 +563,9 @@ public final class ApduServiceInfo implements Parcelable { int bannerResource = source.readInt(); int uid = source.readInt(); String settingsActivityName = source.readString(); return new ApduServiceInfo(info, onHost, description, staticAidGroups, return new ApduServiceInfo(info, description, staticAidGroups, dynamicAidGroups, requiresUnlock, bannerResource, uid, settingsActivityName); settingsActivityName, offHostName, staticOffHostName); } @Override Loading @@ -531,6 +577,14 @@ public final class ApduServiceInfo implements Parcelable { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(" " + getComponent() + " (Description: " + getDescription() + ")"); if (mOnHost) { pw.println(" On Host Service"); } else { pw.println(" Off-host Service"); pw.println(" " + "Current off-host SE" + mOffHostName + " static off-host: " + mOffHostName); } pw.println(" Static off-host Secure Element:"); pw.println(" Static AID groups:"); for (AidGroup group : mStaticAidGroups.values()) { pw.println(" Category: " + group.category); Loading core/java/android/nfc/cardemulation/CardEmulation.java +102 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ 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.provider.Settings.SettingNotFoundException; import android.util.Log; Loading Loading @@ -344,6 +343,108 @@ public final class CardEmulation { } } /** * Unsets the off-host Secure Element for the given service. * * <p>Note that this will only remove Secure Element that was dynamically * set using the {@link #setOffHostForService(ComponentName, String)} * and resets it to a value that was statically assigned using manifest. * * <p>Note that you can only unset off-host SE for a service that * is running under the same UID as the caller of this API. Typically * this means you need to call this from the same * package as the service itself, though UIDs can also * be shared between packages using shared UIDs. * * @param service The component name of the service * @return whether the registration was successful. */ public boolean unsetOffHostForService(ComponentName service) { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); if (adapter == null) { return false; } try { return sService.unsetOffHostForService(mContext.getUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.unsetOffHostForService(mContext.getUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * Sets the off-host Secure Element for the given service. * * <p>If off-host SE was initially set (either statically * through the manifest, or dynamically by using this API), * it will be replaced with this one. All AIDs registered by * this service will be re-routed to this Secure Element if * successful. * * <p>Note that you can only set off-host SE for a service that * is running under the same UID as the caller of this API. Typically * this means you need to call this from the same * package as the service itself, though UIDs can also * be shared between packages using shared UIDs. * * <p>Registeration will be successful only if the Secure Element * exists on the device. * * @param service The component name of the service * @param offHostSecureElement Secure Element to register the AID to * @return whether the registration was successful. */ public boolean setOffHostForService(ComponentName service, String offHostSecureElement) { boolean validSecureElement = false; NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); if (adapter == null || offHostSecureElement == null) { return false; } List<String> validSE = adapter.getSupportedOffHostSecureElements(); if ((offHostSecureElement.startsWith("eSE") && !validSE.contains("eSE")) || (offHostSecureElement.startsWith("SIM") && !validSE.contains("SIM"))) { return false; } if (offHostSecureElement.equals("eSE")) { offHostSecureElement = "eSE1"; } else if (offHostSecureElement.equals("SIM")) { offHostSecureElement = "SIM1"; } try { return sService.setOffHostForService(mContext.getUserId(), service, offHostSecureElement); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.setOffHostForService(mContext.getUserId(), service, offHostSecureElement); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * Retrieves the currently registered AIDs for the specified * category for a service. Loading core/res/res/values/attrs.xml +2 −0 Original line number Diff line number Diff line Loading @@ -3690,6 +3690,8 @@ <!-- Component name of an activity that allows the user to modify the settings for this service. --> <attr name="settingsActivity"/> <!-- Secure Element which the AIDs should be routed to --> <attr name="secureElementName"/> </declare-styleable> <!-- Specify one or more <code>aid-group</code> elements inside a Loading Loading
api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -29253,8 +29253,10 @@ package android.nfc.cardemulation { method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String); method public boolean registerAidsForService(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>); method public boolean removeAidsForService(android.content.ComponentName, java.lang.String); method public boolean setOffHostForService(android.content.ComponentName, java.lang.String); method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); method public boolean supportsAidPrefixRegistration(); method public boolean unsetOffHostForService(android.content.ComponentName); method public boolean unsetPreferredService(android.app.Activity); 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";
core/java/android/nfc/INfcCardEmulation.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ interface INfcCardEmulation boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category); boolean setDefaultForNextTap(int userHandle, in ComponentName service); boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup); boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement); boolean unsetOffHostForService(int userHandle, in ComponentName service); AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category); boolean removeAidGroupForService(int userHandle, in ComponentName service, String category); List<ApduServiceInfo> getServices(int userHandle, in String category); Loading
core/java/android/nfc/cardemulation/ApduServiceInfo.java +62 −8 Original line number Diff line number Diff line Loading @@ -18,11 +18,10 @@ package android.nfc.cardemulation; import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.content.res.TypedArray; Loading @@ -30,7 +29,6 @@ import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.os.ResultReceiver; import android.util.AttributeSet; import android.util.Log; import android.util.Xml; Loading Loading @@ -68,6 +66,18 @@ public final class ApduServiceInfo implements Parcelable { */ final boolean mOnHost; /** * Offhost reader name. * eg: SIM, eSE etc */ String mOffHostName; /** * Offhost reader name from manifest file. * Used for unsetOffHostSecureElement() */ final String mStaticOffHostName; /** * Mapping from category to static AID group */ Loading Loading @@ -104,15 +114,17 @@ public final class ApduServiceInfo implements Parcelable { * @hide */ @UnsupportedAppUsage public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, public ApduServiceInfo(ResolveInfo info, String description, ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups, boolean requiresUnlock, int bannerResource, int uid, String settingsActivityName) { String settingsActivityName, String offHost, String staticOffHost) { this.mService = info; this.mDescription = description; this.mStaticAidGroups = new HashMap<String, AidGroup>(); this.mDynamicAidGroups = new HashMap<String, AidGroup>(); this.mOnHost = onHost; this.mOffHostName = offHost; this.mStaticOffHostName = staticOffHost; this.mOnHost = (offHost == null); this.mRequiresDeviceUnlock = requiresUnlock; for (AidGroup aidGroup : staticAidGroups) { this.mStaticAidGroups.put(aidGroup.category, aidGroup); Loading Loading @@ -174,6 +186,8 @@ public final class ApduServiceInfo implements Parcelable { com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1); mSettingsActivityName = sa.getString( com.android.internal.R.styleable.HostApduService_settingsActivity); mOffHostName = null; mStaticOffHostName = mOffHostName; sa.recycle(); } else { TypedArray sa = res.obtainAttributes(attrs, Loading @@ -186,6 +200,16 @@ public final class ApduServiceInfo implements Parcelable { com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1); mSettingsActivityName = sa.getString( com.android.internal.R.styleable.HostApduService_settingsActivity); mOffHostName = sa.getString( com.android.internal.R.styleable.OffHostApduService_secureElementName); if (mOffHostName != null) { if (mOffHostName.equals("eSE")) { mOffHostName = "eSE1"; } else if (mOffHostName.equals("SIM")) { mOffHostName = "SIM1"; } } mStaticOffHostName = mOffHostName; sa.recycle(); } Loading Loading @@ -289,6 +313,10 @@ public final class ApduServiceInfo implements Parcelable { mService.serviceInfo.name); } public String getOffHostSecureElement() { return mOffHostName; } /** * Returns a consolidated list of AIDs from the AID groups * registered by this service. Note that if a service has both Loading Loading @@ -404,6 +432,20 @@ public final class ApduServiceInfo implements Parcelable { mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup); } @UnsupportedAppUsage public void setOffHostSecureElement(String offHost) { mOffHostName = offHost; } /** * Resets the off host Secure Element to statically defined * by the service in the manifest file. */ @UnsupportedAppUsage public void unsetOffHostSecureElement() { mOffHostName = mStaticOffHostName; } public CharSequence loadLabel(PackageManager pm) { return mService.loadLabel(pm); } Loading Loading @@ -481,6 +523,8 @@ public final class ApduServiceInfo implements Parcelable { mService.writeToParcel(dest, flags); dest.writeString(mDescription); dest.writeInt(mOnHost ? 1 : 0); dest.writeString(mOffHostName); dest.writeString(mStaticOffHostName); dest.writeInt(mStaticAidGroups.size()); if (mStaticAidGroups.size() > 0) { dest.writeTypedList(new ArrayList<AidGroup>(mStaticAidGroups.values())); Loading @@ -503,6 +547,8 @@ public final class ApduServiceInfo implements Parcelable { ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source); String description = source.readString(); boolean onHost = source.readInt() != 0; String offHostName = source.readString(); String staticOffHostName = source.readString(); ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>(); int numStaticGroups = source.readInt(); if (numStaticGroups > 0) { Loading @@ -517,9 +563,9 @@ public final class ApduServiceInfo implements Parcelable { int bannerResource = source.readInt(); int uid = source.readInt(); String settingsActivityName = source.readString(); return new ApduServiceInfo(info, onHost, description, staticAidGroups, return new ApduServiceInfo(info, description, staticAidGroups, dynamicAidGroups, requiresUnlock, bannerResource, uid, settingsActivityName); settingsActivityName, offHostName, staticOffHostName); } @Override Loading @@ -531,6 +577,14 @@ public final class ApduServiceInfo implements Parcelable { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(" " + getComponent() + " (Description: " + getDescription() + ")"); if (mOnHost) { pw.println(" On Host Service"); } else { pw.println(" Off-host Service"); pw.println(" " + "Current off-host SE" + mOffHostName + " static off-host: " + mOffHostName); } pw.println(" Static off-host Secure Element:"); pw.println(" Static AID groups:"); for (AidGroup group : mStaticAidGroups.values()) { pw.println(" Category: " + group.category); Loading
core/java/android/nfc/cardemulation/CardEmulation.java +102 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ 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.provider.Settings.SettingNotFoundException; import android.util.Log; Loading Loading @@ -344,6 +343,108 @@ public final class CardEmulation { } } /** * Unsets the off-host Secure Element for the given service. * * <p>Note that this will only remove Secure Element that was dynamically * set using the {@link #setOffHostForService(ComponentName, String)} * and resets it to a value that was statically assigned using manifest. * * <p>Note that you can only unset off-host SE for a service that * is running under the same UID as the caller of this API. Typically * this means you need to call this from the same * package as the service itself, though UIDs can also * be shared between packages using shared UIDs. * * @param service The component name of the service * @return whether the registration was successful. */ public boolean unsetOffHostForService(ComponentName service) { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); if (adapter == null) { return false; } try { return sService.unsetOffHostForService(mContext.getUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.unsetOffHostForService(mContext.getUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * Sets the off-host Secure Element for the given service. * * <p>If off-host SE was initially set (either statically * through the manifest, or dynamically by using this API), * it will be replaced with this one. All AIDs registered by * this service will be re-routed to this Secure Element if * successful. * * <p>Note that you can only set off-host SE for a service that * is running under the same UID as the caller of this API. Typically * this means you need to call this from the same * package as the service itself, though UIDs can also * be shared between packages using shared UIDs. * * <p>Registeration will be successful only if the Secure Element * exists on the device. * * @param service The component name of the service * @param offHostSecureElement Secure Element to register the AID to * @return whether the registration was successful. */ public boolean setOffHostForService(ComponentName service, String offHostSecureElement) { boolean validSecureElement = false; NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); if (adapter == null || offHostSecureElement == null) { return false; } List<String> validSE = adapter.getSupportedOffHostSecureElements(); if ((offHostSecureElement.startsWith("eSE") && !validSE.contains("eSE")) || (offHostSecureElement.startsWith("SIM") && !validSE.contains("SIM"))) { return false; } if (offHostSecureElement.equals("eSE")) { offHostSecureElement = "eSE1"; } else if (offHostSecureElement.equals("SIM")) { offHostSecureElement = "SIM1"; } try { return sService.setOffHostForService(mContext.getUserId(), service, offHostSecureElement); } catch (RemoteException e) { // Try one more time recoverService(); if (sService == null) { Log.e(TAG, "Failed to recover CardEmulationService."); return false; } try { return sService.setOffHostForService(mContext.getUserId(), service, offHostSecureElement); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; } } } /** * Retrieves the currently registered AIDs for the specified * category for a service. Loading
core/res/res/values/attrs.xml +2 −0 Original line number Diff line number Diff line Loading @@ -3690,6 +3690,8 @@ <!-- Component name of an activity that allows the user to modify the settings for this service. --> <attr name="settingsActivity"/> <!-- Secure Element which the AIDs should be routed to --> <attr name="secureElementName"/> </declare-styleable> <!-- Specify one or more <code>aid-group</code> elements inside a Loading