Utils.java revision ef1567e413c9ed5f5c4fdb9e354861632f7b2f87
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 int[] 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 try { 65 int[] mccMnc = new int[2]; 66 mccMnc[0] = Integer.parseInt(domain.get(1).substring(3)); 67 mccMnc[1] = Integer.parseInt(domain.get(2).substring(3)); 68 return mccMnc; 69 } 70 catch (NumberFormatException nfe) { 71 return null; 72 } 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 byte[] hexToBytes(String text) { 137 if ((text.length() & 1) == 1) { 138 throw new NumberFormatException("Odd length hex string: " + text.length()); 139 } 140 byte[] data = new byte[text.length() >> 1]; 141 int position = 0; 142 for (int n = 0; n < text.length(); n += 2) { 143 data[position] = 144 (byte) (((fromHex(text.charAt(n), false) & NIBBLE_MASK) << 4) | 145 (fromHex(text.charAt(n + 1), false) & NIBBLE_MASK)); 146 position++; 147 } 148 return data; 149 } 150 151 public static int fromHex(char ch, boolean lenient) throws NumberFormatException { 152 if (ch <= '9' && ch >= '0') { 153 return ch - '0'; 154 } else if (ch >= 'a' && ch <= 'f') { 155 return ch + 10 - 'a'; 156 } else if (ch <= 'F' && ch >= 'A') { 157 return ch + 10 - 'A'; 158 } else if (lenient) { 159 return -1; 160 } else { 161 throw new NumberFormatException("Bad hex-character: " + ch); 162 } 163 } 164 165 private static char toAscii(int b) { 166 return b >= ' ' && b < 0x7f ? (char) b : '.'; 167 } 168 169 static boolean isDecimal(String s) { 170 for (int n = 0; n < s.length(); n++) { 171 char ch = s.charAt(n); 172 if (ch < '0' || ch > '9') { 173 return false; 174 } 175 } 176 return true; 177 } 178 179 public static <T extends Comparable> int compare(Comparable<T> c1, T c2) { 180 if (c1 == null) { 181 return c2 == null ? 0 : -1; 182 } 183 else if (c2 == null) { 184 return 1; 185 } 186 else { 187 return c1.compareTo(c2); 188 } 189 } 190 191 public static String bytesToBingoCard(ByteBuffer data, int len) { 192 ByteBuffer dup = data.duplicate(); 193 dup.limit(dup.position() + len); 194 return bytesToBingoCard(dup); 195 } 196 197 public static String bytesToBingoCard(ByteBuffer data) { 198 ByteBuffer dup = data.duplicate(); 199 StringBuilder sbx = new StringBuilder(); 200 while (dup.hasRemaining()) { 201 sbx.append(String.format("%02x ", dup.get() & BYTE_MASK)); 202 } 203 dup = data.duplicate(); 204 sbx.append(' '); 205 while (dup.hasRemaining()) { 206 sbx.append(String.format("%c", toAscii(dup.get() & BYTE_MASK))); 207 } 208 return sbx.toString(); 209 } 210 211 public static String toUTCString(long ms) { 212 if (ms < 0) { 213 return "unset"; 214 } 215 Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 216 c.setTimeInMillis(ms); 217 return String.format("%4d/%02d/%02d %2d:%02d:%02dZ", 218 c.get(Calendar.YEAR), 219 c.get(Calendar.MONTH) + 1, 220 c.get(Calendar.DAY_OF_MONTH), 221 c.get(Calendar.HOUR_OF_DAY), 222 c.get(Calendar.MINUTE), 223 c.get(Calendar.SECOND)); 224 } 225} 226