AidGroup.java revision 1bfc3d624925c2b6e0928e26cf0660aee0a05ddf
1aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenpackage android.nfc.cardemulation; 2aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 3aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport java.io.IOException; 4aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport java.util.ArrayList; 5df48db3c7cab1e39ffe16738c070644c1ef66782Martijn Coenenimport java.util.List; 6aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 7aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport org.xmlpull.v1.XmlPullParser; 8aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport org.xmlpull.v1.XmlPullParserException; 9aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport org.xmlpull.v1.XmlSerializer; 10aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 11aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport android.os.Parcel; 12aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport android.os.Parcelable; 13aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenimport android.util.Log; 14aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 15aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen/** 162f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * The AidGroup class represents a group of Application Identifiers (AIDs). 172f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * 182f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * <p>An instance of this object can be used with 191bfc3d624925c2b6e0928e26cf0660aee0a05ddfMartijn Coenen * {@link CardEmulation#registerAidsForService(android.content.ComponentName, String, java.util.List)} 202f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * to tell the OS which AIDs are handled by your HCE- or SE-based service. 212f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * 222f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * <p>The format of AIDs is defined in the ISO/IEC 7816-4 specification. This class 232f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * requires the AIDs to be input as a hexadecimal string, with an even amount of 242f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * hexadecimal characters, e.g. "F014811481". 25df48db3c7cab1e39ffe16738c070644c1ef66782Martijn Coenen * 26df48db3c7cab1e39ffe16738c070644c1ef66782Martijn Coenen * @hide 27aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen */ 28aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenenpublic final class AidGroup implements Parcelable { 29aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen /** 30aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen * The maximum number of AIDs that can be present in any one group. 31aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen */ 32aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public static final int MAX_NUM_AIDS = 256; 33aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 34aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen static final String TAG = "AidGroup"; 35aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 36df48db3c7cab1e39ffe16738c070644c1ef66782Martijn Coenen final List<String> aids; 37aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen final String category; 38aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen final String description; 39aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 40aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen /** 41aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen * Creates a new AidGroup object. 42aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen * 43aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen * @param aids The list of AIDs present in the group 442f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen * @param category The category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT} 45aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen */ 46df48db3c7cab1e39ffe16738c070644c1ef66782Martijn Coenen public AidGroup(List<String> aids, String category) { 47aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (aids == null || aids.size() == 0) { 48aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen throw new IllegalArgumentException("No AIDS in AID group."); 49aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 50aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (aids.size() > MAX_NUM_AIDS) { 51aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen throw new IllegalArgumentException("Too many AIDs in AID group."); 52aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 531bfc3d624925c2b6e0928e26cf0660aee0a05ddfMartijn Coenen for (String aid : aids) { 541bfc3d624925c2b6e0928e26cf0660aee0a05ddfMartijn Coenen if (!ApduServiceInfo.isValidAid(aid)) { 551bfc3d624925c2b6e0928e26cf0660aee0a05ddfMartijn Coenen throw new IllegalArgumentException("AID " + aid + " is not a valid AID."); 561bfc3d624925c2b6e0928e26cf0660aee0a05ddfMartijn Coenen } 571bfc3d624925c2b6e0928e26cf0660aee0a05ddfMartijn Coenen } 582f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen if (isValidCategory(category)) { 592f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen this.category = category; 602f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen } else { 612f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen this.category = CardEmulation.CATEGORY_OTHER; 62aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 63aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen this.aids = aids; 64aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen this.description = null; 65aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 66aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 67aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen AidGroup(String category, String description) { 68aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen this.aids = new ArrayList<String>(); 69aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen this.category = category; 70aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen this.description = description; 71aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 72aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 73aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen /** 74aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen * @return the category of this AID group 75aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen */ 76aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public String getCategory() { 77aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return category; 78aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 79aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 80aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen /** 81aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen * @return the list of AIDs in this group 82aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen */ 83df48db3c7cab1e39ffe16738c070644c1ef66782Martijn Coenen public List<String> getAids() { 84aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return aids; 85aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 86aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 87aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen @Override 88aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public String toString() { 89aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen StringBuilder out = new StringBuilder("Category: " + category + 90aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen ", AIDs:"); 91aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen for (String aid : aids) { 92aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen out.append(aid); 93aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen out.append(", "); 94aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 95aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return out.toString(); 96aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 97aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 98aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen @Override 99aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public int describeContents() { 100aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return 0; 101aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 102aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 103aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen @Override 104aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public void writeToParcel(Parcel dest, int flags) { 105aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen dest.writeString(category); 106aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen dest.writeInt(aids.size()); 107aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (aids.size() > 0) { 108aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen dest.writeStringList(aids); 109aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 110aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 111aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 112aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public static final Parcelable.Creator<AidGroup> CREATOR = 113aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen new Parcelable.Creator<AidGroup>() { 114aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 115aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen @Override 116aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public AidGroup createFromParcel(Parcel source) { 117aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen String category = source.readString(); 118aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen int listSize = source.readInt(); 119aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen ArrayList<String> aidList = new ArrayList<String>(); 120aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (listSize > 0) { 121aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen source.readStringList(aidList); 122aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 123aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return new AidGroup(aidList, category); 124aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 125aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 126aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen @Override 127aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public AidGroup[] newArray(int size) { 128aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return new AidGroup[size]; 129aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 130aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen }; 131aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 132aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen static public AidGroup createFromXml(XmlPullParser parser) throws XmlPullParserException, IOException { 133aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen String category = parser.getAttributeValue(null, "category"); 134aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen ArrayList<String> aids = new ArrayList<String>(); 135aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen int eventType = parser.getEventType(); 136aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen int minDepth = parser.getDepth(); 137aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen while (eventType != XmlPullParser.END_DOCUMENT && parser.getDepth() >= minDepth) { 138aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (eventType == XmlPullParser.START_TAG) { 139aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen String tagName = parser.getName(); 140aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (tagName.equals("aid")) { 141aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen String aid = parser.getAttributeValue(null, "value"); 142aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (aid != null) { 143aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen aids.add(aid); 144aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 145aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } else { 146aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen Log.d(TAG, "Ignorning unexpected tag: " + tagName); 147aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 148aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 149aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen eventType = parser.next(); 150aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 151aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen if (category != null && aids.size() > 0) { 152aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return new AidGroup(aids, category); 153aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } else { 154aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return null; 155aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 156aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 157aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 158aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen public void writeAsXml(XmlSerializer out) throws IOException { 159aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen out.attribute(null, "category", category); 160aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen for (String aid : aids) { 161aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen out.startTag(null, "aid"); 162aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen out.attribute(null, "value", aid); 163aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen out.endTag(null, "aid"); 164aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 165aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 166aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen 1672f6f3a0181b008f58b18804b749d5ddf1ba73bc8Martijn Coenen static boolean isValidCategory(String category) { 168aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen return CardEmulation.CATEGORY_PAYMENT.equals(category) || 169aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen CardEmulation.CATEGORY_OTHER.equals(category); 170aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen } 171aa1492d1d8c5f80e074faacb83905bd07487975dMartijn Coenen} 172