1 /* 2 * Copyright (C) 2012 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 17 package com.android.bluetooth; 18 19 import android.app.ActivityManager; 20 import android.bluetooth.BluetoothAdapter; 21 import android.bluetooth.BluetoothDevice; 22 import android.content.ContextWrapper; 23 import android.os.Binder; 24 import android.os.ParcelUuid; 25 import android.os.UserHandle; 26 import android.util.Log; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.OutputStream; 31 import java.nio.ByteBuffer; 32 import java.nio.ByteOrder; 33 import java.util.UUID; 34 import java.util.concurrent.TimeUnit; 35 36 /** 37 * @hide 38 */ 39 40 final public class Utils { 41 private static final String TAG = "BluetoothUtils"; 42 private static final int MICROS_PER_UNIT = 625; 43 44 static final int BD_ADDR_LEN = 6; // bytes 45 static final int BD_UUID_LEN = 16; // bytes 46 getAddressStringFromByte(byte[] address)47 public static String getAddressStringFromByte(byte[] address) { 48 if (address == null || address.length != BD_ADDR_LEN) { 49 return null; 50 } 51 52 return String.format("%02X:%02X:%02X:%02X:%02X:%02X", 53 address[0], address[1], address[2], address[3], address[4], 54 address[5]); 55 } 56 getByteAddress(BluetoothDevice device)57 public static byte[] getByteAddress(BluetoothDevice device) { 58 return getBytesFromAddress(device.getAddress()); 59 } 60 getBytesFromAddress(String address)61 public static byte[] getBytesFromAddress(String address) { 62 int i, j = 0; 63 byte[] output = new byte[BD_ADDR_LEN]; 64 65 for (i = 0; i < address.length(); i++) { 66 if (address.charAt(i) != ':') { 67 output[j] = (byte) Integer.parseInt(address.substring(i, i + 2), BD_UUID_LEN); 68 j++; 69 i++; 70 } 71 } 72 73 return output; 74 } 75 byteArrayToInt(byte[] valueBuf)76 public static int byteArrayToInt(byte[] valueBuf) { 77 return byteArrayToInt(valueBuf, 0); 78 } 79 byteArrayToShort(byte[] valueBuf)80 public static short byteArrayToShort(byte[] valueBuf) { 81 ByteBuffer converter = ByteBuffer.wrap(valueBuf); 82 converter.order(ByteOrder.nativeOrder()); 83 return converter.getShort(); 84 } 85 byteArrayToInt(byte[] valueBuf, int offset)86 public static int byteArrayToInt(byte[] valueBuf, int offset) { 87 ByteBuffer converter = ByteBuffer.wrap(valueBuf); 88 converter.order(ByteOrder.nativeOrder()); 89 return converter.getInt(offset); 90 } 91 intToByteArray(int value)92 public static byte[] intToByteArray(int value) { 93 ByteBuffer converter = ByteBuffer.allocate(4); 94 converter.order(ByteOrder.nativeOrder()); 95 converter.putInt(value); 96 return converter.array(); 97 } 98 uuidToByteArray(ParcelUuid pUuid)99 public static byte[] uuidToByteArray(ParcelUuid pUuid) { 100 int length = BD_UUID_LEN; 101 ByteBuffer converter = ByteBuffer.allocate(length); 102 converter.order(ByteOrder.BIG_ENDIAN); 103 long msb, lsb; 104 UUID uuid = pUuid.getUuid(); 105 msb = uuid.getMostSignificantBits(); 106 lsb = uuid.getLeastSignificantBits(); 107 converter.putLong(msb); 108 converter.putLong(8, lsb); 109 return converter.array(); 110 } 111 uuidsToByteArray(ParcelUuid[] uuids)112 public static byte[] uuidsToByteArray(ParcelUuid[] uuids) { 113 int length = uuids.length * BD_UUID_LEN; 114 ByteBuffer converter = ByteBuffer.allocate(length); 115 converter.order(ByteOrder.BIG_ENDIAN); 116 UUID uuid; 117 long msb, lsb; 118 for (int i = 0; i < uuids.length; i++) { 119 uuid = uuids[i].getUuid(); 120 msb = uuid.getMostSignificantBits(); 121 lsb = uuid.getLeastSignificantBits(); 122 converter.putLong(i * BD_UUID_LEN, msb); 123 converter.putLong(i * BD_UUID_LEN + 8, lsb); 124 } 125 return converter.array(); 126 } 127 byteArrayToUuid(byte[] val)128 public static ParcelUuid[] byteArrayToUuid(byte[] val) { 129 int numUuids = val.length / BD_UUID_LEN; 130 ParcelUuid[] puuids = new ParcelUuid[numUuids]; 131 UUID uuid; 132 int offset = 0; 133 134 ByteBuffer converter = ByteBuffer.wrap(val); 135 converter.order(ByteOrder.BIG_ENDIAN); 136 137 for (int i = 0; i < numUuids; i++) { 138 puuids[i] = new ParcelUuid(new UUID(converter.getLong(offset), 139 converter.getLong(offset + 8))); 140 offset += BD_UUID_LEN; 141 } 142 return puuids; 143 } 144 debugGetAdapterStateString(int state)145 public static String debugGetAdapterStateString(int state) { 146 switch (state) { 147 case BluetoothAdapter.STATE_OFF: 148 return "STATE_OFF"; 149 case BluetoothAdapter.STATE_ON: 150 return "STATE_ON"; 151 case BluetoothAdapter.STATE_TURNING_ON: 152 return "STATE_TURNING_ON"; 153 case BluetoothAdapter.STATE_TURNING_OFF: 154 return "STATE_TURNING_OFF"; 155 default: 156 return "UNKNOWN"; 157 } 158 } 159 copyStream(InputStream is, OutputStream os, int bufferSize)160 public static void copyStream(InputStream is, OutputStream os, int bufferSize) 161 throws IOException { 162 if (is != null && os != null) { 163 byte[] buffer = new byte[bufferSize]; 164 int bytesRead = 0; 165 while ((bytesRead = is.read(buffer)) >= 0) { 166 os.write(buffer, 0, bytesRead); 167 } 168 } 169 } 170 safeCloseStream(InputStream is)171 public static void safeCloseStream(InputStream is) { 172 if (is != null) { 173 try { 174 is.close(); 175 } catch (Throwable t) { 176 Log.d(TAG, "Error closing stream", t); 177 } 178 } 179 } 180 safeCloseStream(OutputStream os)181 public static void safeCloseStream(OutputStream os) { 182 if (os != null) { 183 try { 184 os.close(); 185 } catch (Throwable t) { 186 Log.d(TAG, "Error closing stream", t); 187 } 188 } 189 } 190 checkCaller()191 public static boolean checkCaller() { 192 boolean ok; 193 // Get the caller's user id then clear the calling identity 194 // which will be restored in the finally clause. 195 int callingUser = UserHandle.getCallingUserId(); 196 long ident = Binder.clearCallingIdentity(); 197 198 try { 199 // With calling identity cleared the current user is the foreground user. 200 int foregroundUser = ActivityManager.getCurrentUser(); 201 ok = (foregroundUser == callingUser); 202 } catch (Exception ex) { 203 Log.e(TAG, "checkIfCallerIsSelfOrForegroundUser: Exception ex=" + ex); 204 ok = false; 205 } finally { 206 Binder.restoreCallingIdentity(ident); 207 } 208 return ok; 209 } 210 211 /** 212 * Enforce the context has android.Manifest.permission.BLUETOOTH_ADMIN permission. A 213 * {@link SecurityException} would be thrown if neither the calling process or the application 214 * does not have BLUETOOTH_ADMIN permission. 215 * 216 * @param context Context for the permission check. 217 */ enforceAdminPermission(ContextWrapper context)218 public static void enforceAdminPermission(ContextWrapper context) { 219 context.enforceCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_ADMIN, 220 "Need BLUETOOTH_ADMIN permission"); 221 } 222 223 /** 224 * Converts {@code millisecond} to unit. Each unit is 0.625 millisecond. 225 */ millsToUnit(int milliseconds)226 public static int millsToUnit(int milliseconds) { 227 return (int) (TimeUnit.MILLISECONDS.toMicros(milliseconds) / MICROS_PER_UNIT); 228 } 229 } 230