NativeUtil.java revision 6a8908d2bc0367397eb92444ac78cc8d43160ef6
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi.util; 18 19import libcore.util.HexEncoding; 20 21import java.nio.ByteBuffer; 22import java.nio.CharBuffer; 23import java.nio.charset.CharacterCodingException; 24import java.nio.charset.CharsetDecoder; 25import java.nio.charset.StandardCharsets; 26import java.util.ArrayList; 27 28/** 29 * Provide utility functions for native interfacing modules. 30 */ 31public class NativeUtil { 32 private static final String ANY_MAC_STR = "any"; 33 private static final byte[] ANY_MAC_BYTES = {0, 0, 0, 0, 0, 0}; 34 private static final int MAC_LENGTH = 6; 35 private static final int MAC_OUI_LENGTH = 3; 36 private static final int MAC_STR_LENGTH = MAC_LENGTH * 2 + 5; 37 38 /** 39 * Convert the string to byte array list. 40 * 41 * @return the UTF_8 char byte values of str, as an ArrayList. 42 * @throws IllegalArgumentException if a null string is sent. 43 */ 44 public static ArrayList<Byte> stringToByteArrayList(String str) { 45 if (str == null) { 46 throw new IllegalArgumentException("null string"); 47 } 48 ArrayList<Byte> byteArrayList = new ArrayList<Byte>(); 49 for (byte b : str.getBytes(StandardCharsets.UTF_8)) { 50 byteArrayList.add(new Byte(b)); 51 } 52 return byteArrayList; 53 } 54 55 /** 56 * Convert the byte array list to string. 57 * 58 * @return the string decoded from UTF_8 byte values in byteArrayList. 59 * @throws IllegalArgumentException if a null byte array list is sent. 60 */ 61 public static String stringFromByteArrayList(ArrayList<Byte> byteArrayList) { 62 if (byteArrayList == null) { 63 throw new IllegalArgumentException("null byte array list"); 64 } 65 byte[] byteArray = new byte[byteArrayList.size()]; 66 int i = 0; 67 for (Byte b : byteArrayList) { 68 byteArray[i] = b; 69 i++; 70 } 71 return new String(byteArray, StandardCharsets.UTF_8); 72 } 73 74 /** 75 * Convert the string to byte array. 76 * 77 * @return the UTF_8 char byte values of str, as an Array. 78 * @throws IllegalArgumentException if a null string is sent. 79 */ 80 public static byte[] stringToByteArray(String str) { 81 if (str == null) { 82 throw new IllegalArgumentException("null string"); 83 } 84 return str.getBytes(StandardCharsets.UTF_8); 85 } 86 87 /** 88 * Convert the byte array list to string. 89 * 90 * @return the string decoded from UTF_8 byte values in byteArray. 91 * @throws IllegalArgumentException if a null byte array is sent. 92 */ 93 public static String stringFromByteArray(byte[] byteArray) { 94 if (byteArray == null) { 95 throw new IllegalArgumentException("null byte array"); 96 } 97 return new String(byteArray); 98 } 99 100 /** 101 * Converts a mac address string to an array of Bytes. 102 * 103 * @param macStr string of format: "XX:XX:XX:XX:XX:XX" or "XXXXXXXXXXXX", where X is any 104 * hexadecimal digit. 105 * Passing "any" is the same as 00:00:00:00:00:00 106 * @throws IllegalArgumentException for various malformed inputs. 107 */ 108 public static byte[] macAddressToByteArray(String macStr) { 109 if (macStr == null) { 110 throw new IllegalArgumentException("null mac string"); 111 } 112 if (ANY_MAC_STR.equals(macStr)) return ANY_MAC_BYTES; 113 String cleanMac = macStr.replace(":", ""); 114 if (cleanMac.length() != MAC_LENGTH * 2) { 115 throw new IllegalArgumentException("invalid mac string length: " + cleanMac); 116 } 117 return HexEncoding.decode(cleanMac.toCharArray(), false); 118 } 119 120 /** 121 * Converts an array of 6 bytes to a HexEncoded String with format: "XX:XX:XX:XX:XX:XX", where X 122 * is any hexadecimal digit. 123 * 124 * @param macArray byte array of mac values, must have length 6 125 * @throws IllegalArgumentException for malformed inputs. 126 */ 127 public static String macAddressFromByteArray(byte[] macArray) { 128 if (macArray == null) { 129 throw new IllegalArgumentException("null mac bytes"); 130 } 131 if (macArray.length != MAC_LENGTH) { 132 throw new IllegalArgumentException("invalid macArray length: " + macArray.length); 133 } 134 StringBuilder sb = new StringBuilder(MAC_STR_LENGTH); 135 for (int i = 0; i < macArray.length; i++) { 136 if (i != 0) sb.append(":"); 137 sb.append(new String(HexEncoding.encode(macArray, i, 1))); 138 } 139 return sb.toString().toLowerCase(); 140 } 141 142 /** 143 * Converts a mac address OUI string to an array of Bytes. 144 * 145 * @param macStr string of format: "XX:XX:XX" or "XXXXXX", where X is any hexadecimal digit. 146 * @throws IllegalArgumentException for various malformed inputs. 147 */ 148 public static byte[] macAddressOuiToByteArray(String macStr) { 149 if (macStr == null) { 150 throw new IllegalArgumentException("null mac string"); 151 } 152 String cleanMac = macStr.replace(":", ""); 153 if (cleanMac.length() != MAC_OUI_LENGTH * 2) { 154 throw new IllegalArgumentException("invalid mac oui string length: " + cleanMac); 155 } 156 return HexEncoding.decode(cleanMac.toCharArray(), false); 157 } 158 159 /** 160 * Remove enclosed quotes of the provided string. 161 * 162 * @param quotedStr String to be unquoted. 163 * @return String without the enclosing quotes. 164 */ 165 public static String removeEnclosingQuotes(String quotedStr) { 166 int length = quotedStr.length(); 167 if ((length >= 2) 168 && (quotedStr.charAt(0) == '"') && (quotedStr.charAt(length - 1) == '"')) { 169 return quotedStr.substring(1, length - 1); 170 } 171 return quotedStr; 172 } 173 174 /** 175 * Converts an string to an arraylist of UTF_8 byte values. 176 * These forms are acceptable: 177 * a) ASCII String encapsulated in quotes, or 178 * b) Hex string with no delimiters. 179 * 180 * @param str String to be converted. 181 * @throws IllegalArgumentException for null string. 182 */ 183 public static ArrayList<Byte> hexOrQuotedAsciiStringToBytes(String str) { 184 if (str == null) { 185 throw new IllegalArgumentException("null string"); 186 } 187 int length = str.length(); 188 if ((length > 1) && (str.charAt(0) == '"') && (str.charAt(length - 1) == '"')) { 189 str = str.substring(1, str.length() - 1); 190 return stringToByteArrayList(str); 191 } else { 192 return byteArrayToArrayList(hexStringToByteArray(str)); 193 } 194 } 195 196 /** 197 * Converts an ArrayList<Byte> of UTF_8 byte values to string. 198 * The string will either be: 199 * a) ASCII String encapsulated in quotes (if all the bytes are ASCII encodeable and non null), 200 * or 201 * b) Hex string with no delimiters. 202 * 203 * @param bytes List of bytes for ssid. 204 * @throws IllegalArgumentException for null bytes. 205 */ 206 public static String bytesToHexOrQuotedAsciiString(ArrayList<Byte> bytes) { 207 if (bytes == null) { 208 throw new IllegalArgumentException("null ssid bytes"); 209 } 210 byte[] byteArray = byteArrayFromArrayList(bytes); 211 // Check for 0's in the byte stream in which case we cannot convert this into a string. 212 if (!bytes.contains(Byte.valueOf((byte) 0))) { 213 CharsetDecoder decoder = StandardCharsets.US_ASCII.newDecoder(); 214 try { 215 CharBuffer decoded = decoder.decode(ByteBuffer.wrap(byteArray)); 216 return "\"" + decoded.toString() + "\""; 217 } catch (CharacterCodingException cce) { 218 } 219 } 220 return hexStringFromByteArray(byteArray); 221 } 222 223 /** 224 * Converts an ssid string to an arraylist of UTF_8 byte values. 225 * These forms are acceptable: 226 * a) ASCII String encapsulated in quotes, or 227 * b) Hex string with no delimiters. 228 * 229 * @param ssidStr String to be converted. 230 * @throws IllegalArgumentException for null string. 231 */ 232 public static ArrayList<Byte> decodeSsid(String ssidStr) { 233 return hexOrQuotedAsciiStringToBytes(ssidStr); 234 } 235 236 /** 237 * Converts an ArrayList<Byte> of UTF_8 byte values to ssid string. 238 * The string will either be: 239 * a) ASCII String encapsulated in quotes (if all the bytes are ASCII encodeable and non null), 240 * or 241 * b) Hex string with no delimiters. 242 * 243 * @param ssidBytes List of bytes for ssid. 244 * @throws IllegalArgumentException for null bytes. 245 */ 246 public static String encodeSsid(ArrayList<Byte> ssidBytes) { 247 return bytesToHexOrQuotedAsciiString(ssidBytes); 248 } 249 250 /** 251 * Convert from an array of primitive bytes to an array list of Byte. 252 */ 253 public static ArrayList<Byte> byteArrayToArrayList(byte[] bytes) { 254 ArrayList<Byte> byteList = new ArrayList<>(); 255 for (Byte b : bytes) { 256 byteList.add(b); 257 } 258 return byteList; 259 } 260 261 /** 262 * Convert from an array list of Byte to an array of primitive bytes. 263 */ 264 public static byte[] byteArrayFromArrayList(ArrayList<Byte> bytes) { 265 byte[] byteArray = new byte[bytes.size()]; 266 int i = 0; 267 for (Byte b : bytes) { 268 byteArray[i++] = b; 269 } 270 return byteArray; 271 } 272 273 /** 274 * Converts a hex string to byte array. 275 * 276 * @param hexStr String to be converted. 277 * @throws IllegalArgumentException for null string. 278 */ 279 public static byte[] hexStringToByteArray(String hexStr) { 280 if (hexStr == null) { 281 throw new IllegalArgumentException("null hex string"); 282 } 283 return HexEncoding.decode(hexStr.toCharArray(), false); 284 } 285 286 /** 287 * Converts a byte array to hex string. 288 * 289 * @param bytes List of bytes for ssid. 290 * @throws IllegalArgumentException for null bytes. 291 */ 292 public static String hexStringFromByteArray(byte[] bytes) { 293 if (bytes == null) { 294 throw new IllegalArgumentException("null hex bytes"); 295 } 296 return new String(HexEncoding.encode(bytes)).toLowerCase(); 297 } 298} 299