Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44bb5796 authored by Ruchi Kandoi's avatar Ruchi Kandoi
Browse files

Add a mechanism to register AIDs to specific off-host SE

Test: manual
Bug: 117253962
Change-Id: Id34bf84dcff7789548eac19478010838bebd9758
parent ebf267a2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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";
+2 −0
Original line number Diff line number Diff line
@@ -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);
+62 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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
     */
@@ -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);
@@ -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,
@@ -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();
            }

@@ -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
@@ -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);
    }
@@ -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()));
@@ -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) {
@@ -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
@@ -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);
+102 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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.
+2 −0
Original line number Diff line number Diff line
@@ -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