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