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