| /* |
| * Copyright (C) 2018 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 com.android.internal.telephony.uicc.euicc; |
| |
| import android.telephony.Rlog; |
| |
| import com.android.internal.telephony.uicc.asn1.Asn1Decoder; |
| import com.android.internal.telephony.uicc.asn1.Asn1Node; |
| import com.android.internal.telephony.uicc.asn1.InvalidAsn1DataException; |
| import com.android.internal.telephony.uicc.asn1.TagNotFoundException; |
| |
| import java.util.Arrays; |
| |
| /** |
| * This represents the version of GSMA SGP.22 spec in the form of 3 numbers: major, minor, and |
| * revision. |
| */ |
| public final class EuiccSpecVersion implements Comparable<EuiccSpecVersion> { |
| private static final String LOG_TAG = "EuiccSpecVer"; |
| |
| // ASN.1 Tags |
| private static final int TAG_ISD_R_APP_TEMPLATE = 0xE0; |
| private static final int TAG_VERSION = 0x82; |
| |
| private final int[] mVersionValues = new int[3]; |
| |
| /** |
| * Parses the response of opening a logical channel to get spec version of the eUICC card. |
| * |
| * @return Parsed spec version. If any error is encountered, null will be returned. |
| */ |
| public static EuiccSpecVersion fromOpenChannelResponse(byte[] response) { |
| Asn1Node node; |
| try { |
| Asn1Decoder decoder = new Asn1Decoder(response); |
| if (!decoder.hasNextNode()) { |
| return null; |
| } |
| node = decoder.nextNode(); |
| } catch (InvalidAsn1DataException e) { |
| Rlog.e(LOG_TAG, "Cannot parse the select response of ISD-R.", e); |
| return null; |
| } |
| try { |
| byte[] versionType; |
| if (node.getTag() == TAG_ISD_R_APP_TEMPLATE) { |
| versionType = node.getChild(TAG_VERSION).asBytes(); |
| } else { |
| versionType = |
| node.getChild(TAG_ISD_R_APP_TEMPLATE, TAG_VERSION).asBytes(); |
| } |
| if (versionType.length == 3) { |
| return new EuiccSpecVersion(versionType); |
| } else { |
| Rlog.e(LOG_TAG, "Cannot parse select response of ISD-R: " + node.toHex()); |
| } |
| } catch (InvalidAsn1DataException | TagNotFoundException e) { |
| Rlog.e(LOG_TAG, "Cannot parse select response of ISD-R: " + node.toHex()); |
| } |
| return null; |
| } |
| |
| public EuiccSpecVersion(int major, int minor, int revision) { |
| mVersionValues[0] = major; |
| mVersionValues[1] = minor; |
| mVersionValues[2] = revision; |
| } |
| |
| /** |
| * @param version The version bytes from ASN1 data. The length must be 3. |
| */ |
| public EuiccSpecVersion(byte[] version) { |
| mVersionValues[0] = version[0] & 0xFF; |
| mVersionValues[1] = version[1] & 0xFF; |
| mVersionValues[2] = version[2] & 0xFF; |
| } |
| |
| public int getMajor() { |
| return mVersionValues[0]; |
| } |
| |
| public int getMinor() { |
| return mVersionValues[1]; |
| } |
| |
| public int getRevision() { |
| return mVersionValues[2]; |
| } |
| |
| @Override |
| public int compareTo(EuiccSpecVersion that) { |
| if (getMajor() > that.getMajor()) { |
| return 1; |
| } else if (getMajor() < that.getMajor()) { |
| return -1; |
| } |
| if (getMinor() > that.getMinor()) { |
| return 1; |
| } else if (getMinor() < that.getMinor()) { |
| return -1; |
| } |
| if (getRevision() > that.getRevision()) { |
| return 1; |
| } else if (getRevision() < that.getRevision()) { |
| return -1; |
| } |
| return 0; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj == null || getClass() != obj.getClass()) { |
| return false; |
| } |
| return Arrays.equals(mVersionValues, ((EuiccSpecVersion) obj).mVersionValues); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Arrays.hashCode(mVersionValues); |
| } |
| |
| @Override |
| public String toString() { |
| return mVersionValues[0] + "." + mVersionValues[1] + "." + mVersionValues[2]; |
| } |
| } |