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