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;
206654f5c903de510a70f9e72cd5ad7837b615d93ffredcimport android.bluetooth.BluetoothAdapter;
2174ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.bluetooth.BluetoothDevice;
2237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport android.os.Binder;
23ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.os.ParcelUuid;
2437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport android.os.UserHandle;
25c7a57f31515107366589bd6875c3cc4af1fc806efredcimport android.util.Log;
26ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
27c7a57f31515107366589bd6875c3cc4af1fc806efredcimport java.io.IOException;
28c7a57f31515107366589bd6875c3cc4af1fc806efredcimport java.io.InputStream;
29c7a57f31515107366589bd6875c3cc4af1fc806efredcimport java.io.OutputStream;
30ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.nio.ByteBuffer;
31ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.nio.ByteOrder;
32ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.util.UUID;
33ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
34ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/**
35ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * @hide
36ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
37ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
38ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshfinal public class Utils {
39c7a57f31515107366589bd6875c3cc4af1fc806efredc    private static final String TAG = "BluetoothUtils";
40ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int BD_ADDR_LEN = 6; // bytes
41ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int BD_UUID_LEN = 16; // bytes
42ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
43ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static String getAddressStringFromByte(byte[] address) {
446654f5c903de510a70f9e72cd5ad7837b615d93ffredc        if (address == null || address.length !=6) {
456654f5c903de510a70f9e72cd5ad7837b615d93ffredc            return null;
466654f5c903de510a70f9e72cd5ad7837b615d93ffredc        }
476654f5c903de510a70f9e72cd5ad7837b615d93ffredc
48ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return String.format("%02X:%02X:%02X:%02X:%02X:%02X",
49ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                address[0], address[1], address[2], address[3], address[4],
50ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                address[5]);
51ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
52ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
5374ae04c73312403e89db0f8e9bd9601d403b4783fredc    public static byte[] getByteAddress(BluetoothDevice device) {
5474ae04c73312403e89db0f8e9bd9601d403b4783fredc        return getBytesFromAddress(device.getAddress());
5574ae04c73312403e89db0f8e9bd9601d403b4783fredc    }
5674ae04c73312403e89db0f8e9bd9601d403b4783fredc
57ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static byte[] getBytesFromAddress(String address) {
58ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        int i, j = 0;
59ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        byte[] output = new byte[BD_ADDR_LEN];
60ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
61ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        for (i = 0; i < address.length();i++) {
62ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (address.charAt(i) != ':') {
63ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                output[j] = (byte) Integer.parseInt(address.substring(i, i+2), 16);
64ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                j++;
65ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                i++;
66ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
67ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
68ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
69ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return output;
70ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
71ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
72ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static int byteArrayToInt(byte[] valueBuf) {
73ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return byteArrayToInt(valueBuf, 0);
74ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
75ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
76ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static short byteArrayToShort(byte[] valueBuf) {
77ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        ByteBuffer converter = ByteBuffer.wrap(valueBuf);
78ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        converter.order(ByteOrder.nativeOrder());
79ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return converter.getShort();
80ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
81ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
82ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static int byteArrayToInt(byte[] valueBuf, int offset) {
83ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        ByteBuffer converter = ByteBuffer.wrap(valueBuf);
84ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        converter.order(ByteOrder.nativeOrder());
85ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return converter.getInt(offset);
86ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
87ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
88ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static byte[] intToByteArray(int value) {
89ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        ByteBuffer converter = ByteBuffer.allocate(4);
90ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        converter.order(ByteOrder.nativeOrder());
91ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        converter.putInt(value);
92ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return converter.array();
93ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
94ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
95cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    public static byte[] uuidToByteArray(ParcelUuid pUuid) {
96cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        int length = BD_UUID_LEN;
97cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        ByteBuffer converter = ByteBuffer.allocate(length);
98cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        converter.order(ByteOrder.BIG_ENDIAN);
99cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        long msb, lsb;
100cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        UUID uuid = pUuid.getUuid();
101cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        msb = uuid.getMostSignificantBits();
102cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        lsb = uuid.getLeastSignificantBits();
103cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        converter.putLong(msb);
104cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        converter.putLong(8, lsb);
105cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        return converter.array();
106cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
107cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
108ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static byte[] uuidsToByteArray(ParcelUuid[] uuids) {
109ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        int length = uuids.length * BD_UUID_LEN;
110ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        ByteBuffer converter = ByteBuffer.allocate(length);
111ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        converter.order(ByteOrder.BIG_ENDIAN);
112ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        UUID uuid;
113ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        long msb, lsb;
114ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        for (int i = 0; i < uuids.length; i++) {
115ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            uuid = uuids[i].getUuid();
116ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            msb = uuid.getMostSignificantBits();
117ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            lsb = uuid.getLeastSignificantBits();
118ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            converter.putLong(i * 16, msb);
119ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            converter.putLong(i * 16 + 8, lsb);
120ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
121ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return converter.array();
122ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
123ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
124ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    public static ParcelUuid[] byteArrayToUuid(byte[] val) {
125ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        int numUuids = val.length/BD_UUID_LEN;
126ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        ParcelUuid[] puuids = new ParcelUuid[numUuids];
127ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        UUID uuid;
128ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        int offset = 0;
129ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
130ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        ByteBuffer converter = ByteBuffer.wrap(val);
131ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        converter.order(ByteOrder.BIG_ENDIAN);
132ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
133ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        for (int i = 0; i < numUuids; i++) {
134ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            puuids[i] = new ParcelUuid(new UUID(converter.getLong(offset),
135ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    converter.getLong(offset + 8)));
136ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            offset += 16;
137ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
138ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return puuids;
139ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
1406654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1416654f5c903de510a70f9e72cd5ad7837b615d93ffredc    public static String debugGetAdapterStateString(int state) {
1426654f5c903de510a70f9e72cd5ad7837b615d93ffredc        switch (state) {
1436654f5c903de510a70f9e72cd5ad7837b615d93ffredc            case BluetoothAdapter.STATE_OFF : return "STATE_OFF";
1446654f5c903de510a70f9e72cd5ad7837b615d93ffredc            case BluetoothAdapter.STATE_ON : return "STATE_ON";
1456654f5c903de510a70f9e72cd5ad7837b615d93ffredc            case BluetoothAdapter.STATE_TURNING_ON : return "STATE_TURNING_ON";
1466654f5c903de510a70f9e72cd5ad7837b615d93ffredc            case BluetoothAdapter.STATE_TURNING_OFF : return "STATE_TURNING_OFF";
1476654f5c903de510a70f9e72cd5ad7837b615d93ffredc            default : return "UNKNOWN";
1486654f5c903de510a70f9e72cd5ad7837b615d93ffredc        }
1496654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
150c7a57f31515107366589bd6875c3cc4af1fc806efredc
151c7a57f31515107366589bd6875c3cc4af1fc806efredc    public static void copyStream(InputStream is, OutputStream os, int bufferSize) throws IOException {
152c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (is != null && os!=null) {
153c7a57f31515107366589bd6875c3cc4af1fc806efredc            byte[] buffer = new byte[bufferSize];
154c7a57f31515107366589bd6875c3cc4af1fc806efredc            int bytesRead=0;
155c7a57f31515107366589bd6875c3cc4af1fc806efredc            while ( (bytesRead = is.read(buffer))>=0) {
156c7a57f31515107366589bd6875c3cc4af1fc806efredc                os.write(buffer,0,bytesRead);
157c7a57f31515107366589bd6875c3cc4af1fc806efredc            }
158c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
159c7a57f31515107366589bd6875c3cc4af1fc806efredc    }
160c7a57f31515107366589bd6875c3cc4af1fc806efredc
161c7a57f31515107366589bd6875c3cc4af1fc806efredc    public static void safeCloseStream(InputStream is) {
162c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (is != null) {
163c7a57f31515107366589bd6875c3cc4af1fc806efredc            try {
164c7a57f31515107366589bd6875c3cc4af1fc806efredc                is.close();
165c7a57f31515107366589bd6875c3cc4af1fc806efredc            } catch (Throwable t) {
166c7a57f31515107366589bd6875c3cc4af1fc806efredc                Log.d(TAG,"Error closing stream",t);
167c7a57f31515107366589bd6875c3cc4af1fc806efredc            }
168c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
169c7a57f31515107366589bd6875c3cc4af1fc806efredc    }
170c7a57f31515107366589bd6875c3cc4af1fc806efredc
171c7a57f31515107366589bd6875c3cc4af1fc806efredc    public static void safeCloseStream(OutputStream os) {
172c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (os != null) {
173c7a57f31515107366589bd6875c3cc4af1fc806efredc            try {
174c7a57f31515107366589bd6875c3cc4af1fc806efredc                os.close();
175c7a57f31515107366589bd6875c3cc4af1fc806efredc            } catch (Throwable t) {
176c7a57f31515107366589bd6875c3cc4af1fc806efredc                Log.d(TAG,"Error closing stream",t);
177c7a57f31515107366589bd6875c3cc4af1fc806efredc            }
178c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
179c7a57f31515107366589bd6875c3cc4af1fc806efredc    }
18037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
18137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu    public static boolean checkCaller() {
18237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        boolean ok;
18337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        // Get the caller's user id then clear the calling identity
18437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        // which will be restored in the finally clause.
18537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        int callingUser = UserHandle.getCallingUserId();
18637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        long ident = Binder.clearCallingIdentity();
18737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu
18837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        try {
18937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            // With calling identity cleared the current user is the foreground user.
19037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            int foregroundUser = ActivityManager.getCurrentUser();
19137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            ok = (foregroundUser == callingUser);
19237510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        } catch (Exception ex) {
19337510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            Log.e(TAG,"checkIfCallerIsSelfOrForegroundUser: Exception ex=" + ex);
19437510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            ok = false;
19537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        } finally {
19637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu            Binder.restoreCallingIdentity(ident);
19737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        }
19837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu        return ok;
19937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu    }
200ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
201