Utils.java revision 820d73615f338d6c71f2d75aba0ad8410e9eed3e
1package com.android.server.wifi.hotspot2;
2
3import java.nio.ByteBuffer;
4import java.util.ArrayList;
5import java.util.Calendar;
6import java.util.Collection;
7import java.util.LinkedList;
8import java.util.List;
9import java.util.TimeZone;
10
11import static com.android.server.wifi.anqp.Constants.BYTE_MASK;
12import static com.android.server.wifi.anqp.Constants.NIBBLE_MASK;
13
14public abstract class Utils {
15
16    public static final String HS20_TAG = "HS20";
17
18    private static final String[] PLMNText = { "wlan", "mnc*", "mcc*", "3gppnetwork", "org" };
19
20    public static List<String> splitDomain(String domain) {
21
22        if (domain.endsWith("."))
23            domain = domain.substring(0, domain.length() - 1);
24        int at = domain.indexOf('@');
25        if (at >= 0)
26            domain = domain.substring(at + 1);
27
28        String[] labels = domain.toLowerCase().split("\\.");
29        LinkedList<String> labelList = new LinkedList<String>();
30        for (String label : labels) {
31            labelList.addFirst(label);
32        }
33
34        return labelList;
35    }
36
37    public static long parseMac(String s) {
38
39        long mac = 0;
40        int count = 0;
41        for (int n = 0; n < s.length(); n++) {
42            int nibble = Utils.fromHex(s.charAt(n), true);
43            if (nibble >= 0) {
44                mac = (mac << 4) | nibble;
45                count++;
46            }
47        }
48        if (count < 12 || (count&1) == 1) {
49            throw new IllegalArgumentException("Bad MAC address: '" + s + "'");
50        }
51        return mac;
52    }
53
54    public static String getMccMnc(List<String> domain) {
55        if (domain.size() != 5) {
56            return null;
57        }
58
59        for (int n = 4; n >= 0; n-- ) {
60            String expect = PLMNText[n];
61            int len = expect.endsWith("*") ? expect.length() - 1 : expect.length();
62            if (!domain.get(n).regionMatches(0, expect, 0, len)) {
63                return null;
64            }
65        }
66
67        String prefix = domain.get(1).substring(3) + domain.get(2).substring(3);
68        for (int n = 0; n < prefix.length(); n++) {
69            char ch = prefix.charAt(n);
70            if (ch < '0' || ch > '9') {
71                return null;
72            }
73        }
74        return prefix;
75    }
76
77    public static String roamingConsortiumsToString(long[] ois) {
78        if (ois == null) {
79            return "null";
80        }
81        List<Long> list = new ArrayList<Long>(ois.length);
82        for (long oi : ois) {
83            list.add(oi);
84        }
85        return roamingConsortiumsToString(list);
86    }
87
88    public static String roamingConsortiumsToString(Collection<Long> ois) {
89        StringBuilder sb = new StringBuilder();
90        boolean first = true;
91        for (long oi : ois) {
92            if (first) {
93                first = false;
94            } else {
95                sb.append(", ");
96            }
97            if (Long.numberOfLeadingZeros(oi) > 40) {
98                sb.append(String.format("%06x", oi));
99            } else {
100                sb.append(String.format("%010x", oi));
101            }
102        }
103        return sb.toString();
104    }
105
106    public static String toUnicodeEscapedString(String s) {
107        StringBuilder sb = new StringBuilder(s.length());
108        for (int n = 0; n < s.length(); n++) {
109            char ch = s.charAt(n);
110            if (ch>= ' ' && ch < 127) {
111                sb.append(ch);
112            }
113            else {
114                sb.append("\\u").append(String.format("%04x", (int)ch));
115            }
116        }
117        return sb.toString();
118    }
119
120    public static String toHexString(byte[] data) {
121        if (data == null) {
122            return "null";
123        }
124        StringBuilder sb = new StringBuilder(data.length * 3);
125
126        boolean first = true;
127        for (byte b : data) {
128            if (first) {
129                first = false;
130            } else {
131                sb.append(' ');
132            }
133            sb.append(String.format("%02x", b & BYTE_MASK));
134        }
135        return sb.toString();
136    }
137
138    public static String toHex(byte[] octets) {
139        StringBuilder sb = new StringBuilder(octets.length * 2);
140        for (byte o : octets) {
141            sb.append(String.format("%02x", o & BYTE_MASK));
142        }
143        return sb.toString();
144    }
145
146    public static byte[] hexToBytes(String text) {
147        if ((text.length() & 1) == 1) {
148            throw new NumberFormatException("Odd length hex string: " + text.length());
149        }
150        byte[] data = new byte[text.length() >> 1];
151        int position = 0;
152        for (int n = 0; n < text.length(); n += 2) {
153            data[position] =
154                    (byte) (((fromHex(text.charAt(n), false) & NIBBLE_MASK) << 4) |
155                            (fromHex(text.charAt(n + 1), false) & NIBBLE_MASK));
156            position++;
157        }
158        return data;
159    }
160
161    public static int fromHex(char ch, boolean lenient) throws NumberFormatException {
162        if (ch <= '9' && ch >= '0') {
163            return ch - '0';
164        } else if (ch >= 'a' && ch <= 'f') {
165            return ch + 10 - 'a';
166        } else if (ch <= 'F' && ch >= 'A') {
167            return ch + 10 - 'A';
168        } else if (lenient) {
169            return -1;
170        } else {
171            throw new NumberFormatException("Bad hex-character: " + ch);
172        }
173    }
174
175    private static char toAscii(int b) {
176        return b >= ' ' && b < 0x7f ? (char) b : '.';
177    }
178
179    static boolean isDecimal(String s) {
180        for (int n = 0; n < s.length(); n++) {
181            char ch = s.charAt(n);
182            if (ch < '0' || ch > '9') {
183                return false;
184            }
185        }
186        return true;
187    }
188
189    public static <T extends Comparable> int compare(Comparable<T> c1, T c2) {
190        if (c1 == null) {
191            return c2 == null ? 0 : -1;
192        }
193        else if (c2 == null) {
194            return 1;
195        }
196        else {
197            return c1.compareTo(c2);
198        }
199    }
200
201    public static String bytesToBingoCard(ByteBuffer data, int len) {
202        ByteBuffer dup = data.duplicate();
203        dup.limit(dup.position() + len);
204        return bytesToBingoCard(dup);
205    }
206
207    public static String bytesToBingoCard(ByteBuffer data) {
208        ByteBuffer dup = data.duplicate();
209        StringBuilder sbx = new StringBuilder();
210        while (dup.hasRemaining()) {
211            sbx.append(String.format("%02x ", dup.get() & BYTE_MASK));
212        }
213        dup = data.duplicate();
214        sbx.append(' ');
215        while (dup.hasRemaining()) {
216            sbx.append(String.format("%c", toAscii(dup.get() & BYTE_MASK)));
217        }
218        return sbx.toString();
219    }
220
221    public static String toHMS(long millis) {
222        long time = millis >= 0 ? millis : -millis;
223        long tmp = time / 1000L;
224        long ms = time - tmp * 1000L;
225
226        time = tmp;
227        tmp /= 60L;
228        long s = time - tmp * 60L;
229
230        time = tmp;
231        tmp /= 60L;
232        long m = time - tmp * 60L;
233
234        return String.format("%s%d:%02d:%02d.%03d", millis < 0 ? "-" : "", tmp, m, s, ms);
235    }
236
237    public static String toUTCString(long ms) {
238        if (ms < 0) {
239            return "unset";
240        }
241        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
242        c.setTimeInMillis(ms);
243        return String.format("%4d/%02d/%02d %2d:%02d:%02dZ",
244                c.get(Calendar.YEAR),
245                c.get(Calendar.MONTH) + 1,
246                c.get(Calendar.DAY_OF_MONTH),
247                c.get(Calendar.HOUR_OF_DAY),
248                c.get(Calendar.MINUTE),
249                c.get(Calendar.SECOND));
250    }
251
252    public static String unquote(String s) {
253        if (s == null) {
254            return null;
255        }
256        else if (s.startsWith("\"") && s.endsWith("\"")) {
257            return s.substring(1, s.length()-1);
258        }
259        else {
260            return s;
261        }
262    }
263}
264