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