Utils.java revision d2fc8cbd87c7a742223e8742a442a48690d426ce
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 17package com.android.bluetooth; 18 19import android.app.ActivityManager; 20import android.app.ActivityThread; 21import android.app.AppOpsManager; 22import android.bluetooth.BluetoothAdapter; 23import android.bluetooth.BluetoothDevice; 24import android.content.Context; 25import android.content.ContextWrapper; 26import android.content.pm.PackageManager; 27import android.content.pm.UserInfo; 28import android.os.Binder; 29import android.os.ParcelUuid; 30import android.os.Process; 31import android.os.UserHandle; 32import android.os.UserManager; 33import android.util.Log; 34 35import java.io.IOException; 36import java.io.InputStream; 37import java.io.OutputStream; 38import java.nio.ByteBuffer; 39import java.nio.ByteOrder; 40import java.util.UUID; 41import java.util.concurrent.TimeUnit; 42 43/** 44 * @hide 45 */ 46 47final public class Utils { 48 private static final String TAG = "BluetoothUtils"; 49 private static final int MICROS_PER_UNIT = 625; 50 51 static final int BD_ADDR_LEN = 6; // bytes 52 static final int BD_UUID_LEN = 16; // bytes 53 54 public static String getAddressStringFromByte(byte[] address) { 55 if (address == null || address.length != BD_ADDR_LEN) { 56 return null; 57 } 58 59 return String.format("%02X:%02X:%02X:%02X:%02X:%02X", 60 address[0], address[1], address[2], address[3], address[4], 61 address[5]); 62 } 63 64 public static byte[] getByteAddress(BluetoothDevice device) { 65 return getBytesFromAddress(device.getAddress()); 66 } 67 68 public static byte[] getBytesFromAddress(String address) { 69 int i, j = 0; 70 byte[] output = new byte[BD_ADDR_LEN]; 71 72 for (i = 0; i < address.length(); i++) { 73 if (address.charAt(i) != ':') { 74 output[j] = (byte) Integer.parseInt(address.substring(i, i + 2), BD_UUID_LEN); 75 j++; 76 i++; 77 } 78 } 79 80 return output; 81 } 82 83 public static int byteArrayToInt(byte[] valueBuf) { 84 return byteArrayToInt(valueBuf, 0); 85 } 86 87 public static short byteArrayToShort(byte[] valueBuf) { 88 ByteBuffer converter = ByteBuffer.wrap(valueBuf); 89 converter.order(ByteOrder.nativeOrder()); 90 return converter.getShort(); 91 } 92 93 public static int byteArrayToInt(byte[] valueBuf, int offset) { 94 ByteBuffer converter = ByteBuffer.wrap(valueBuf); 95 converter.order(ByteOrder.nativeOrder()); 96 return converter.getInt(offset); 97 } 98 99 public static byte[] intToByteArray(int value) { 100 ByteBuffer converter = ByteBuffer.allocate(4); 101 converter.order(ByteOrder.nativeOrder()); 102 converter.putInt(value); 103 return converter.array(); 104 } 105 106 public static byte[] uuidToByteArray(ParcelUuid pUuid) { 107 int length = BD_UUID_LEN; 108 ByteBuffer converter = ByteBuffer.allocate(length); 109 converter.order(ByteOrder.BIG_ENDIAN); 110 long msb, lsb; 111 UUID uuid = pUuid.getUuid(); 112 msb = uuid.getMostSignificantBits(); 113 lsb = uuid.getLeastSignificantBits(); 114 converter.putLong(msb); 115 converter.putLong(8, lsb); 116 return converter.array(); 117 } 118 119 public static byte[] uuidsToByteArray(ParcelUuid[] uuids) { 120 int length = uuids.length * BD_UUID_LEN; 121 ByteBuffer converter = ByteBuffer.allocate(length); 122 converter.order(ByteOrder.BIG_ENDIAN); 123 UUID uuid; 124 long msb, lsb; 125 for (int i = 0; i < uuids.length; i++) { 126 uuid = uuids[i].getUuid(); 127 msb = uuid.getMostSignificantBits(); 128 lsb = uuid.getLeastSignificantBits(); 129 converter.putLong(i * BD_UUID_LEN, msb); 130 converter.putLong(i * BD_UUID_LEN + 8, lsb); 131 } 132 return converter.array(); 133 } 134 135 public static ParcelUuid[] byteArrayToUuid(byte[] val) { 136 int numUuids = val.length / BD_UUID_LEN; 137 ParcelUuid[] puuids = new ParcelUuid[numUuids]; 138 UUID uuid; 139 int offset = 0; 140 141 ByteBuffer converter = ByteBuffer.wrap(val); 142 converter.order(ByteOrder.BIG_ENDIAN); 143 144 for (int i = 0; i < numUuids; i++) { 145 puuids[i] = new ParcelUuid(new UUID(converter.getLong(offset), 146 converter.getLong(offset + 8))); 147 offset += BD_UUID_LEN; 148 } 149 return puuids; 150 } 151 152 public static String debugGetAdapterStateString(int state) { 153 switch (state) { 154 case BluetoothAdapter.STATE_OFF: 155 return "STATE_OFF"; 156 case BluetoothAdapter.STATE_ON: 157 return "STATE_ON"; 158 case BluetoothAdapter.STATE_TURNING_ON: 159 return "STATE_TURNING_ON"; 160 case BluetoothAdapter.STATE_TURNING_OFF: 161 return "STATE_TURNING_OFF"; 162 default: 163 return "UNKNOWN"; 164 } 165 } 166 167 public static void copyStream(InputStream is, OutputStream os, int bufferSize) 168 throws IOException { 169 if (is != null && os != null) { 170 byte[] buffer = new byte[bufferSize]; 171 int bytesRead = 0; 172 while ((bytesRead = is.read(buffer)) >= 0) { 173 os.write(buffer, 0, bytesRead); 174 } 175 } 176 } 177 178 public static void safeCloseStream(InputStream is) { 179 if (is != null) { 180 try { 181 is.close(); 182 } catch (Throwable t) { 183 Log.d(TAG, "Error closing stream", t); 184 } 185 } 186 } 187 188 public static void safeCloseStream(OutputStream os) { 189 if (os != null) { 190 try { 191 os.close(); 192 } catch (Throwable t) { 193 Log.d(TAG, "Error closing stream", t); 194 } 195 } 196 } 197 198 public static boolean checkCaller() { 199 boolean ok; 200 // Get the caller's user id then clear the calling identity 201 // which will be restored in the finally clause. 202 int callingUser = UserHandle.getCallingUserId(); 203 int callingUid = Binder.getCallingUid(); 204 long ident = Binder.clearCallingIdentity(); 205 206 try { 207 // With calling identity cleared the current user is the foreground user. 208 int foregroundUser = ActivityManager.getCurrentUser(); 209 ok = (foregroundUser == callingUser); 210 if (!ok) { 211 // Always allow SystemUI/System access. 212 int systemUiUid = ActivityThread.getPackageManager().getPackageUid( 213 "com.android.systemui", UserHandle.USER_OWNER); 214 ok = (systemUiUid == callingUid) || (Process.SYSTEM_UID == callingUid); 215 } 216 } catch (Exception ex) { 217 Log.e(TAG, "checkIfCallerIsSelfOrForegroundUser: Exception ex=" + ex); 218 ok = false; 219 } finally { 220 Binder.restoreCallingIdentity(ident); 221 } 222 return ok; 223 } 224 225 public static boolean checkCallerAllowManagedProfiles(Context mContext) { 226 if (mContext == null) { 227 return checkCaller(); 228 } 229 boolean ok; 230 // Get the caller's user id and if it's a managed profile, get it's parents 231 // id, then clear the calling identity 232 // which will be restored in the finally clause. 233 int callingUser = UserHandle.getCallingUserId(); 234 int callingUid = Binder.getCallingUid(); 235 long ident = Binder.clearCallingIdentity(); 236 try { 237 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 238 UserInfo ui = um.getProfileParent(callingUser); 239 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 240 // With calling identity cleared the current user is the foreground user. 241 int foregroundUser = ActivityManager.getCurrentUser(); 242 ok = (foregroundUser == callingUser) || 243 (foregroundUser == parentUser); 244 if (!ok) { 245 // Always allow SystemUI/System access. 246 int systemUiUid = ActivityThread.getPackageManager().getPackageUid( 247 "com.android.systemui", UserHandle.USER_OWNER); 248 ok = (systemUiUid == callingUid) || (Process.SYSTEM_UID == callingUid); 249 } 250 } catch (Exception ex) { 251 Log.e(TAG, "checkCallerAllowManagedProfiles: Exception ex=" + ex); 252 ok = false; 253 } finally { 254 Binder.restoreCallingIdentity(ident); 255 } 256 return ok; 257 } 258 259 /** 260 * Enforce the context has android.Manifest.permission.BLUETOOTH_ADMIN permission. A 261 * {@link SecurityException} would be thrown if neither the calling process or the application 262 * does not have BLUETOOTH_ADMIN permission. 263 * 264 * @param context Context for the permission check. 265 */ 266 public static void enforceAdminPermission(ContextWrapper context) { 267 context.enforceCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_ADMIN, 268 "Need BLUETOOTH_ADMIN permission"); 269 } 270 271 /** 272 * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION or 273 * android.Manifest.permission.ACCESS_FINE_LOCATION and a corresponding app op is allowed 274 */ 275 public static boolean checkCallerHasLocationPermission(Context context, AppOpsManager appOps, 276 String callingPackage) { 277 if (context.checkCallingOrSelfPermission(android.Manifest.permission. 278 ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED 279 && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { 280 return true; 281 } 282 283 return context.checkCallingOrSelfPermission(android.Manifest.permission. 284 ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED 285 && isAppOppAllowed(appOps, AppOpsManager.OP_COARSE_LOCATION, callingPackage); 286 } 287 288 private static boolean isAppOppAllowed(AppOpsManager appOps, int op, String callingPackage) { 289 return appOps.noteOp(op, Binder.getCallingUid(), callingPackage) 290 == AppOpsManager.MODE_ALLOWED; 291 } 292 293 /** 294 * Converts {@code millisecond} to unit. Each unit is 0.625 millisecond. 295 */ 296 public static int millsToUnit(int milliseconds) { 297 return (int) (TimeUnit.MILLISECONDS.toMicros(milliseconds) / MICROS_PER_UNIT); 298 } 299} 300