• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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;
18 
19 import android.annotation.IntDef;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.telephony.Rlog;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.util.Arrays;
27 import java.util.Objects;
28 
29 /**
30  * {@hide}
31  */
32 public class PlmnActRecord implements Parcelable {
33     private static final String LOG_TAG = "PlmnActRecord";
34 
35     private static final boolean VDBG = false;
36 
37     @Retention(RetentionPolicy.SOURCE)
38     @IntDef(flag = true, value = {ACCESS_TECH_UTRAN, ACCESS_TECH_EUTRAN, ACCESS_TECH_GSM,
39             ACCESS_TECH_GSM_COMPACT, ACCESS_TECH_CDMA2000_HRPD, ACCESS_TECH_CDMA2000_1XRTT,
40             ACCESS_TECH_RESERVED})
41     public @interface AccessTech {}
42     // Values specified in 3GPP 31.102 sec. 4.2.5
43     public static final int ACCESS_TECH_UTRAN = 0x8000;
44     public static final int ACCESS_TECH_EUTRAN = 0x4000;
45     public static final int ACCESS_TECH_GSM = 0x0080;
46     public static final int ACCESS_TECH_GSM_COMPACT = 0x0040;
47     public static final int ACCESS_TECH_CDMA2000_HRPD = 0x0020;
48     public static final int ACCESS_TECH_CDMA2000_1XRTT = 0x0010;
49     public static final int ACCESS_TECH_RESERVED = 0x3F0F;
50 
51     public static final int ENCODED_LENGTH = 5;
52 
53     public final String plmn;
54     public final int accessTechs;
55 
56     /**
57      * Instantiate a PLMN w/ ACT Record
58      */
PlmnActRecord(String plmn, int accessTechs)59     public PlmnActRecord(String plmn, int accessTechs) {
60         this.plmn = plmn;
61         this.accessTechs = accessTechs;
62     }
63 
64     /* From 3gpp 31.102 section 4.2.5
65      * Bytes 0-2 bcd-encoded PLMN-ID
66      * Bytes 3-4 bitfield of access technologies
67      */
PlmnActRecord(byte[] bytes, int offset)68     public PlmnActRecord(byte[] bytes, int offset) {
69         if (VDBG) Rlog.v(LOG_TAG, "Creating PlmnActRecord " + offset);
70         this.plmn = IccUtils.bcdPlmnToString(bytes, offset);
71         this.accessTechs = (Byte.toUnsignedInt(bytes[offset + 3]) << 8)
72                         | Byte.toUnsignedInt(bytes[offset + 4]);
73     }
74 
75     /**
76      * Get a record encoded as per 31.102 section 4.2.5
77      */
getBytes()78     public byte[] getBytes() {
79         byte[] ret = new byte[ENCODED_LENGTH];
80         IccUtils.stringToBcdPlmn(this.plmn, ret, 0);
81         ret[3] = (byte) (this.accessTechs >> 8);
82         ret[4] = (byte) this.accessTechs;
83         return ret;
84     }
85 
accessTechString()86     private String accessTechString() {
87         if (accessTechs == 0) {
88             return "NONE";
89         }
90 
91         StringBuilder sb = new StringBuilder();
92         if ((accessTechs & ACCESS_TECH_UTRAN) != 0) {
93             sb.append("UTRAN|");
94         }
95         if ((accessTechs & ACCESS_TECH_EUTRAN) != 0) {
96             sb.append("EUTRAN|");
97         }
98         if ((accessTechs & ACCESS_TECH_GSM) != 0) {
99             sb.append("GSM|");
100         }
101         if ((accessTechs & ACCESS_TECH_GSM_COMPACT) != 0) {
102             sb.append("GSM_COMPACT|");
103         }
104         if ((accessTechs & ACCESS_TECH_CDMA2000_HRPD) != 0) {
105             sb.append("CDMA2000_HRPD|");
106         }
107         if ((accessTechs & ACCESS_TECH_CDMA2000_1XRTT) != 0) {
108             sb.append("CDMA2000_1XRTT|");
109         }
110         if ((accessTechs & ACCESS_TECH_RESERVED) != 0) {
111             sb.append(String.format("UNKNOWN:%x|", accessTechs & ACCESS_TECH_RESERVED));
112         }
113         // Trim the tailing pipe character
114         return sb.substring(0, sb.length() - 1);
115     }
116 
117     @Override
toString()118     public String toString() {
119         return String.format("{PLMN=%s,AccessTechs=%s}", plmn, accessTechString());
120     }
121 
122     /**
123      * Convenience method for extracting all records from encoded bytes
124      */
getRecords(byte[] recordBytes)125     public static PlmnActRecord[] getRecords(byte[] recordBytes) {
126         if (recordBytes == null || recordBytes.length == 0
127                 || recordBytes.length % ENCODED_LENGTH != 0) {
128             Rlog.e(LOG_TAG, "Malformed PlmnActRecord, bytes: "
129                     + ((recordBytes != null) ? Arrays.toString(recordBytes) : null));
130             return null;
131         }
132         int numRecords = recordBytes.length / ENCODED_LENGTH;
133         if (VDBG) Rlog.v(LOG_TAG, "Extracting Logs, count=" + numRecords);
134 
135         PlmnActRecord[] records = new PlmnActRecord[numRecords];
136 
137         for(int i = 0; i < numRecords; i++) {
138             records[i] = new PlmnActRecord(recordBytes, i * ENCODED_LENGTH);
139         }
140         return records;
141     }
142 
143     // Parcelable Implementation
144     @Override
describeContents()145     public int describeContents() {
146         return 0;
147     }
148 
149     @Override
writeToParcel(Parcel dest, int flags)150     public void writeToParcel(Parcel dest, int flags) {
151         dest.writeString(plmn);
152         dest.writeInt(accessTechs);
153     }
154 
155     public static final Parcelable.Creator<PlmnActRecord> CREATOR =
156             new Parcelable.Creator<PlmnActRecord>() {
157         @Override
158         public PlmnActRecord createFromParcel(Parcel source) {
159             return new PlmnActRecord(source.readString(), source.readInt());
160         }
161 
162         @Override
163         public PlmnActRecord[] newArray(int size) {
164             return new PlmnActRecord[size];
165         }
166     };
167 
168     @Override
hashCode()169     public int hashCode() {
170         return Objects.hash(plmn, accessTechs);
171     }
172 
173     @Override
equals(Object rhs)174     public boolean equals(Object rhs) {
175         if (!(rhs instanceof PlmnActRecord)) return false;
176 
177         PlmnActRecord r = (PlmnActRecord) rhs;
178         return plmn.equals(r.plmn) && accessTechs == r.accessTechs;
179     }
180 }
181