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
17package com.android.internal.telephony.uicc;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.telephony.Rlog;
22
23import java.util.Arrays;
24
25/**
26 * {@hide}
27 */
28public class PlmnActRecord implements Parcelable {
29    private static final String LOG_TAG = "PlmnActRecord";
30
31    // Values specified in 3GPP 31.102 sec. 4.2.5
32    public static final int ACCESS_TECH_UTRAN = 0x8000;
33    public static final int ACCESS_TECH_EUTRAN = 0x4000;
34    public static final int ACCESS_TECH_GSM = 0x0080;
35    public static final int ACCESS_TECH_GSM_COMPACT = 0x0040;
36    public static final int ACCESS_TECH_CDMA2000_HRPD = 0x0020;
37    public static final int ACCESS_TECH_CDMA2000_1XRTT = 0x0010;
38    public static final int ACCESS_TECH_RESERVED = 0x3F0F;
39
40    public static final int ENCODED_LENGTH = 5;
41
42    public final String plmn;
43    public final int accessTechs;
44
45    private static final boolean VDBG = false;
46
47    public static final Parcelable.Creator<PlmnActRecord> CREATOR =
48            new Parcelable.Creator<PlmnActRecord>() {
49        @Override
50        public PlmnActRecord createFromParcel(Parcel source) {
51            return new PlmnActRecord(source.readString(), source.readInt());
52        }
53
54        @Override
55        public PlmnActRecord[] newArray(int size) {
56            return new PlmnActRecord[size];
57        }
58    };
59
60    /* From 3gpp 31.102 section 4.2.5
61     * Bytes 0-2 bcd-encoded PLMN-ID
62     * Bytes 3-4 bitfield of access technologies
63     */
64    public PlmnActRecord(byte[] bytes, int offset) {
65        if (VDBG) Rlog.v(LOG_TAG, "Creating PlmnActRecord " + offset);
66        this.plmn = IccUtils.bcdPlmnToString(bytes, offset);
67        this.accessTechs = ((int) bytes[offset + 3] << 8) | bytes[offset + 4];
68    }
69
70    private PlmnActRecord(String plmn, int accessTechs) {
71        this.plmn = plmn;
72        this.accessTechs = accessTechs;
73    }
74
75    private String accessTechString() {
76        if (accessTechs == 0) {
77            return "NONE";
78        }
79
80        StringBuilder sb = new StringBuilder();
81        if ((accessTechs & ACCESS_TECH_UTRAN) != 0) {
82            sb.append("UTRAN|");
83        }
84        if ((accessTechs & ACCESS_TECH_EUTRAN) != 0) {
85            sb.append("EUTRAN|");
86        }
87        if ((accessTechs & ACCESS_TECH_GSM) != 0) {
88            sb.append("GSM|");
89        }
90        if ((accessTechs & ACCESS_TECH_GSM_COMPACT) != 0) {
91            sb.append("GSM_COMPACT|");
92        }
93        if ((accessTechs & ACCESS_TECH_CDMA2000_HRPD) != 0) {
94            sb.append("CDMA2000_HRPD|");
95        }
96        if ((accessTechs & ACCESS_TECH_CDMA2000_1XRTT) != 0) {
97            sb.append("CDMA2000_1XRTT|");
98        }
99        if ((accessTechs & ACCESS_TECH_RESERVED) != 0) {
100            sb.append(String.format("UNKNOWN:%x|", accessTechs & ACCESS_TECH_RESERVED));
101        }
102        // Trim the tailing pipe character
103        return sb.substring(0, sb.length() - 1);
104    }
105
106    @Override
107    public String toString() {
108        return String.format("{PLMN=%s,AccessTechs=%s}", plmn, accessTechString());
109    }
110
111    /**
112     * Convenience method for extracting all records from encoded bytes
113     */
114    public static PlmnActRecord[] getRecords(byte[] recordBytes) {
115        if (recordBytes == null || recordBytes.length == 0
116                || recordBytes.length % ENCODED_LENGTH != 0) {
117            Rlog.e(LOG_TAG, "Malformed PlmnActRecord, bytes: "
118                    + ((recordBytes != null) ? Arrays.toString(recordBytes) : null));
119            return null;
120        }
121        int numRecords = recordBytes.length / ENCODED_LENGTH;
122        if (VDBG) Rlog.v(LOG_TAG, "Extracting Logs, count=" + numRecords);
123
124        PlmnActRecord[] records = new PlmnActRecord[numRecords];
125
126        for(int i = 0; i < numRecords; i++) {
127            records[i] = new PlmnActRecord(recordBytes, i * ENCODED_LENGTH);
128        }
129        return records;
130    }
131
132    // Parcelable Implementation
133    @Override
134    public int describeContents() {
135        return 0;
136    }
137
138    @Override
139    public void writeToParcel(Parcel dest, int flags) {
140        dest.writeString(plmn);
141        dest.writeInt(accessTechs);
142    }
143
144}
145