• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.uicc.euicc;
18 
19 import android.telephony.Rlog;
20 
21 import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
22 import com.android.internal.telephony.uicc.asn1.Asn1Node;
23 import com.android.internal.telephony.uicc.asn1.InvalidAsn1DataException;
24 import com.android.internal.telephony.uicc.asn1.TagNotFoundException;
25 
26 import java.util.Arrays;
27 
28 /**
29  * This represents the version of GSMA SGP.22 spec in the form of 3 numbers: major, minor, and
30  * revision.
31  */
32 public final class EuiccSpecVersion implements Comparable<EuiccSpecVersion> {
33     private static final String LOG_TAG = "EuiccSpecVer";
34 
35     // ASN.1 Tags
36     private static final int TAG_ISD_R_APP_TEMPLATE = 0xE0;
37     private static final int TAG_VERSION = 0x82;
38 
39     private final int[] mVersionValues = new int[3];
40 
41     /**
42      * Parses the response of opening a logical channel to get spec version of the eUICC card.
43      *
44      * @return Parsed spec version. If any error is encountered, null will be returned.
45      */
fromOpenChannelResponse(byte[] response)46     public static EuiccSpecVersion fromOpenChannelResponse(byte[] response) {
47         Asn1Node node;
48         try {
49             Asn1Decoder decoder = new Asn1Decoder(response);
50             if (!decoder.hasNextNode()) {
51                 return null;
52             }
53             node = decoder.nextNode();
54         } catch (InvalidAsn1DataException e) {
55             Rlog.e(LOG_TAG, "Cannot parse the select response of ISD-R.", e);
56             return null;
57         }
58         try {
59             byte[] versionType;
60             if (node.getTag() == TAG_ISD_R_APP_TEMPLATE) {
61                 versionType = node.getChild(TAG_VERSION).asBytes();
62             } else {
63                 versionType =
64                         node.getChild(TAG_ISD_R_APP_TEMPLATE, TAG_VERSION).asBytes();
65             }
66             if (versionType.length == 3) {
67                 return new EuiccSpecVersion(versionType);
68             } else {
69                 Rlog.e(LOG_TAG, "Cannot parse select response of ISD-R: " + node.toHex());
70             }
71         } catch (InvalidAsn1DataException | TagNotFoundException e) {
72             Rlog.e(LOG_TAG, "Cannot parse select response of ISD-R: " + node.toHex());
73         }
74         return null;
75     }
76 
EuiccSpecVersion(int major, int minor, int revision)77     public EuiccSpecVersion(int major, int minor, int revision) {
78         mVersionValues[0] = major;
79         mVersionValues[1] = minor;
80         mVersionValues[2] = revision;
81     }
82 
83     /**
84      * @param version The version bytes from ASN1 data. The length must be 3.
85      */
EuiccSpecVersion(byte[] version)86     public EuiccSpecVersion(byte[] version) {
87         mVersionValues[0] = version[0] & 0xFF;
88         mVersionValues[1] = version[1] & 0xFF;
89         mVersionValues[2] = version[2] & 0xFF;
90     }
91 
getMajor()92     public int getMajor() {
93         return mVersionValues[0];
94     }
95 
getMinor()96     public int getMinor() {
97         return mVersionValues[1];
98     }
99 
getRevision()100     public int getRevision() {
101         return mVersionValues[2];
102     }
103 
104     @Override
compareTo(EuiccSpecVersion that)105     public int compareTo(EuiccSpecVersion that) {
106         if (getMajor() > that.getMajor()) {
107             return 1;
108         } else if (getMajor() < that.getMajor()) {
109             return -1;
110         }
111         if (getMinor() > that.getMinor()) {
112             return 1;
113         } else if (getMinor() < that.getMinor()) {
114             return -1;
115         }
116         if (getRevision() > that.getRevision()) {
117             return 1;
118         } else if (getRevision() < that.getRevision()) {
119             return -1;
120         }
121         return 0;
122     }
123 
124     @Override
equals(Object obj)125     public boolean equals(Object obj) {
126         if (this == obj) {
127             return true;
128         }
129         if (obj == null || getClass() != obj.getClass()) {
130             return false;
131         }
132         return Arrays.equals(mVersionValues, ((EuiccSpecVersion) obj).mVersionValues);
133     }
134 
135     @Override
hashCode()136     public int hashCode() {
137         return Arrays.hashCode(mVersionValues);
138     }
139 
140     @Override
toString()141     public String toString() {
142         return mVersionValues[0] + "." + mVersionValues[1] + "." + mVersionValues[2];
143     }
144 }
145