1ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/* 2ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Copyright (C) 2012 The Android Open Source Project 3ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 4ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * you may not use this file except in compliance with the License. 6ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * You may obtain a copy of the License at 7ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 8ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 10ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Unless required by applicable law or agreed to in writing, software 11ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * See the License for the specific language governing permissions and 14ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * limitations under the License. 15ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */ 16ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 17ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshpackage com.android.bluetooth; 18ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 1937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport android.app.ActivityManager; 20465bbd2160749d9e0a3f3aabeb4e20bb51573001Jason Monkimport android.app.ActivityThread; 21d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolovimport android.app.AppOpsManager; 226654f5c903de510a70f9e72cd5ad7837b615d93ffredcimport android.bluetooth.BluetoothAdapter; 2374ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.bluetooth.BluetoothDevice; 242287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franzimport android.content.Context; 2527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wangimport android.content.ContextWrapper; 26d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolovimport android.content.pm.PackageManager; 272287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franzimport android.content.pm.UserInfo; 2837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport android.os.Binder; 29586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolovimport android.os.Build; 30ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.os.ParcelUuid; 318e6936eae2f949066dcc6e2e66a48ffa50450402Santos Cordonimport android.os.Process; 3237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport android.os.UserHandle; 332287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franzimport android.os.UserManager; 34c7a57f31515107366589bd6875c3cc4af1fc806efredcimport android.util.Log; 35ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 36c7a57f31515107366589bd6875c3cc4af1fc806efredcimport java.io.IOException; 37c7a57f31515107366589bd6875c3cc4af1fc806efredcimport java.io.InputStream; 38c7a57f31515107366589bd6875c3cc4af1fc806efredcimport java.io.OutputStream; 39ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.nio.ByteBuffer; 40ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.nio.ByteOrder; 411b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolovimport java.util.List; 42ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.util.UUID; 4396509d5ff7109bc42a4c25143f70ec41a127d109Wei Wangimport java.util.concurrent.TimeUnit; 44ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 45ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/** 46ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * @hide 47ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */ 48ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 49ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshfinal public class Utils { 50c7a57f31515107366589bd6875c3cc4af1fc806efredc private static final String TAG = "BluetoothUtils"; 5196509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang private static final int MICROS_PER_UNIT = 625; 5296509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang 53ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh static final int BD_ADDR_LEN = 6; // bytes 54ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh static final int BD_UUID_LEN = 16; // bytes 55ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 56ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static String getAddressStringFromByte(byte[] address) { 5727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (address == null || address.length != BD_ADDR_LEN) { 586654f5c903de510a70f9e72cd5ad7837b615d93ffredc return null; 596654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 606654f5c903de510a70f9e72cd5ad7837b615d93ffredc 61ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return String.format("%02X:%02X:%02X:%02X:%02X:%02X", 62ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh address[0], address[1], address[2], address[3], address[4], 63ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh address[5]); 64ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 65ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 6674ae04c73312403e89db0f8e9bd9601d403b4783fredc public static byte[] getByteAddress(BluetoothDevice device) { 6774ae04c73312403e89db0f8e9bd9601d403b4783fredc return getBytesFromAddress(device.getAddress()); 6874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 6974ae04c73312403e89db0f8e9bd9601d403b4783fredc 70ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static byte[] getBytesFromAddress(String address) { 71ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh int i, j = 0; 72ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh byte[] output = new byte[BD_ADDR_LEN]; 73ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 7427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang for (i = 0; i < address.length(); i++) { 75ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh if (address.charAt(i) != ':') { 7627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang output[j] = (byte) Integer.parseInt(address.substring(i, i + 2), BD_UUID_LEN); 77ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh j++; 78ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh i++; 79ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 80ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 81ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 82ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return output; 83ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 84ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 85ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static int byteArrayToInt(byte[] valueBuf) { 86ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return byteArrayToInt(valueBuf, 0); 87ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 88ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 89ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static short byteArrayToShort(byte[] valueBuf) { 90ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh ByteBuffer converter = ByteBuffer.wrap(valueBuf); 91ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh converter.order(ByteOrder.nativeOrder()); 92ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return converter.getShort(); 93ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 94ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 95ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static int byteArrayToInt(byte[] valueBuf, int offset) { 96ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh ByteBuffer converter = ByteBuffer.wrap(valueBuf); 97ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh converter.order(ByteOrder.nativeOrder()); 98ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return converter.getInt(offset); 99ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 100ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 101ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static byte[] intToByteArray(int value) { 102ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh ByteBuffer converter = ByteBuffer.allocate(4); 103ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh converter.order(ByteOrder.nativeOrder()); 104ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh converter.putInt(value); 105ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return converter.array(); 106ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 107ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 108cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie public static byte[] uuidToByteArray(ParcelUuid pUuid) { 109cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie int length = BD_UUID_LEN; 110cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie ByteBuffer converter = ByteBuffer.allocate(length); 111cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie converter.order(ByteOrder.BIG_ENDIAN); 112cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie long msb, lsb; 113cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie UUID uuid = pUuid.getUuid(); 114cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie msb = uuid.getMostSignificantBits(); 115cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie lsb = uuid.getLeastSignificantBits(); 116cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie converter.putLong(msb); 117cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie converter.putLong(8, lsb); 118cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie return converter.array(); 119cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie } 120cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie 121ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static byte[] uuidsToByteArray(ParcelUuid[] uuids) { 122ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh int length = uuids.length * BD_UUID_LEN; 123ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh ByteBuffer converter = ByteBuffer.allocate(length); 124ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh converter.order(ByteOrder.BIG_ENDIAN); 125ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh UUID uuid; 126ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh long msb, lsb; 127ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh for (int i = 0; i < uuids.length; i++) { 128ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh uuid = uuids[i].getUuid(); 129ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh msb = uuid.getMostSignificantBits(); 130ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh lsb = uuid.getLeastSignificantBits(); 13127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang converter.putLong(i * BD_UUID_LEN, msb); 13227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang converter.putLong(i * BD_UUID_LEN + 8, lsb); 133ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 134ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return converter.array(); 135ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 136ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 137ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh public static ParcelUuid[] byteArrayToUuid(byte[] val) { 13827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int numUuids = val.length / BD_UUID_LEN; 139ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh ParcelUuid[] puuids = new ParcelUuid[numUuids]; 140ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh UUID uuid; 141ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh int offset = 0; 142ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 143ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh ByteBuffer converter = ByteBuffer.wrap(val); 144ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh converter.order(ByteOrder.BIG_ENDIAN); 145ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh 146ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh for (int i = 0; i < numUuids; i++) { 147ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh puuids[i] = new ParcelUuid(new UUID(converter.getLong(offset), 148ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh converter.getLong(offset + 8))); 14927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang offset += BD_UUID_LEN; 150ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 151ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh return puuids; 152ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh } 1536654f5c903de510a70f9e72cd5ad7837b615d93ffredc 1546654f5c903de510a70f9e72cd5ad7837b615d93ffredc public static String debugGetAdapterStateString(int state) { 1556654f5c903de510a70f9e72cd5ad7837b615d93ffredc switch (state) { 15627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case BluetoothAdapter.STATE_OFF: 15727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return "STATE_OFF"; 15827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case BluetoothAdapter.STATE_ON: 15927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return "STATE_ON"; 16027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case BluetoothAdapter.STATE_TURNING_ON: 16127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return "STATE_TURNING_ON"; 16227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang case BluetoothAdapter.STATE_TURNING_OFF: 16327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return "STATE_TURNING_OFF"; 16427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang default: 16527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang return "UNKNOWN"; 1666654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 1676654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 168c7a57f31515107366589bd6875c3cc4af1fc806efredc 16927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang public static void copyStream(InputStream is, OutputStream os, int bufferSize) 17027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang throws IOException { 17127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang if (is != null && os != null) { 172c7a57f31515107366589bd6875c3cc4af1fc806efredc byte[] buffer = new byte[bufferSize]; 17327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang int bytesRead = 0; 17427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang while ((bytesRead = is.read(buffer)) >= 0) { 17527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang os.write(buffer, 0, bytesRead); 176c7a57f31515107366589bd6875c3cc4af1fc806efredc } 177c7a57f31515107366589bd6875c3cc4af1fc806efredc } 178c7a57f31515107366589bd6875c3cc4af1fc806efredc } 179c7a57f31515107366589bd6875c3cc4af1fc806efredc 180c7a57f31515107366589bd6875c3cc4af1fc806efredc public static void safeCloseStream(InputStream is) { 181c7a57f31515107366589bd6875c3cc4af1fc806efredc if (is != null) { 182c7a57f31515107366589bd6875c3cc4af1fc806efredc try { 183c7a57f31515107366589bd6875c3cc4af1fc806efredc is.close(); 184c7a57f31515107366589bd6875c3cc4af1fc806efredc } catch (Throwable t) { 18527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.d(TAG, "Error closing stream", t); 186c7a57f31515107366589bd6875c3cc4af1fc806efredc } 187c7a57f31515107366589bd6875c3cc4af1fc806efredc } 188c7a57f31515107366589bd6875c3cc4af1fc806efredc } 189c7a57f31515107366589bd6875c3cc4af1fc806efredc 190c7a57f31515107366589bd6875c3cc4af1fc806efredc public static void safeCloseStream(OutputStream os) { 191c7a57f31515107366589bd6875c3cc4af1fc806efredc if (os != null) { 192c7a57f31515107366589bd6875c3cc4af1fc806efredc try { 193c7a57f31515107366589bd6875c3cc4af1fc806efredc os.close(); 194c7a57f31515107366589bd6875c3cc4af1fc806efredc } catch (Throwable t) { 19527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.d(TAG, "Error closing stream", t); 196c7a57f31515107366589bd6875c3cc4af1fc806efredc } 197c7a57f31515107366589bd6875c3cc4af1fc806efredc } 198c7a57f31515107366589bd6875c3cc4af1fc806efredc } 19937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu 20037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu public static boolean checkCaller() { 20137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu boolean ok; 20237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu // Get the caller's user id then clear the calling identity 20337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu // which will be restored in the finally clause. 20437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu int callingUser = UserHandle.getCallingUserId(); 205465bbd2160749d9e0a3f3aabeb4e20bb51573001Jason Monk int callingUid = Binder.getCallingUid(); 20637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu long ident = Binder.clearCallingIdentity(); 20737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu 20837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu try { 20937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu // With calling identity cleared the current user is the foreground user. 21037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu int foregroundUser = ActivityManager.getCurrentUser(); 21137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu ok = (foregroundUser == callingUser); 212465bbd2160749d9e0a3f3aabeb4e20bb51573001Jason Monk if (!ok) { 2138e6936eae2f949066dcc6e2e66a48ffa50450402Santos Cordon // Always allow SystemUI/System access. 214352e218bcaa0f4c47636f8aeef02eef543aeb131Jeff Sharkey final int systemUiUid = ActivityThread.getPackageManager().getPackageUid( 215352e218bcaa0f4c47636f8aeef02eef543aeb131Jeff Sharkey "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, 216352e218bcaa0f4c47636f8aeef02eef543aeb131Jeff Sharkey UserHandle.USER_SYSTEM); 2178e6936eae2f949066dcc6e2e66a48ffa50450402Santos Cordon ok = (systemUiUid == callingUid) || (Process.SYSTEM_UID == callingUid); 218465bbd2160749d9e0a3f3aabeb4e20bb51573001Jason Monk } 21937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu } catch (Exception ex) { 22027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang Log.e(TAG, "checkIfCallerIsSelfOrForegroundUser: Exception ex=" + ex); 22137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu ok = false; 22237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu } finally { 22337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu Binder.restoreCallingIdentity(ident); 22437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu } 22537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu return ok; 22637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu } 22727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 2282287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz public static boolean checkCallerAllowManagedProfiles(Context mContext) { 2292287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz if (mContext == null) { 2302287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz return checkCaller(); 2312287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz } 2322287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz boolean ok; 2332287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz // Get the caller's user id and if it's a managed profile, get it's parents 2342287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz // id, then clear the calling identity 2352287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz // which will be restored in the finally clause. 2362287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz int callingUser = UserHandle.getCallingUserId(); 237465bbd2160749d9e0a3f3aabeb4e20bb51573001Jason Monk int callingUid = Binder.getCallingUid(); 2382287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz long ident = Binder.clearCallingIdentity(); 2392287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz try { 2402287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 2412287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz UserInfo ui = um.getProfileParent(callingUser); 2422287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 2432287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz // With calling identity cleared the current user is the foreground user. 2442287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz int foregroundUser = ActivityManager.getCurrentUser(); 2452287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz ok = (foregroundUser == callingUser) || 2462287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz (foregroundUser == parentUser); 247465bbd2160749d9e0a3f3aabeb4e20bb51573001Jason Monk if (!ok) { 2488e6936eae2f949066dcc6e2e66a48ffa50450402Santos Cordon // Always allow SystemUI/System access. 249352e218bcaa0f4c47636f8aeef02eef543aeb131Jeff Sharkey final int systemUiUid = ActivityThread.getPackageManager().getPackageUid( 250352e218bcaa0f4c47636f8aeef02eef543aeb131Jeff Sharkey "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, 251352e218bcaa0f4c47636f8aeef02eef543aeb131Jeff Sharkey UserHandle.USER_SYSTEM); 2528e6936eae2f949066dcc6e2e66a48ffa50450402Santos Cordon ok = (systemUiUid == callingUid) || (Process.SYSTEM_UID == callingUid); 253465bbd2160749d9e0a3f3aabeb4e20bb51573001Jason Monk } 2542287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz } catch (Exception ex) { 2552287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz Log.e(TAG, "checkCallerAllowManagedProfiles: Exception ex=" + ex); 2562287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz ok = false; 2572287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz } finally { 2582287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz Binder.restoreCallingIdentity(ident); 2592287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz } 2602287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz return ok; 2612287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz } 2622287bc2b01df774378123fe7bc7bca14fee549f7Benjamin Franz 26327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang /** 26427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * Enforce the context has android.Manifest.permission.BLUETOOTH_ADMIN permission. A 26527bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * {@link SecurityException} would be thrown if neither the calling process or the application 26627bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * does not have BLUETOOTH_ADMIN permission. 26727bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * 26827bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang * @param context Context for the permission check. 26927bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang */ 27027bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang public static void enforceAdminPermission(ContextWrapper context) { 27127bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang context.enforceCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_ADMIN, 27227bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang "Need BLUETOOTH_ADMIN permission"); 27327bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang } 27427bd5f277ccf471f2fa9cd9151a2a226b51bc825Wei Wang 27596509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang /** 276d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION or 277d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov * android.Manifest.permission.ACCESS_FINE_LOCATION and a corresponding app op is allowed 278d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov */ 279d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov public static boolean checkCallerHasLocationPermission(Context context, AppOpsManager appOps, 280d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov String callingPackage) { 281d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov if (context.checkCallingOrSelfPermission(android.Manifest.permission. 282d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED 283d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov && isAppOppAllowed(appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) { 284d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov return true; 285d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov } 286d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov 287586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov if (context.checkCallingOrSelfPermission(android.Manifest.permission. 288d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED 289586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov && isAppOppAllowed(appOps, AppOpsManager.OP_COARSE_LOCATION, callingPackage)) { 290586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov return true; 291586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov } 292c16dd2fad8325f24f5099e9ab175894b247859ecDianne Hackborn // Enforce location permission for apps targeting M and later versions 293a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov if (isMApp(context, callingPackage)) { 294e041e1b073d81516073223da4aef23e91cc823e7Calvin On // PEERS_MAC_ADDRESS is another way to get scan results without 295e041e1b073d81516073223da4aef23e91cc823e7Calvin On // requiring location permissions, so only throw an exception here 296e041e1b073d81516073223da4aef23e91cc823e7Calvin On // if PEERS_MAC_ADDRESS permission is missing as well 297e041e1b073d81516073223da4aef23e91cc823e7Calvin On if (!checkCallerHasPeersMacAddressPermission(context)) { 298e041e1b073d81516073223da4aef23e91cc823e7Calvin On throw new SecurityException("Need ACCESS_COARSE_LOCATION or " 299e041e1b073d81516073223da4aef23e91cc823e7Calvin On + "ACCESS_FINE_LOCATION permission to get scan results"); 300e041e1b073d81516073223da4aef23e91cc823e7Calvin On } 301586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov } else { 3021b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov // Pre-M apps running in the foreground should continue getting scan results 3031b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov if (isForegroundApp(context, callingPackage)) { 3041b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov return true; 3051b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov } 306586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION " 307586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov + "permission to get scan results"); 308586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov } 309586ba822a87a5cb0f58035ce0983825f5f23285dFyodor Kupolov return false; 310d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov } 311d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov 3121b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov /** 313312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov * Returns true if the caller holds PEERS_MAC_ADDRESS. 314312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov */ 315312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov public static boolean checkCallerHasPeersMacAddressPermission(Context context) { 316312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov return context.checkCallingOrSelfPermission( 317312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov android.Manifest.permission.PEERS_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED; 318312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov } 319312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov 320a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov public static boolean isLegacyForegroundApp(Context context, String pkgName) { 321a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov return !isMApp(context, pkgName) && isForegroundApp(context, pkgName); 322a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov } 323a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov 324a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov private static boolean isMApp(Context context, String pkgName) { 325a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov try { 326a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov return context.getPackageManager().getApplicationInfo(pkgName, 0) 327a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov .targetSdkVersion >= Build.VERSION_CODES.M; 328a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov } catch (PackageManager.NameNotFoundException e) { 329a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov // In case of exception, assume M app 330a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov } 331a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov return true; 332a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov } 333a072c9e05c551dba0a938e158cb3a650c18b4dedFyodor Kupolov 334312e10ad5bcbb1e3d021c4798d55c40f99c7a6efFyodor Kupolov /** 3351b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov * Return true if the specified package name is a foreground app. 3361b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov * 3371b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov * @param pkgName application package name. 3381b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov */ 3391b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov private static boolean isForegroundApp(Context context, String pkgName) { 3401b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); 3411b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); 3421b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName()); 3431b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov } 3441b1433ad9b4d769a1f9e37284c5d80fb021d31d7Fyodor Kupolov 345d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov private static boolean isAppOppAllowed(AppOpsManager appOps, int op, String callingPackage) { 346d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov return appOps.noteOp(op, Binder.getCallingUid(), callingPackage) 347d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov == AppOpsManager.MODE_ALLOWED; 348d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov } 349d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov 350d2fc8cbd87c7a742223e8742a442a48690d426ceFyodor Kupolov /** 35196509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang * Converts {@code millisecond} to unit. Each unit is 0.625 millisecond. 35296509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang */ 35396509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang public static int millsToUnit(int milliseconds) { 35496509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang return (int) (TimeUnit.MILLISECONDS.toMicros(milliseconds) / MICROS_PER_UNIT); 35596509d5ff7109bc42a4c25143f70ec41a127d109Wei Wang } 356ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh} 357