BluetoothService.java revision 7f9ecca8f2dc288f785b37d2478e89b80fc3cefc
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: Move this to
19bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * java/services/com/android/server/BluetoothService.java
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and make the contructor package private again.
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter;
28dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.BluetoothClass;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice;
30f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothDeviceProfileState;
315a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport android.bluetooth.BluetoothHeadset;
322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.bluetooth.BluetoothHealthAppConfiguration;
334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganeshimport android.bluetooth.BluetoothInputDevice;
346fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.bluetooth.BluetoothPan;
3596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganeshimport android.bluetooth.BluetoothProfile;
36f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganeshimport android.bluetooth.BluetoothProfileState;
3724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.bluetooth.BluetoothSocket;
3810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganeshimport android.bluetooth.BluetoothUuid;
39bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth;
4016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.bluetooth.IBluetoothCallback;
41fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganeshimport android.bluetooth.IBluetoothHealthCallback;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
476e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganeshimport android.content.SharedPreferences;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.IBinder;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.ParcelFileDescriptor;
533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.ParcelUuid;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
55105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
58cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganeshimport android.util.Pair;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
60fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganeshimport com.android.internal.app.IBatteryStats;
61fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh
623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedInputStream;
63a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.BufferedReader;
643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedWriter;
65a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.DataInputStream;
66a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.File;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileInputStream;
693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileNotFoundException;
703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileWriter;
71a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.InputStreamReader;
723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.IOException;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
74a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.RandomAccessFile;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
7916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator;
805a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
83bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub {
84bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private static final String TAG = "BluetoothService";
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean DBG = true;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNativeData;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private BluetoothEventLoop mEventLoop;
8996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh    private BluetoothHeadset mBluetoothHeadset;
904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private BluetoothInputDevice mInputDevice;
9174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh    private BluetoothPan mPan;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsAirplaneSensitive;
9344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey    private boolean mIsAirplaneToggleable;
947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    private BluetoothAdapterStateMachine mBluetoothState;
95997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly    private boolean mRestart = false;  // need to call enable() after disable()
96bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private boolean mIsDiscovering;
9784690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh    private int[] mAdapterSdpHandles;
9850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh    private ParcelUuid[] mAdapterUuids;
99997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly
100bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private BluetoothAdapter mAdapter;  // constant after init()
1019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private final BluetoothBondState mBondState;  // local cache of bondings
102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private final IBatteryStats mBatteryStats;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
106a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh    static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1083fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr";
1093fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin";
1103fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
1116e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh    private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address";
1126e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh    private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings";
1136e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh
1147f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    private static final int MESSAGE_UUID_INTENT = 1;
1157f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2;
116a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
117a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    // The time (in millisecs) to delay the pairing attempt after the first
118a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    // auto pairing attempt fails. We use an exponential delay with
119a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and
120a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value.
121a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
122a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
1231caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
1241caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    // The timeout used to sent the UUIDs Intent
1251caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    // This timeout should be greater than the page timeout
1261caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private static final int UUID_INTENT_DELAY = 6000;
127105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
12816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    /** Always retrieve RFCOMM channel for these SDP UUIDs */
12916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    private static final ParcelUuid[] RFCOMM_UUIDS = {
13016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            BluetoothUuid.Handsfree,
13116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            BluetoothUuid.HSP,
13216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            BluetoothUuid.ObexObjectPush };
13316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
1349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private final BluetoothAdapterProperties mAdapterProperties;
1359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private final BluetoothDeviceProperties mDeviceProperties;
136d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
13716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache;
13816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    private final ArrayList<String> mUuidIntentTracker;
13916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker;
1401caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
14124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private final HashMap<Integer, Integer> mServiceRecordToPid;
14224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
143f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh    private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState;
144f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh    private final BluetoothProfileState mA2dpProfileState;
145f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh    private final BluetoothProfileState mHfpProfileState;
1469b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
1479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    private BluetoothA2dpService mA2dpService;
148cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData;
149545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
150a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh    private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0;
151707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh
1523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    private static String mDockAddress;
1533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    private String mDockPin;
1543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
155c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh    private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
156a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh    private BluetoothPanProfileHandler mBluetoothPanProfileHandler;
15730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    private BluetoothInputProfileHandler mBluetoothInputProfileHandler;
1582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler;
159a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    private static final String INCOMING_CONNECTION_FILE =
160a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie      "/data/misc/bluetooth/incoming_connection.conf";
161a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    private HashMap<String, Pair<Integer, String>> mIncomingConnections;
162c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh
16316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    private static class RemoteService {
16416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        public String address;
16516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        public ParcelUuid uuid;
16616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        public RemoteService(String address, ParcelUuid uuid) {
16716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            this.address = address;
16816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            this.uuid = uuid;
16916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
17016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        @Override
17116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        public boolean equals(Object o) {
17216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            if (o instanceof RemoteService) {
17316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                RemoteService service = (RemoteService)o;
17416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                return address.equals(service.address) && uuid.equals(service.uuid);
17516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            }
17616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            return false;
17716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
1785f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root
1795f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root        @Override
1805f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root        public int hashCode() {
1815f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root            int hash = 1;
1825f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root            hash = hash * 31 + (address == null ? 0 : address.hashCode());
1835f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root            hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode());
1845f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root            return hash;
1855f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root        }
18616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    }
18716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        classInitNative();
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
192bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothService(Context context) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
194105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Need to do this in place of:
196105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // mBatteryStats = BatteryStatsService.getService();
197105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Since we can not import BatteryStatsService from here. This class really needs to be
198105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // moved to java/services/com/android/server/
199105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initializeNativeDataNative();
202ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
203ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        if (isEnabledNative() == 1) {
204ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            Log.w(TAG, "Bluetooth daemons already running - runtime restart? ");
205ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            disableNative();
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
207ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDiscovering = false;
209a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh
2109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        mBondState = new BluetoothBondState(context, this);
2119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        mAdapterProperties = new BluetoothAdapterProperties(context, this);
2129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        mDeviceProperties = new BluetoothDeviceProperties(this);
21310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
21410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>();
215cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>();
2161caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mUuidIntentTracker = new ArrayList<String>();
21716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();
21824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        mServiceRecordToPid = new HashMap<Integer, Integer>();
219f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();
220f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);
221f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
222f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh
223f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        mHfpProfileState.start();
224f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        mA2dpProfileState.start();
2253fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
2263fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        IntentFilter filter = new IntentFilter();
2276e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh        registerForAirplaneMode(filter);
2286e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh
2293fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        filter.addAction(Intent.ACTION_DOCK_EVENT);
2306e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh        mContext.registerReceiver(mReceiver, filter);
23130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);
232a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh        mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
2332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);
234a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        mIncomingConnections = new HashMap<String, Pair<Integer, String>>();
2353fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    }
2363fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
2379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public static synchronized String readDockBluetoothAddress() {
2383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        if (mDockAddress != null) return mDockAddress;
2393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
2403fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        BufferedInputStream file = null;
2413fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        String dockAddress;
2423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        try {
2433fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH));
2443fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            byte[] address = new byte[17];
2453fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            file.read(address);
2463fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            dockAddress = new String(address);
2473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            dockAddress = dockAddress.toUpperCase();
2483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) {
2493fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                mDockAddress = dockAddress;
2503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                return mDockAddress;
2513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            } else {
2529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                Log.e(TAG, "CheckBluetoothAddress failed for car dock address: "
2539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                        + dockAddress);
2543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            }
2553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        } catch (FileNotFoundException e) {
2569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.e(TAG, "FileNotFoundException while trying to read dock address");
2573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        } catch (IOException e) {
2589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.e(TAG, "IOException while trying to read dock address");
2593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        } finally {
2603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            if (file != null) {
2613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                try {
2623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                    file.close();
2633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                } catch (IOException e) {
2643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                    // Ignore
2653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                }
2663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            }
2673fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        }
2683fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        mDockAddress = null;
2693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        return null;
2703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    }
2713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
2723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    private synchronized boolean writeDockPin() {
2733fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        BufferedWriter out = null;
2743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        try {
2753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH));
2763fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
2773fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            // Generate a random 4 digit pin between 0000 and 9999
2783fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            // This is not truly random but good enough for our purposes.
2793fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            int pin = (int) Math.floor(Math.random() * 10000);
2803fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
2813fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            mDockPin = String.format("%04d", pin);
2823fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            out.write(mDockPin);
2833fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            return true;
2843fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        } catch (FileNotFoundException e) {
2859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.e(TAG, "FileNotFoundException while trying to write dock pairing pin");
2863fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        } catch (IOException e) {
2879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.e(TAG, "IOException while while trying to write dock pairing pin");
2883fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        } finally {
2893fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            if (out != null) {
2903fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                try {
2913fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                    out.close();
2923fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                } catch (IOException e) {
2933fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                    // Ignore
2943fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                }
2953fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            }
2963fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        }
2973fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        mDockPin = null;
2983fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        return false;
2993fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    }
3003fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
3013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    /*package*/ synchronized String getDockPin() {
3023fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        return mDockPin;
303bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    }
304bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly
305bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public synchronized void initAfterRegistration() {
306f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly        mAdapter = BluetoothAdapter.getDefaultAdapter();
3077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);
3087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mBluetoothState.start();
3097f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mEventLoop = mBluetoothState.getBluetoothEventLoop();
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3127d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh    public synchronized void initAfterA2dpRegistration() {
3137d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh        mEventLoop.getProfileProxy();
3147d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh    }
3157d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() throws Throwable {
3186e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh        mContext.unregisterReceiver(mReceiver);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cleanupNativeDataNative();
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.finalize();
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isEnabled() {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
3288c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        return isEnabledInternal();
3298c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh    }
3308c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
3318c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh    private boolean isEnabledInternal() {
3327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON);
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
335105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public int getBluetoothState() {
336105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
3377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        return getBluetoothStateInternal();
338105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
339105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    int getBluetoothStateInternal() {
3417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        return mBluetoothState.getBluetoothAdapterState();
3429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
343105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bring down bluetooth and disable BT in settings. Returns true on success.
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean disable() {
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return disable(true);
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bring down bluetooth. Returns true on success.
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
354e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly     * @param saveSetting If true, persist the new setting
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean disable(boolean saveSetting) {
357e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3597f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        int adapterState = getBluetoothStateInternal();
3607f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
3617f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        switch (adapterState) {
362de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_OFF:
363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return true;
364de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_ON:
365105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            break;
366105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        default:
367105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return false;
368105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
3697a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh
3707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting);
371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return true;
372105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
373105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    synchronized void disconnectDevices() {
3757a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh        // Disconnect devices handled by BluetoothService.
3767a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh        for (BluetoothDevice device: getConnectedInputDevices()) {
3777a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh            disconnectInputDevice(device);
3787a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh        }
3797a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh
3807a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh        for (BluetoothDevice device: getConnectedPanDevices()) {
3817a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh            disconnectPanDevice(device);
3827a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh        }
3837a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh    }
384105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /**
3867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * The Bluetooth has been turned off, but hot. Do bonding, profile,
3877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * and internal cleanup
3887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     */
3897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    synchronized void finishDisable() {
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // mark in progress bondings as cancelled
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
392005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3962d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh        // Stop the profile state machine for bonded devices.
3972d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDED)) {
3982d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh            removeProfileState(address);
3992d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh        }
4002d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // update mode
402de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
403de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE);
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
406105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIsDiscovering = false;
407bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapterProperties.clear();
40824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        mServiceRecordToPid.clear();
409105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
410a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        mProfilesConnected = 0;
411a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        mProfilesConnecting = 0;
412a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        mProfilesDisconnecting = 0;
413c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh        mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
41450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        mAdapterUuids = null;
41550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        mAdapterSdpHandles = null;
416a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh
417105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Log bluetooth off to battery stats.
418105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        long ident = Binder.clearCallingIdentity();
419105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        try {
420105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mBatteryStats.noteBluetoothOff();
421105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } catch (RemoteException e) {
422105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } finally {
423105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Binder.restoreCallingIdentity(ident);
424105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
425997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly
426997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        if (mRestart) {
427997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            mRestart = false;
428997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            enable();
429997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /**
4337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * power off Bluetooth
4347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     */
4357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    synchronized void shutoffBluetooth() {
4367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        tearDownNativeDataNative();
4377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        disableNative();
4387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (mRestart) {
4397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            mRestart = false;
4407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            enable();
4417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        }
4427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    }
4437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
444105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /** Bring up BT and persist BT on in settings */
445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public boolean enable() {
446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return enable(true);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enable this Bluetooth device, asynchronously.
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This turns on/off the underlying hardware.
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
453105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * @param saveSetting If true, persist the new state of BT in settings
454105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * @return True on success (so far)
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
456105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public synchronized boolean enable(boolean saveSetting) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Airplane mode can prevent Bluetooth radio from being turned on.
46144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey        if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4647f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
4657f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        return true;
4667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    }
4677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
4687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /**
4697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * Turn on Bluetooth Module, Load firmware, and do all the preparation
4707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * needed to get the Bluetooth Module ready but keep it not discoverable
4717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * and not connectable.
4727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     */
4737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /* package */ synchronized boolean prepareBluetooth() {
4747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (!setupNativeDataNative()) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mIsDiscovering = false;
4787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
4797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        switchConnectable(false);
4807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        updateSdpRecords();
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
484997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly    /** Forcibly restart Bluetooth if it is on */
485997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly    /* package */ synchronized void restart() {
4867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
487997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            return;
488997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        }
489997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        mRestart = true;
490997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        if (!disable(false)) {
491997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            mRestart = false;
492997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        }
493d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
494997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Handler mHandler = new Handler() {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
4991caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            case MESSAGE_UUID_INTENT:
5001caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh                String address = (String)msg.obj;
50116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                if (address != null) {
5021caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh                    sendUuidIntent(address);
50316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                    makeServiceChannelCallbacks(address);
50416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                }
5051caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh                break;
506a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
507a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                address = (String)msg.obj;
508a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                if (address != null) {
509a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                    createBond(address);
510a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                    return;
511a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                }
512a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                break;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
51750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh    private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) {
51850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        //Register SDP records.
51950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        int[] svcIdentifiers = new int[uuids.size()];
52050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        for (int i = 0; i < uuids.size(); i++) {
52150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh            svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i));
52250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        }
52350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers);
52450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh    }
525105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
52650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh    private synchronized void updateSdpRecords() {
52750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
52850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh
52950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        // Add the default records
53050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        uuids.add(BluetoothUuid.HSP_AG);
53150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        uuids.add(BluetoothUuid.ObexObjectPush);
53250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh
53350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        if (mContext.getResources().
53450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh                getBoolean(com.android.internal.R.bool.config_voice_capable)) {
53550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh            uuids.add(BluetoothUuid.Handsfree_AG);
53650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh            uuids.add(BluetoothUuid.PBAP_PSE);
53750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        }
53850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh
53950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        // Add SDP records for profiles maintained by Android userspace
54050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        addReservedSdpRecords(uuids);
54150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh
54250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        // Enable profiles maintained by Bluez userspace.
54374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,
54474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                BluetoothPanProfileHandler.NAP_BRIDGE);
54550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh
54650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        // Add SDP records for profiles maintained by Bluez userspace
54750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        uuids.add(BluetoothUuid.AudioSource);
54850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        uuids.add(BluetoothUuid.AvrcpTarget);
54950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        uuids.add(BluetoothUuid.NAP);
55050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh
55150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        // Cannot cast uuids.toArray directly since ParcelUuid is parcelable
55250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        mAdapterUuids = new ParcelUuid[uuids.size()];
55350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        for (int i = 0; i < uuids.size(); i++) {
55450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh            mAdapterUuids[i] = uuids.get(i);
55550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        }
55650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh    }
55750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh
5589efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh    /**
5599efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh     * This function is called from Bluetooth Event Loop when onPropertyChanged
5609efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh     * for adapter comes in with UUID property.
5619efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh     * @param uuidsThe uuids of adapter as reported by Bluez.
5629efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh     */
5637f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /*package*/ synchronized void updateBluetoothState(String uuids) {
5647f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
5659efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh
5667f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (mAdapterUuids != null &&
5677f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
5687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5727f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /**
5737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * This method is called immediately after Bluetooth module is turned on.
5747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * It starts auto-connection and places bluetooth on sign onto the battery
5757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * stats
5767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     */
5777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /*package*/ void runBluetooth() {
5787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mIsDiscovering = false;
5797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mBondState.readAutoPairingData();
5807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        mBondState.initBondState();
5817f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        initProfileState();
5827f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
5837f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        autoConnect();
5847f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
5857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        // Log bluetooth on to battery stats.
5867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        long ident = Binder.clearCallingIdentity();
5877f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        try {
5887f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            mBatteryStats.noteBluetoothOn();
5897f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        } catch (RemoteException e) {
5907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            Log.e(TAG, "", e);
5917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        } finally {
5927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            Binder.restoreCallingIdentity(ident);
5937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
596a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    /*package*/ synchronized boolean attemptAutoPair(String address) {
597a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        if (!mBondState.hasAutoPairingFailed(address) &&
598a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                !mBondState.isAutoPairingBlacklisted(address)) {
599a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            mBondState.attempt(address);
600a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            setPin(address, BluetoothDevice.convertPinToBytes("0000"));
601a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            return true;
602a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        }
603a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        return false;
604a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    }
605a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
606f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh    /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) {
607f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh        // Check for keyboards which have fixed PIN 0000 as the pairing pin
608f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh        return mBondState.isFixedPinZerosAutoPairKeyboard(address);
609f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh    }
610f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh
611a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) {
612a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        if (result == BluetoothDevice.BOND_SUCCESS) {
613a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            setBondState(address, BluetoothDevice.BOND_BONDED);
614a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            if (mBondState.isAutoPairingAttemptsInProgress(address)) {
615a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                mBondState.clearPinAttempts(address);
616a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            }
617a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED &&
618a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                mBondState.getAttempt(address) == 1) {
619a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            mBondState.addAutoPairingFailure(address);
620a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            pairingAttempt(address, result);
621a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN &&
622a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh              mBondState.isAutoPairingAttemptsInProgress(address)) {
623a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            pairingAttempt(address, result);
624a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        } else {
625a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            setBondState(address, BluetoothDevice.BOND_NONE, result);
626a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            if (mBondState.isAutoPairingAttemptsInProgress(address)) {
627a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                mBondState.clearPinAttempts(address);
628a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            }
629a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        }
630a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    }
631a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
632a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    /*package*/ synchronized String getPendingOutgoingBonding() {
633a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        return mBondState.getPendingOutgoingBonding();
634a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    }
635a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
636a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    private void pairingAttempt(String address, int result) {
637a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        // This happens when our initial guess of "0000" as the pass key
638a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        // fails. Try to create the bond again and display the pin dialog
639a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        // to the user. Use back-off while posting the delayed
640a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        // message. The initial value is
641a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is
642a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is
643a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        // reached, display an error to the user.
644a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        int attempt = mBondState.getAttempt(address);
645a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY >
646a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                    MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) {
647a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            mBondState.clearPinAttempts(address);
648a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            setBondState(address, BluetoothDevice.BOND_NONE, result);
649a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            return;
650a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        }
651a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
652a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
653a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        message.obj = address;
654a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        boolean postResult =  mHandler.sendMessageDelayed(message,
655a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                                        attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
656a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        if (!postResult) {
657a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            mBondState.clearPinAttempts(address);
658a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            setBondState(address,
659a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh                    BluetoothDevice.BOND_NONE, result);
660a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh            return;
661a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        }
662a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        mBondState.attempt(address);
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    /*package*/ BluetoothDevice getRemoteDevice(String address) {
6669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return mAdapter.getRemoteDevice(address);
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String toBondStateString(int bondState) {
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (bondState) {
671005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        case BluetoothDevice.BOND_NONE:
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "not bonded";
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BluetoothDevice.BOND_BONDING:
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "bonding";
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BluetoothDevice.BOND_BONDED:
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "bonded";
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "??????";
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean setName(String name) {
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (name == null) {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
688d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setPropertyString("Name", name);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
691d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean
692d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    // Either have a single property function with Object as the parameter
693d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    // or have a function for each property and then obfuscate in the JNI layer.
694d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    // The following looks dirty.
695d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private boolean setPropertyString(String key, String value) {
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
6978c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
698d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setAdapterPropertyStringNative(key, value);
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
701d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private boolean setPropertyInteger(String key, int value) {
702d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
7038c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
704d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setAdapterPropertyIntegerNative(key, value);
705d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
707d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private boolean setPropertyBoolean(String key, boolean value) {
708d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
7098c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
710d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setAdapterPropertyBooleanNative(key, value ? 1 : 0);
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
713d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /**
714d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Set the discoverability window for the device.  A timeout of zero
715d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * makes the device permanently discoverable (if the device is
716d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * discoverable).  Setting the timeout to a nonzero value does not make
717d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * a device discoverable; you need to call setMode() to make the device
718d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * explicitly discoverable.
719d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     *
720f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby     * @param timeout The discoverable timeout in seconds.
721d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     */
722d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean setDiscoverableTimeout(int timeout) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
725d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setPropertyInteger("DiscoverableTimeout", timeout);
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
72812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly    public synchronized boolean setScanMode(int mode, int duration) {
72918b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
73018b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly                                                "Need WRITE_SECURE_SETTINGS permission");
7317f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        return setScanMode(mode, duration, true);
7327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    }
7337f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
7347f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /**
7357f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     * @param on true set the local Bluetooth module to be connectable
7367f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     *                but not dicoverable
7377f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     *           false set the local Bluetooth module to be not connectable
7387f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     *                 and not dicoverable
7397f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie     */
7407f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /*package*/ synchronized void switchConnectable(boolean on) {
7417f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (on) {
7427f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE
7437f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false);
7447f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        } else {
7457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            // 0 is a dummy value, does not apply for SCAN_MODE_NONE
7467f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false);
7477f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        }
7487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    }
7497f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
7507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) {
7519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        boolean pairable;
7529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        boolean discoverable;
75312835478ee687a493d1b5882e67b6725bd539c26Nick Pelly
754de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        switch (mode) {
755de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.SCAN_MODE_NONE:
756d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            pairable = false;
757d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            discoverable = false;
758de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            break;
759de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
760d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            pairable = true;
761d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            discoverable = false;
762005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            break;
763de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
764d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            pairable = true;
765d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            discoverable = true;
76612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly            if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds");
767005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            break;
768de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        default:
769de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            Log.w(TAG, "Requested invalid scan mode " + mode);
770de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            return false;
771d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7737f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (allowOnlyInOnState) {
7747f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            setPropertyBoolean("Pairable", pairable);
7757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            setPropertyBoolean("Discoverable", discoverable);
7767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        } else {
7777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            // allowed to set the property through native layer directly
7787f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0);
7797f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0);
7807f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        }
781d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return true;
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
784b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh    /*package*/ synchronized String getProperty(String name) {
785b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh        if (!isEnabledInternal()) return null;
7869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return mAdapterProperties.getProperty(name);
787b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh    }
788b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh
7899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    BluetoothAdapterProperties getAdapterProperties() {
7909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return mAdapterProperties;
7919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
7929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
7939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    BluetoothDeviceProperties getDeviceProperties() {
7949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return mDeviceProperties;
7959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
7969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
7979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    boolean isRemoteDeviceInCache(String address) {
7989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return mDeviceProperties.isInCache(address);
7999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
8009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
8019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    void setRemoteDeviceProperty(String address, String name, String value) {
8029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        mDeviceProperties.setProperty(address, name, value);
8039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
8049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
8059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    void updateRemoteDevicePropertiesCache(String address) {
8069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        mDeviceProperties.updateCache(address);
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized String getAddress() {
810d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
811d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return getProperty("Address");
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
814d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized String getName() {
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
816d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return getProperty("Name");
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
81958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh    public synchronized ParcelUuid[] getUuids() {
82058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
82158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        String value =  getProperty("UUIDs");
82258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        if (value == null) return null;
82350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh        return convertStringToParcelUuid(value);
82450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh    }
82558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh
82650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh    private synchronized ParcelUuid[] convertStringToParcelUuid(String value) {
82758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        String[] uuidStrings = null;
82858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        // The UUIDs are stored as a "," separated string.
82958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        uuidStrings = value.split(",");
83058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
83158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh
83258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        for (int i = 0; i < uuidStrings.length; i++) {
83358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
83458b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        }
83558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh        return uuids;
83658b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh    }
83758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh
83858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
840d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Returns the user-friendly name of a remote device.  This value is
841d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * returned from our local cache, which is updated when onPropertyChange
842d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * event is received.
843d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Do not expect to retrieve the updated remote name immediately after
844d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * changing the name on the remote device.
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
846d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @param address Bluetooth address of remote device.
847d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     *
848d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @return The user-friendly name of the specified remote device.
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
850d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized String getRemoteName(String address) {
851d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
852005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
853d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
854d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
8559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return mDeviceProperties.getProperty(address, "Name");
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the discoverability window for the device.  A timeout of zero
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that the device is permanently discoverable (if the device is
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in the discoverable mode).
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The discoverability window of the device, in seconds.  A negative
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         value indicates an error.
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getDiscoverableTimeout() {
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
868d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String timeout = getProperty("DiscoverableTimeout");
869d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (timeout != null)
870d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh           return Integer.valueOf(timeout);
871d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else
872d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return -1;
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getScanMode() {
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
8778c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal())
878de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            return BluetoothAdapter.SCAN_MODE_NONE;
879d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
880d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        boolean pairable = getProperty("Pairable").equals("true");
881d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        boolean discoverable = getProperty("Discoverable").equals("true");
882d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return bluezStringToScanMode (pairable, discoverable);
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
885d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean startDiscovery() {
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
8888c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
8898c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
890d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return startDiscoveryNative();
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
893d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean cancelDiscovery() {
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
8968c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
8978c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
898d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return stopDiscoveryNative();
899d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
900d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
901d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean isDiscovering() {
902d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
903d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return mIsDiscovering;
904d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
905d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
906d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ void setIsDiscovering(boolean isDiscovering) {
907d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mIsDiscovering = isDiscovering;
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
910cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    private boolean isBondingFeasible(String address) {
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
9138c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
9148c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
915005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9202092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        if (mBondState.getPendingOutgoingBonding() != null) {
9219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.d(TAG, "Ignoring createBond(): another device is bonding");
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // a different device is currently bonding, fail
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check for bond state only if we are not performing auto
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // pairing exponential back-off attempts.
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
929005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly                mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) {
9309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.d(TAG, "Ignoring createBond(): this device is already bonding or bonded");
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9343fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        if (address.equals(mDockAddress)) {
9353fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            if (!writeDockPin()) {
9369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                Log.e(TAG, "Error while writing Pin for the dock");
9373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh                return false;
9383fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh            }
9393fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh        }
940cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        return true;
941cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    }
9423fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
943cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    public synchronized boolean createBond(String address) {
944cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (!isBondingFeasible(address)) return false;
945cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
946cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (!createPairedDeviceNative(address, 60000  /*1 minute*/ )) {
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9502092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        mBondState.setPendingOutgoingBonding(address);
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
9522092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
956cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    public synchronized boolean createBondOutOfBand(String address, byte[] hash,
957cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh                                                    byte[] randomizer) {
958cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (!isBondingFeasible(address)) return false;
9593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
960cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (!createPairedDeviceOutOfBandNative(address, 60000 /* 1 minute */)) {
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
964cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        setDeviceOutOfBandData(address, hash, randomizer);
9652092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        mBondState.setPendingOutgoingBonding(address);
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
9672092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
971cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    public synchronized boolean setDeviceOutOfBandData(String address, byte[] hash,
972cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            byte[] randomizer) {
973cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
974cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
975cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (!isEnabledInternal()) return false;
976cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
977cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        Pair <byte[], byte[]> value = new Pair<byte[], byte[]>(hash, randomizer);
978cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
979cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (DBG) {
9809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.d(TAG, "Setting out of band data for: " + address + ":" +
9819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                  Arrays.toString(hash) + ":" + Arrays.toString(randomizer));
982cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        }
983cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
984cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        mDeviceOobData.put(address, value);
985cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        return true;
986cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    }
987cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
988cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    Pair<byte[], byte[]> getDeviceOutOfBandData(BluetoothDevice device) {
989cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        return mDeviceOobData.get(device.getAddress());
990cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    }
991cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
992cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
993cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    public synchronized byte[] readOutOfBandData() {
994cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
995cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh                                                "Need BLUETOOTH permission");
996cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (!isEnabledInternal()) return null;
997cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
998cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        return readAdapterOutOfBandDataNative();
999cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    }
1000cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean cancelBondProcess(String address) {
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
10048c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
10058c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
1006005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) {
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1014005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
1016d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        cancelDeviceCreationNative(address);
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean removeBond(String address) {
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
10238c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
10248c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
1025005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1028f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
10299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (state != null) {
1030f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            state.sendMessage(BluetoothDeviceProfileState.UNPAIR);
10319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            return true;
10329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        } else {
10339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            return false;
10349b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
10359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
10369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
10379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public synchronized boolean removeBondInternal(String address) {
1038cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh        // Unset the trusted device state and then unpair
1039cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh        setTrust(address, false);
1040d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return removeDeviceNative(getObjectPathFromAddress(address));
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized String[] listBonds() {
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBondState.listInState(BluetoothDevice.BOND_BONDED);
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1048a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    /*package*/ synchronized String[] listInState(int state) {
1049a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh      return mBondState.listInState(state);
1050a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    }
1051a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getBondState(String address) {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1054005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
1055b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly            return BluetoothDevice.ERROR;
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBondState.getBondState(address.toUpperCase());
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1060a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    /*package*/ synchronized boolean setBondState(String address, int state) {
1061a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        return setBondState(address, state, 0);
1062a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    }
1063a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
1064a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    /*package*/ synchronized boolean setBondState(String address, int state, int reason) {
1065ae5fbb0b4363a2a399e92e310777d7a955a25370Arek Lichwa        mBondState.setBondState(address.toUpperCase(), state, reason);
1066a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh        return true;
1067a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh    }
1068a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh
10693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    public synchronized boolean isBluetoothDock(String address) {
10706e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh        SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
10719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                Context.MODE_PRIVATE);
10726e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh
10736e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh        return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address);
10743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh    }
10753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh
10769488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh    /*package*/ String[] getRemoteDeviceProperties(String address) {
10778c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return null;
10788c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
10799488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh        String objectPath = getObjectPathFromAddress(address);
10809488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh        return (String [])getDevicePropertiesNative(objectPath);
10819488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh    }
10829488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1084efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * Sets the remote device trust state.
1085efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     *
1086efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * @return boolean to indicate operation success or fail
1087efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     */
1088efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    public synchronized boolean setTrust(String address, boolean value) {
1089005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
1090e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1091e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly                    "Need BLUETOOTH_ADMIN permission");
1092efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            return false;
1093efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        }
1094efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
10958c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
10968c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
10979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return setDevicePropertyBooleanNative(
10989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                getObjectPathFromAddress(address), "Trusted", value ? 1 : 0);
1099efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    }
1100efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
1101efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    /**
1102efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * Gets the remote device trust state as boolean.
1103efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * Note: this value may be
1104efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * retrieved from cache if we retrieved the data before *
1105efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     *
11069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby     * @return boolean to indicate trusted or untrusted state
1107efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     */
1108efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    public synchronized boolean getTrustState(String address) {
1109005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
1110efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1111efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            return false;
1112efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        }
1113efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
11149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String val = mDeviceProperties.getProperty(address, "Trusted");
1115efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        if (val == null) {
1116efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            return false;
1117efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        } else {
11189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            return val.equals("true");
1119efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        }
1120efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    }
1121efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
1122efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    /**
1123d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Gets the remote major, minor classes encoded as a 32-bit
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * integer.
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Note: this value is retrieved from cache, because we get it during
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *       remote-device discovery.
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return 32-bit integer encoding the remote major, minor, and service
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         classes.
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getRemoteClass(String address) {
1133005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
1134ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1135ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly            return BluetoothClass.ERROR;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String val = mDeviceProperties.getProperty(address, "Class");
1138d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (val == null)
1139d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return BluetoothClass.ERROR;
1140d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else {
1141d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return Integer.valueOf(val);
1142d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1144d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1147dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh     * Gets the UUIDs supported by the remote device
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1149dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh     * @return array of 128bit ParcelUuids
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1151dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh    public synchronized ParcelUuid[] getRemoteUuids(String address) {
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1153005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11561caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        return getUuidFromCache(address);
11571caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    }
11581caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
11599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    ParcelUuid[] getUuidFromCache(String address) {
11609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String value = mDeviceProperties.getProperty(address, "UUIDs");
1161dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        if (value == null) return null;
1162dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh
1163dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        String[] uuidStrings = null;
1164d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        // The UUIDs are stored as a "," separated string.
1165dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        uuidStrings = value.split(",");
1166dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
1167dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh
1168dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        for (int i = 0; i < uuidStrings.length; i++) {
1169dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
1170dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        }
1171d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return uuids;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
117416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    /**
117516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * Connect and fetch new UUID's using SDP.
117616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * The UUID's found are broadcast as intents.
117716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * Optionally takes a uuid and callback to fetch the RFCOMM channel for the
117816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * a given uuid.
117916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success
118016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for
118116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * callback and broadcast intents.
118216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     */
118316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid,
118416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            IBluetoothCallback callback) {
11851caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
11868c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
11878c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
11881caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
11891caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            return false;
11901caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        }
11911caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
119216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        RemoteService service = new RemoteService(address, uuid);
119316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        if (uuid != null && mUuidCallbackTracker.get(service) != null) {
119416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            // An SDP query for this address & uuid is already in progress
119516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            // Do not add this callback for the uuid
119616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            return false;
119716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
119816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
11991caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        if (mUuidIntentTracker.contains(address)) {
12001caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            // An SDP query for this address is already in progress
120116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            // Add this uuid onto the in-progress SDP query
120216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            if (uuid != null) {
120316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
120416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            }
12051caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            return true;
12061caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        }
12071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
1208421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh        // If the device is already created, we will
1209421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh        // do the SDP on the callback of createDeviceNative.
1210421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh        boolean ret= createDeviceNative(address);
12111caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
12121caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mUuidIntentTracker.add(address);
121316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        if (uuid != null) {
121416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
121516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
12161caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
12171caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT);
12181caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        message.obj = address;
12191caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY);
12201caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        return ret;
12211caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    }
12221caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1224d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Gets the rfcomm channel associated with the UUID.
122516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly     * Pulls records from the cache only.
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1227d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @param address Address of the remote device
1228dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh     * @param uuid ParcelUuid of the service attribute
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1230d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @return rfcomm channel associated with the service attribute
123110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh     *         -1 on error
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1233dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh    public int getRemoteServiceChannel(String address, ParcelUuid uuid) {
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
12358c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return -1;
12368c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
1237005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
1238b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly            return BluetoothDevice.ERROR;
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
124010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // Check if we are recovering from a crash.
124110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        if (mDeviceProperties.isEmpty()) {
12429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            if (mDeviceProperties.updateCache(address) == null)
124310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                return -1;
124410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        }
124510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
124610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address);
124710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        if (value != null && value.containsKey(uuid))
124810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            return value.get(uuid);
124910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        return -1;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean setPin(String address, byte[] pin) {
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
12558c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
12568c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pin == null || pin.length <= 0 || pin.length > 16 ||
1258005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            !BluetoothAdapter.checkBluetoothAddress(address)) {
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (data == null) {
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "setPin(" + address + ") called but no native data available, " +
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  " or by bluez.\n");
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // bluez API wants pin as a string
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String pinString;
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pinString = new String(pin, "UTF8");
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (UnsupportedEncodingException uee) {
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "UTF8 not supported?!?");
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return setPinNative(address, pinString, data.intValue());
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1280b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    public synchronized boolean setPasskey(String address, int passkey) {
1281b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1282b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
12838c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
12848c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
1285005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) {
1286b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            return false;
1287b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        }
1288b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        address = address.toUpperCase();
1289b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
1290b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        if (data == null) {
1291b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
1292b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
1293b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  " or by bluez.\n");
1294b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            return false;
1295b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        }
1296b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        return setPasskeyNative(address, passkey, data.intValue());
1297b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    }
1298b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh
1299b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    public synchronized boolean setPairingConfirmation(String address, boolean confirm) {
1300b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1301b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
13028c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
13038c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
1304b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        address = address.toUpperCase();
1305b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
1306b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        if (data == null) {
1307b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
1308b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
1309b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  " or by bluez.\n");
1310b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            return false;
1311b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        }
1312b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        return setPairingConfirmationNative(address, confirm, data.intValue());
1313b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    }
1314b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh
1315cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    public synchronized boolean setRemoteOutOfBandData(String address) {
1316cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1317cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
1318cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (!isEnabledInternal()) return false;
1319cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        address = address.toUpperCase();
1320cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
1321cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (data == null) {
1322cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            Log.w(TAG, "setRemoteOobData(" + address + ") called but no native data available, " +
1323cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
1324cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh                  " or by bluez.\n");
1325cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            return false;
1326cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        }
1327cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
1328cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        Pair<byte[], byte[]> val = mDeviceOobData.get(address);
1329cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        byte[] hash, randomizer;
1330cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        if (val == null) {
1331cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            // TODO: check what should be passed in this case.
1332cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            hash = new byte[16];
1333cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            randomizer = new byte[16];
1334cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        } else {
1335cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            hash = val.first;
1336cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh            randomizer = val.second;
1337cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        }
1338cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh        return setRemoteOutOfBandDataNative(address, hash, randomizer, data.intValue());
1339cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    }
1340cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
1341b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    public synchronized boolean cancelPairingUserInput(String address) {
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
13448c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return false;
13458c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
1346005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1349005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
1350397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (data == null) {
1354b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " +
1355b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " +
1356b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                "by the remote or by bluez.\n");
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1359b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        return cancelPairingUserInputNative(address, data.intValue());
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13628c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh    /*package*/ void updateDeviceServiceChannelCache(String address) {
13639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        if (DBG) Log.d(TAG, "updateDeviceServiceChannelCache(" + address + ")");
13649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
136510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // We are storing the rfcomm channel numbers only for the uuids
136610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // we are interested in.
13679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        ParcelUuid[] deviceUuids = getRemoteUuids(address);
136816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
13699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        ArrayList<ParcelUuid> applicationUuids = new ArrayList<ParcelUuid>();
137016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
137116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        synchronized (this) {
137216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            for (RemoteService service : mUuidCallbackTracker.keySet()) {
137316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                if (service.address.equals(address)) {
137416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                    applicationUuids.add(service.uuid);
137516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                }
137616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            }
137716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
137810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
13799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        Map <ParcelUuid, Integer> uuidToChannelMap = new HashMap<ParcelUuid, Integer>();
138016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
138116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        // Retrieve RFCOMM channel for default uuids
138216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        for (ParcelUuid uuid : RFCOMM_UUIDS) {
138310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) {
13849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                int channel = getDeviceServiceChannelForUuid(address, uuid);
13859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                uuidToChannelMap.put(uuid, channel);
13869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                if (DBG) Log.d(TAG, "\tuuid(system): " + uuid + " " + channel);
138710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            }
138810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        }
138916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        // Retrieve RFCOMM channel for application requested uuids
139016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        for (ParcelUuid uuid : applicationUuids) {
139116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) {
13929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                int channel = getDeviceServiceChannelForUuid(address, uuid);
13939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                uuidToChannelMap.put(uuid, channel);
13949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                if (DBG) Log.d(TAG, "\tuuid(application): " + uuid + " " + channel);
139516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            }
139616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
139716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
139816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        synchronized (this) {
139916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            // Make application callbacks
140016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator();
140116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                    iter.hasNext();) {
140216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                RemoteService service = iter.next();
140316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                if (service.address.equals(address)) {
14049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    if (uuidToChannelMap.containsKey(service.uuid)) {
14059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                        int channel = uuidToChannelMap.get(service.uuid);
14069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
14079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                        if (DBG) Log.d(TAG, "Making callback for " + service.uuid +
14089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                                    " with result " + channel);
140916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                        IBluetoothCallback callback = mUuidCallbackTracker.get(service);
141016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                        if (callback != null) {
141116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                            try {
141216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                                callback.onRfcommChannelFound(channel);
141316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                            } catch (RemoteException e) {Log.e(TAG, "", e);}
141416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                        }
141516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
141616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                        iter.remove();
141716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                    }
141816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                }
141916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            }
142016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
142116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            // Update cache
14229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            mDeviceServiceChannelCache.put(address, uuidToChannelMap);
142316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
142410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh    }
142510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
14269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private int getDeviceServiceChannelForUuid(String address,
14279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            ParcelUuid uuid) {
14289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return getDeviceServiceChannelNative(getObjectPathFromAddress(address),
14299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                uuid.toString(), 0x0004);
14309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
14319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
143224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    /**
143324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly     * b is a handle to a Binder instance, so that this service can be notified
143424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly     * for Applications that terminate unexpectedly, to clean there service
143524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly     * records
143624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly     */
143724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid,
143824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            int channel, IBinder b) {
14398c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
14408c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh        if (!isEnabledInternal()) return -1;
14418c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh
144224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        if (serviceName == null || uuid == null || channel < 1 ||
144324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly                channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) {
144424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            return -1;
144524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
144624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) {
144724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            Log.w(TAG, "Attempted to register a reserved UUID: " + uuid);
144824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            return -1;
144924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
145024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        int handle = addRfcommServiceRecordNative(serviceName,
145124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly                uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(),
145224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly                (short)channel);
14539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        if (DBG) Log.d(TAG, "new handle " + Integer.toHexString(handle));
145424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        if (handle == -1) {
145524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            return -1;
145624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
145724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
145824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        int pid = Binder.getCallingPid();
145924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        mServiceRecordToPid.put(new Integer(handle), new Integer(pid));
146024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        try {
146124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            b.linkToDeath(new Reaper(handle, pid), 0);
146224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        } catch (RemoteException e) {}
146324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        return handle;
146424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    }
146524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
146624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    public void removeServiceRecord(int handle) {
146724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
146824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly                                                "Need BLUETOOTH permission");
146924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        checkAndRemoveRecord(handle, Binder.getCallingPid());
147024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    }
147124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
147224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private synchronized void checkAndRemoveRecord(int handle, int pid) {
147324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        Integer handleInt = new Integer(handle);
147424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        Integer owner = mServiceRecordToPid.get(handleInt);
147524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        if (owner != null && pid == owner.intValue()) {
14769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            if (DBG) Log.d(TAG, "Removing service record " +
14779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                Integer.toHexString(handle) + " for pid " + pid);
147824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            mServiceRecordToPid.remove(handleInt);
147924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            removeServiceRecordNative(handle);
148024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
148124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    }
148224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
148324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private class Reaper implements IBinder.DeathRecipient {
148424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        int pid;
148524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        int handle;
148624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        Reaper(int handle, int pid) {
148724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            this.pid = pid;
148824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            this.handle = handle;
148924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
149024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        public void binderDied() {
149124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            synchronized (BluetoothService.this) {
14929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
149324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly                checkAndRemoveRecord(handle, pid);
149424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            }
149524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
149624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    }
149724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
15016e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh            if (intent == null) return;
15026e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ContentResolver resolver = context.getContentResolver();
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Query the airplane mode from Settings.System just to make sure that
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // some random app is not sending this intent and disabling bluetooth
15087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie                if (isAirplaneModeOn()) {
15097f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON);
15107f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie                } else {
15117f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF);
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15136e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh            } else if (Intent.ACTION_DOCK_EVENT.equals(action)) {
15146e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
15156e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
15166e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state);
15176e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
15186e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                    mDockAddress = null;
15196e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                    mDockPin = null;
15206e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                } else {
15216e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                    SharedPreferences.Editor editor =
15226e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                        mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
15236e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                                mContext.MODE_PRIVATE).edit();
15246e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                    editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true);
152566fce5068a8a3aeb28aaf713843891b286a75280Brad Fitzpatrick                    editor.apply();
15266e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh                }
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15316e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh    private void registerForAirplaneMode(IntentFilter filter) {
153244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey        final ContentResolver resolver = mContext.getContentResolver();
153344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey        final String airplaneModeRadios = Settings.System.getString(resolver,
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.System.AIRPLANE_MODE_RADIOS);
153544303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey        final String toggleableRadios = Settings.System.getString(resolver,
153644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey                Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
153744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey
153844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey        mIsAirplaneSensitive = airplaneModeRadios == null ? true :
153944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey                airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
154044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey        mIsAirplaneToggleable = toggleableRadios == null ? false :
154144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey                toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH);
154244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsAirplaneSensitive) {
15446e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh            filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* Returns true if airplane mode is currently on */
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final boolean isAirplaneModeOn() {
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Settings.System.getInt(mContext.getContentResolver(),
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15541caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    /* Broadcast the Uuid intent */
15551caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    /*package*/ synchronized void sendUuidIntent(String address) {
15566179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        ParcelUuid[] uuid = getUuidFromCache(address);
15576179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        Intent intent = new Intent(BluetoothDevice.ACTION_UUID);
15582d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
15596179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid);
15606179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
15619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        mUuidIntentTracker.remove(address);
156216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    }
156316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
156416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    /*package*/ synchronized void makeServiceChannelCallbacks(String address) {
156516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator();
156616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                iter.hasNext();) {
156716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            RemoteService service = iter.next();
156816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            if (service.address.equals(address)) {
15699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                if (DBG) Log.d(TAG, "Cleaning up failed UUID channel lookup: "
15709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    + service.address + " " + service.uuid);
157116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                IBluetoothCallback callback = mUuidCallbackTracker.get(service);
157216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                if (callback != null) {
157316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                    try {
157416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                        callback.onRfcommChannelFound(-1);
157516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                    } catch (RemoteException e) {Log.e(TAG, "", e);}
157616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                }
157716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly
157816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly                iter.remove();
157916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly            }
158016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly        }
15811caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    }
15821caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
15857f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
1586105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
1587105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1588105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
158924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive);
159044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey        pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable);
159124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly
159224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        pw.println("Local address = " + getAddress());
159324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        pw.println("Local name = " + getName());
159424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        pw.println("isDiscovering() = " + isDiscovering());
1595105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
159696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        mAdapter.getProfileProxy(mContext,
159796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh                                 mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
15984ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mAdapter.getProfileProxy(mContext,
15994ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
160074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        mAdapter.getProfileProxy(mContext,
160174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                mBluetoothProfileServiceListener, BluetoothProfile.PAN);
1602105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
16039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        dumpKnownDevices(pw);
16049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        dumpAclConnectedDevices(pw);
16059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        dumpHeadsetService(pw);
16064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        dumpInputDeviceProfile(pw);
160774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        dumpPanProfile(pw);
16089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        dumpApplicationServiceRecords(pw);
16094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
16104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
16119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private void dumpHeadsetService(PrintWriter pw) {
1612105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\n--Headset Service--");
161396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        if (mBluetoothHeadset != null) {
1614bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh            List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
1615bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh            if (deviceList.size() == 0) {
161674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                pw.println("No headsets connected");
1617bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh            } else {
1618bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh                BluetoothDevice device = deviceList.get(0);
16199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                pw.println("\ngetConnectedDevices[0] = " + device);
16209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                dumpHeadsetConnectionState(pw, device);
1621bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh                pw.println("getBatteryUsageHint() = " +
1622bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh                             mBluetoothHeadset.getBatteryUsageHint(device));
162396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh            }
162496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh
16255a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh            deviceList.clear();
16265a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh            deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] {
162796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
162874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            pw.println("--Connected and Disconnected Headsets");
1629bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh            for (BluetoothDevice device: deviceList) {
163096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh                pw.println(device);
163196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh                if (mBluetoothHeadset.isAudioConnected(device)) {
163296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh                    pw.println("SCO audio connected to device:" + device);
163396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh                }
163496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh            }
1635105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
16364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
16374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
16386c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly
16394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private void dumpInputDeviceProfile(PrintWriter pw) {
16404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        pw.println("\n--Bluetooth Service- Input Device Profile");
16414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mInputDevice != null) {
16424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices();
16434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            if (deviceList.size() == 0) {
164474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                pw.println("No input devices connected");
16454ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } else {
164674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                pw.println("Number of connected devices:" + deviceList.size());
16474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                BluetoothDevice device = deviceList.get(0);
16484ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                pw.println("getConnectedDevices[0] = " + device);
16494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                pw.println("Priority of Connected device = " + mInputDevice.getPriority(device));
16504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
16514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                switch (mInputDevice.getConnectionState(device)) {
16524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    case BluetoothInputDevice.STATE_CONNECTING:
16534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        pw.println("getConnectionState() = STATE_CONNECTING");
16544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        break;
16554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    case BluetoothInputDevice.STATE_CONNECTED:
16564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        pw.println("getConnectionState() = STATE_CONNECTED");
16574ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        break;
16584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    case BluetoothInputDevice.STATE_DISCONNECTING:
16594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        pw.println("getConnectionState() = STATE_DISCONNECTING");
16604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        break;
16614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                }
16624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
16634ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            deviceList.clear();
16644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] {
16654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
16664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            pw.println("--Connected and Disconnected input devices");
16674ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            for (BluetoothDevice device: deviceList) {
16684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                pw.println(device);
16694ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
167024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly        }
16714ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset);
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
167474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh    private void dumpPanProfile(PrintWriter pw) {
167574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        pw.println("\n--Bluetooth Service- Pan Profile");
167674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        if (mPan != null) {
167774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            List<BluetoothDevice> deviceList = mPan.getConnectedDevices();
167874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            if (deviceList.size() == 0) {
167974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                pw.println("No Pan devices connected");
168074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            } else {
168174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                pw.println("Number of connected devices:" + deviceList.size());
168274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                BluetoothDevice device = deviceList.get(0);
168374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                pw.println("getConnectedDevices[0] = " + device);
168474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh
168574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                switch (mPan.getConnectionState(device)) {
168674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    case BluetoothInputDevice.STATE_CONNECTING:
168774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        pw.println("getConnectionState() = STATE_CONNECTING");
168874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        break;
168974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    case BluetoothInputDevice.STATE_CONNECTED:
169074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        pw.println("getConnectionState() = STATE_CONNECTED");
169174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        break;
169274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    case BluetoothInputDevice.STATE_DISCONNECTING:
169374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        pw.println("getConnectionState() = STATE_DISCONNECTING");
169474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        break;
169574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                }
169674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            }
169774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            deviceList.clear();
169874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            deviceList = mPan.getDevicesMatchingConnectionStates(new int[] {
169974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
170074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            pw.println("--Connected and Disconnected Pan devices");
170174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            for (BluetoothDevice device: deviceList) {
170274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                pw.println(device);
170374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            }
170474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        }
17059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
17069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
17079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private void dumpHeadsetConnectionState(PrintWriter pw,
17089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            BluetoothDevice device) {
17099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        switch (mBluetoothHeadset.getConnectionState(device)) {
17109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothHeadset.STATE_CONNECTING:
17119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                pw.println("getConnectionState() = STATE_CONNECTING");
17129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                break;
17139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothHeadset.STATE_CONNECTED:
17149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                pw.println("getConnectionState() = STATE_CONNECTED");
17159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                break;
17169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothHeadset.STATE_DISCONNECTING:
17179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                pw.println("getConnectionState() = STATE_DISCONNECTING");
17189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                break;
17199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothHeadset.STATE_AUDIO_CONNECTED:
17209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                pw.println("getConnectionState() = STATE_AUDIO_CONNECTED");
17219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                break;
17229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
17239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
17249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
17259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private void dumpApplicationServiceRecords(PrintWriter pw) {
17269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        pw.println("\n--Application Service Records--");
17279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        for (Integer handle : mServiceRecordToPid.keySet()) {
17289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Integer pid = mServiceRecordToPid.get(handle);
17299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
17309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
173174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        mAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothHeadset);
173274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh    }
173374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh
17349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private void dumpAclConnectedDevices(PrintWriter pw) {
17359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String[] devicesObjectPath = getKnownDevices();
17369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        pw.println("\n--ACL connected devices--");
17379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        if (devicesObjectPath != null) {
17389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            for (String device : devicesObjectPath) {
17399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                pw.println(getAddressFromObjectPath(device));
17409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            }
17419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
17429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
17439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
17449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private void dumpKnownDevices(PrintWriter pw) {
17459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        pw.println("\n--Known devices--");
17469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        for (String address : mDeviceProperties.keySet()) {
17479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            int bondState = mBondState.getBondState(address);
17489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            pw.printf("%s %10s (%d) %s\n", address,
17499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                       toBondStateString(bondState),
17509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                       mBondState.getAttempt(address),
17519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                       getRemoteName(address));
17529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
17539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address);
17549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            if (uuidChannels == null) {
17559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                pw.println("\tuuids = null");
17569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            } else {
17579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                for (ParcelUuid uuid : uuidChannels.keySet()) {
17589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    Integer channel = uuidChannels.get(uuid);
17599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    if (channel == null) {
17609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                        pw.println("\t" + uuid);
17619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    } else {
17629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                        pw.println("\t" + uuid + " RFCOMM channel = " + channel);
17639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    }
17649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                }
17659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            }
17669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            for (RemoteService service : mUuidCallbackTracker.keySet()) {
17679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                if (service.address.equals(address)) {
17689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    pw.println("\tPENDING CALLBACK: " + service.uuid);
17699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                }
17709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            }
17719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
17729a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
17739a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
177496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
177596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        new BluetoothProfile.ServiceListener() {
177696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        public void onServiceConnected(int profile, BluetoothProfile proxy) {
17774ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            if (profile == BluetoothProfile.HEADSET) {
17784ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                mBluetoothHeadset = (BluetoothHeadset) proxy;
17794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
17804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                mInputDevice = (BluetoothInputDevice) proxy;
178174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            } else if (profile == BluetoothProfile.PAN) {
178274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                mPan = (BluetoothPan) proxy;
17834ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
17844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        }
178596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        public void onServiceDisconnected(int profile) {
17864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            if (profile == BluetoothProfile.HEADSET) {
17874ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                mBluetoothHeadset = null;
17884ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
17894ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                mInputDevice = null;
179074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            } else if (profile == BluetoothProfile.PAN) {
179174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                mPan = null;
17924ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
179396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        }
179496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh    };
179596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh
1796d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) {
1797d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (pairable && discoverable)
1798bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1799d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else if (pairable && !discoverable)
1800bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
1801d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else
1802bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            return BluetoothAdapter.SCAN_MODE_NONE;
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* package */ static String scanModeToBluezString(int mode) {
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (mode) {
1807bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        case BluetoothAdapter.SCAN_MODE_NONE:
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "off";
1809bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connectable";
1811bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "discoverable";
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1817d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /*package*/ String getAddressFromObjectPath(String objectPath) {
18189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String adapterObjectPath = mAdapterProperties.getObjectPath();
1819d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (adapterObjectPath == null || objectPath == null) {
1820f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby            Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath +
1821d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                    "  or deviceObjectPath:" + objectPath + " is null");
1822d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
1823d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
1824d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (!objectPath.startsWith(adapterObjectPath)) {
1825f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby            Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath +
1826d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                    "  is not a prefix of deviceObjectPath:" + objectPath +
1827d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                    "bluetoothd crashed ?");
1828d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
1829d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
1830d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String address = objectPath.substring(adapterObjectPath.length());
1831d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (address != null) return address.replace('_', ':');
1832d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1833d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        Log.e(TAG, "getAddressFromObjectPath: Address being returned is null");
1834d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return null;
1835d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
1836d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1837d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /*package*/ String getObjectPathFromAddress(String address) {
18389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String path = mAdapterProperties.getObjectPath();
1839d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (path == null) {
1840d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            Log.e(TAG, "Error: Object Path is null");
1841d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
1842d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
1843d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        path = path + address.replace(":", "_");
1844d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return path;
1845d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
1846d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1847b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh    /*package */ void setLinkTimeout(String address, int num_slots) {
1848b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh        String path = getObjectPathFromAddress(address);
1849b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh        boolean result = setLinkTimeoutNative(path, num_slots);
1850b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh
18519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        if (!result) Log.d(TAG, "Set Link Timeout to " + num_slots + " slots failed");
1852b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh    }
1853b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh
185430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    /**** Handlers for PAN  Profile ****/
18556003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    // TODO: This needs to be converted to a state machine.
185630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
18576003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean isTetheringOn() {
185830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
18596003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
18606003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothPanProfileHandler.isTetheringOn();
18616003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
186230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
186330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
18646003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    /*package*/boolean allowIncomingTethering() {
18656003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
18666003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothPanProfileHandler.allowIncomingTethering();
18676003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
186830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
186930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
18706003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public void setBluetoothTethering(boolean value) {
187130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
18726003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
18736003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            mBluetoothPanProfileHandler.setBluetoothTethering(value);
18746003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
187530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
187630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
18776003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public int getPanDeviceConnectionState(BluetoothDevice device) {
187830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
18796003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
18806003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device);
18816003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
188230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
188330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
18846003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean connectPanDevice(BluetoothDevice device) {
188530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
188630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh            "Need BLUETOOTH_ADMIN permission");
18876003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
18886003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothPanProfileHandler.connectPanDevice(device);
18896003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
189030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
189130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
18926003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public List<BluetoothDevice> getConnectedPanDevices() {
189330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
18946003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
18956003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothPanProfileHandler.getConnectedPanDevices();
18966003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
189730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
189830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
18996003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public List<BluetoothDevice> getPanDevicesMatchingConnectionStates(
190074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            int[] states) {
190174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
19026003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
19036003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states);
19046003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
190574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh    }
190674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh
19076003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean disconnectPanDevice(BluetoothDevice device) {
190830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
190930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh            "Need BLUETOOTH_ADMIN permission");
19106003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
19116003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothPanProfileHandler.disconnectPanDevice(device);
19126003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
191330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
191430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19156003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
191630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh                                                             String iface,
191730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh                                                             int state,
191830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh                                                             int role) {
19196003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
19206003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role);
19216003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
192230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
192330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19246003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
192530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh                                                             int state, int role) {
19266003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothPanProfileHandler) {
19276003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role);
19286003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
192930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
193030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
193130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    /**** Handlers for Input Device Profile ****/
19326003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    // This needs to be converted to state machine
193330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19346003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean connectInputDevice(BluetoothDevice device) {
193530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
193630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
193730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
19386003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19396003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.connectInputDevice(device, state);
19406003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
194130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
194230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19436003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean connectInputDeviceInternal(BluetoothDevice device) {
19446003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19456003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.connectInputDeviceInternal(device);
19466003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
194730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
194830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19496003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean disconnectInputDevice(BluetoothDevice device) {
195030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
195130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
195230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
19536003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19546003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.disconnectInputDevice(device, state);
19556003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
195630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
195730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19586003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean disconnectInputDeviceInternal(BluetoothDevice device) {
19596003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19606003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
19616003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
196230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
196330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19646003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public int getInputDeviceConnectionState(BluetoothDevice device) {
196530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
19666003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19676003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device);
19686003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
196930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
197030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19716003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public List<BluetoothDevice> getConnectedInputDevices() {
197230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
19736003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19746003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.getConnectedInputDevices();
19756003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
197630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
197730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19786003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public List<BluetoothDevice> getInputDevicesMatchingConnectionStates(
19794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            int[] states) {
19804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
19816003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19826003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states);
19836003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
19844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
19854ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
19864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
19876003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public int getInputDevicePriority(BluetoothDevice device) {
198830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
19896003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19906003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.getInputDevicePriority(device);
19916003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
199230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
199330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
19946003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    public boolean setInputDevicePriority(BluetoothDevice device, int priority) {
199530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
199630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
19976003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
19986003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority);
19996003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
200030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
200130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
2002a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    public boolean allowIncomingHidConnect(BluetoothDevice device, boolean allow) {
2003a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
2004a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                                                "Need BLUETOOTH_ADMIN permission");
2005a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        String address = device.getAddress();
2006a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
2007a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            return false;
2008a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2009a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2010a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        Integer data = getAuthorizationAgentRequestData(address);
2011a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (data == null) {
2012a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            Log.w(TAG, "allowIncomingHidConnect(" + device +
2013a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  ") called but no native data available");
2014a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            return false;
2015a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2016a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (DBG) log("allowIncomingHidConnect: " + device + " : " + allow + " : " + data);
2017a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        return setAuthorizationNative(address, allow, data.intValue());
2018a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2019a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
20206003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
20216003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
20226003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states);
20236003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
202430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
202530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
20266003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh    /*package*/void handleInputDevicePropertyChange(String address, boolean connected) {
20276003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        synchronized (mBluetoothInputProfileHandler) {
20286003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh            mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected);
20296003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh        }
203030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    }
203130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh
20322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    /**** Handlers for Health Device Profile ****/
20332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    // TODO: All these need to be converted to a state machine.
20342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
2035fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh    public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
2036fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh                                            IBluetoothHealthCallback callback) {
20372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
20382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
20392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
2040fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh                return mBluetoothHealthProfileHandler.registerAppConfiguration(config, callback);
20412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
20422ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
20432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
20452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
20462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
20472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
20482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                return mBluetoothHealthProfileHandler.unregisterAppConfiguration(config);
20492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
20502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
20512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public boolean connectChannelToSource(BluetoothDevice device,
20542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            BluetoothHealthAppConfiguration config) {
20552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
20562ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
20572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
20582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            return mBluetoothHealthProfileHandler.connectChannelToSource(device,
20592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                    config);
20602ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
20612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
20622ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public boolean connectChannelToSink(BluetoothDevice device,
20642ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            BluetoothHealthAppConfiguration config, int channelType) {
20652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
20662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                                                "Need BLUETOOTH permission");
20672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
20682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            return mBluetoothHealthProfileHandler.connectChannel(device, config,
20692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                    channelType);
20702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
20712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
20722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public boolean disconnectChannel(BluetoothDevice device,
20742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
20752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
20762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
20772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
20782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            return mBluetoothHealthProfileHandler.disconnectChannel(device, config, fd);
20792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
20802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
20812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
20832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            BluetoothHealthAppConfiguration config) {
20842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
20852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
20862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
20872ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            return mBluetoothHealthProfileHandler.getMainChannelFd(device, config);
20882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
20892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
20902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20912ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    /*package*/ void onHealthDevicePropertyChanged(String devicePath,
20922ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            String channelPath) {
20932ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
20942ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            mBluetoothHealthProfileHandler.onHealthDevicePropertyChanged(devicePath,
20952ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                    channelPath);
20962ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
20972ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
20982ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
20992ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    /*package*/ void onHealthDeviceChannelChanged(String devicePath,
21002ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            String channelPath, boolean exists) {
21012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized(mBluetoothHealthProfileHandler) {
21022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            mBluetoothHealthProfileHandler.onHealthDeviceChannelChanged(devicePath,
21032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                    channelPath, exists);
21042ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
21052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
21062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
21072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public int getHealthDeviceConnectionState(BluetoothDevice device) {
21082ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
21092ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
21102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
21112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            return mBluetoothHealthProfileHandler.getHealthDeviceConnectionState(device);
21122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
21132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
21142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
21152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public List<BluetoothDevice> getConnectedHealthDevices() {
21162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
21172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
21182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
21192ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            return mBluetoothHealthProfileHandler.getConnectedHealthDevices();
21202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
21212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
21222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
21232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(
21242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            int[] states) {
21252ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
21262ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                "Need BLUETOOTH permission");
21272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        synchronized (mBluetoothHealthProfileHandler) {
21282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            return mBluetoothHealthProfileHandler.
21292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh                    getHealthDevicesMatchingConnectionStates(states);
21302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh        }
21312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    }
21322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
2133a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    /*package*/boolean notifyIncomingHidConnection(String address) {
2134a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
2135a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (state == null) {
2136a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            return false;
2137a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2138a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        Message msg = new Message();
2139a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        msg.what = BluetoothDeviceProfileState.CONNECT_HID_INCOMING;
2140a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        state.sendMessage(msg);
2141a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        return true;
2142a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2143a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
21449b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public boolean connectHeadset(String address) {
214596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
214696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh
2147f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
21489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (state != null) {
2149f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            Message msg = new Message();
2150f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING;
2151f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.obj = state;
2152f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            mHfpProfileState.sendMessage(msg);
2153f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            return true;
21549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
21559b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return false;
21569b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
21579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
21589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public boolean disconnectHeadset(String address) {
215996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
216096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh
2161f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
21629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (state != null) {
2163f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            Message msg = new Message();
2164f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING;
2165f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.obj = state;
2166f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            mHfpProfileState.sendMessage(msg);
21679b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            return true;
21689b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
21699b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return false;
21709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
21719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
21729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public boolean connectSink(String address) {
217396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
217496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh
2175f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
21769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (state != null) {
2177f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            Message msg = new Message();
2178f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING;
2179f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.obj = state;
2180f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            mA2dpProfileState.sendMessage(msg);
2181f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            return true;
21829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
21839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return false;
21849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
21859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
21869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public boolean disconnectSink(String address) {
218796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
218896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh
2189f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
21909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (state != null) {
2191f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            Message msg = new Message();
2192f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING;
2193f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.obj = state;
2194f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            mA2dpProfileState.sendMessage(msg);
21959b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            return true;
21969b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
21979b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return false;
21989b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
21999b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
22009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    BluetoothDeviceProfileState addProfileState(String address) {
2201f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
22029b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (state != null) return state;
22039b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
2204f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService);
2205f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        mDeviceProfileState.put(address, state);
22069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        state.start();
22079b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return state;
22089b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
22099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
22109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    void removeProfileState(String address) {
2211f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        mDeviceProfileState.remove(address);
22129b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
22139b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
22149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    synchronized String[] getKnownDevices() {
22159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String[] bonds = null;
22169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String val = getProperty("Devices");
22179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        if (val != null) {
22189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            bonds = val.split(",");
22199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
22209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return bonds;
22219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
22229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
22239b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    private void initProfileState() {
22249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String[] bonds = null;
22259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String val = mAdapterProperties.getProperty("Devices");
22269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (val != null) {
22279b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            bonds = val.split(",");
22289b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
22299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (bonds == null) {
22309b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            return;
22319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
22329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        for (String path : bonds) {
22339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            String address = getAddressFromObjectPath(path);
2234f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            BluetoothDeviceProfileState state = addProfileState(address);
22359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
22369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
22379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
22389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private void autoConnect() {
22399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        String[] bonds = getKnownDevices();
22409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        if (bonds == null) {
22419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            return;
22429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
22439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        for (String path : bonds) {
22449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            String address = getAddressFromObjectPath(path);
22459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
22469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            if (state != null) {
22479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                Message msg = new Message();
22489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES;
22499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                state.sendMessage(msg);
22509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            }
22519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
22529b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
22539b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
22549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public boolean notifyIncomingConnection(String address) {
2255f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh        BluetoothDeviceProfileState state =
2256f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh             mDeviceProfileState.get(address);
22579b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (state != null) {
22589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            Message msg = new Message();
2259f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING;
22609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            state.sendMessage(msg);
22619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            return true;
22629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
22639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return false;
22649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
22659b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
22669b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    /*package*/ boolean notifyIncomingA2dpConnection(String address) {
2267f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh       BluetoothDeviceProfileState state =
2268f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh            mDeviceProfileState.get(address);
22699b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh       if (state != null) {
22709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh           Message msg = new Message();
2271f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh           msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING;
22729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh           state.sendMessage(msg);
22739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh           return true;
22749b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh       }
22759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh       return false;
22769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
22779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
22789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) {
22799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        mA2dpService = a2dpService;
22809b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
22819b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
2282a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    /*package*/ Integer getAuthorizationAgentRequestData(String address) {
2283a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        Integer data = mEventLoop.getAuthorizationAgentRequestData().remove(address);
2284a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        return data;
2285a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2286a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
228770a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh    public void sendProfileStateMessage(int profile, int cmd) {
228870a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh        Message msg = new Message();
228970a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh        msg.what = cmd;
229070a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh        if (profile == BluetoothProfileState.HFP) {
229170a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh            mHfpProfileState.sendMessage(msg);
229270a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh        } else if (profile == BluetoothProfileState.A2DP) {
229370a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh            mA2dpProfileState.sendMessage(msg);
229470a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh        }
229570a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh    }
229670a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh
2297c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh    public int getAdapterConnectionState() {
2298c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh        return mAdapterConnectionState;
2299c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh    }
2300c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh
2301a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh    public synchronized void sendConnectionStateChange(BluetoothDevice device, int state,
2302a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh                                                        int prevState) {
23039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        // Since this is a binder call check if Bluetooth is on still
23047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie        if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
23059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
23069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
23079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            if (!validateProfileConnectionState(state) ||
23089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    !validateProfileConnectionState(prevState)) {
23099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                // Previously, an invalid state was broadcast anyway,
23109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                // with the invalid state converted to -1 in the intent.
23119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                // Better to log an error and not send an intent with
23129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                // invalid contents or set mAdapterConnectionState to -1.
23139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                Log.e(TAG, "Error in sendConnectionStateChange: "
23149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                        + "prevState " + prevState + " state " + state);
23159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return;
23169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            }
2317c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh
2318c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh            mAdapterConnectionState = state;
2319c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh
23207f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            if (state == BluetoothProfile.STATE_DISCONNECTED) {
23217f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie                mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED);
23227f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie            }
23237f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie
2324a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
2325a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
23269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
23279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    convertToAdapterState(state));
23289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
23299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    convertToAdapterState(prevState));
233060b4d2a2bd232a7116fd037501cac704f328c0a1Jaikumar Ganesh            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2331a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
23329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": "
23339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                    + prevState + " -> " + state);
2334a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        }
2335a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh    }
2336a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh
23379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private boolean validateProfileConnectionState(int state) {
23389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return (state == BluetoothProfile.STATE_DISCONNECTED ||
23399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                state == BluetoothProfile.STATE_CONNECTING ||
23409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                state == BluetoothProfile.STATE_CONNECTED ||
23419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                state == BluetoothProfile.STATE_DISCONNECTING);
23429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
23439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
23449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private int convertToAdapterState(int state) {
2345a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        switch (state) {
23469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothProfile.STATE_DISCONNECTED:
23479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return BluetoothAdapter.STATE_DISCONNECTED;
23489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothProfile.STATE_DISCONNECTING:
23499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return BluetoothAdapter.STATE_DISCONNECTING;
23509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothProfile.STATE_CONNECTED:
23519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return BluetoothAdapter.STATE_CONNECTED;
2352a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            case BluetoothProfile.STATE_CONNECTING:
2353a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh                return BluetoothAdapter.STATE_CONNECTING;
23549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        }
23559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        Log.e(TAG, "Error in convertToAdapterState");
23569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        return -1;
23579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    }
23589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
23599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) {
23609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby        switch (prevState) {
23619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            case BluetoothProfile.STATE_CONNECTING:
23629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                mProfilesConnecting--;
23639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                break;
23649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
2365a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            case BluetoothProfile.STATE_CONNECTED:
23669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                mProfilesConnected--;
23679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                break;
23689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby
2369a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            case BluetoothProfile.STATE_DISCONNECTING:
23709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                mProfilesDisconnecting--;
23719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                break;
2372a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        }
2373a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh
2374a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        switch (state) {
2375a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            case BluetoothProfile.STATE_CONNECTING:
2376a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh                mProfilesConnecting++;
23779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return (mProfilesConnected == 0 && mProfilesConnecting == 1);
2378a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh
2379a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            case BluetoothProfile.STATE_CONNECTED:
2380a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh                mProfilesConnected++;
23819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return (mProfilesConnected == 1);
2382a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh
2383a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            case BluetoothProfile.STATE_DISCONNECTING:
2384a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh                mProfilesDisconnecting++;
23859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return (mProfilesConnected == 0 && mProfilesDisconnecting == 1);
2386a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh
2387a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh            case BluetoothProfile.STATE_DISCONNECTED:
23889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return (mProfilesConnected == 0 && mProfilesConnecting == 0);
2389a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh
23909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby            default:
23919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby                return true;
2392a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh        }
23939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2394d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
2395a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    private void createIncomingConnectionStateFile() {
2396a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        File f = new File(INCOMING_CONNECTION_FILE);
2397a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (!f.exists()) {
2398a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            try {
2399a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                f.createNewFile();
2400a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } catch (IOException e) {
2401a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                Log.e(TAG, "IOException: cannot create file");
2402a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            }
2403a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2404a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2405a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2406a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    /** @hide */
2407a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    public Pair<Integer, String> getIncomingState(String address) {
2408a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (mIncomingConnections.isEmpty()) {
2409a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            createIncomingConnectionStateFile();
2410a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            readIncomingConnectionState();
2411a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2412a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        return mIncomingConnections.get(address);
2413a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2414a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2415a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    private void readIncomingConnectionState() {
2416a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        synchronized(mIncomingConnections) {
2417a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            FileInputStream fstream = null;
2418a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            try {
2419a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie              fstream = new FileInputStream(INCOMING_CONNECTION_FILE);
2420a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie              DataInputStream in = new DataInputStream(fstream);
2421a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie              BufferedReader file = new BufferedReader(new InputStreamReader(in));
2422a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie              String line;
2423a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie              while((line = file.readLine()) != null) {
2424a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  line = line.trim();
2425a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  if (line.length() == 0) continue;
2426a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  String[] value = line.split(",");
2427a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  if (value != null && value.length == 3) {
2428a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                      Integer val1 = Integer.parseInt(value[1]);
2429a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                      Pair<Integer, String> val = new Pair(val1, value[2]);
2430a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                      mIncomingConnections.put(value[0], val);
2431a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  }
2432a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie              }
2433a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } catch (FileNotFoundException e) {
2434a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                log("FileNotFoundException: readIncomingConnectionState" + e.toString());
2435a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } catch (IOException e) {
2436a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                log("IOException: readIncomingConnectionState" + e.toString());
2437a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } finally {
2438a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                if (fstream != null) {
2439a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    try {
2440a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                        fstream.close();
2441a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    } catch (IOException e) {
2442a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                        // Ignore
2443a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    }
2444a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                }
2445a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            }
2446a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2447a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2448a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2449a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    private void truncateIncomingConnectionFile() {
2450a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        RandomAccessFile r = null;
2451a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        try {
2452a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            r = new RandomAccessFile(INCOMING_CONNECTION_FILE, "rw");
2453a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            r.setLength(0);
2454a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        } catch (FileNotFoundException e) {
2455a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            log("FileNotFoundException: truncateIncomingConnectionState" + e.toString());
2456a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        } catch (IOException e) {
2457a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            log("IOException: truncateIncomingConnectionState" + e.toString());
2458a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        } finally {
2459a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            if (r != null) {
2460a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                try {
2461a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    r.close();
2462a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                } catch (IOException e) {
2463a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    // ignore
2464a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                 }
2465a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            }
2466a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2467a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2468a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2469a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    /** @hide */
2470a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    public void writeIncomingConnectionState(String address, Pair<Integer, String> data) {
2471a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        synchronized(mIncomingConnections) {
2472a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            mIncomingConnections.put(address, data);
2473a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2474a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            truncateIncomingConnectionFile();
2475a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            BufferedWriter out = null;
2476a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            StringBuilder value = new StringBuilder();
2477a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            try {
2478a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                out = new BufferedWriter(new FileWriter(INCOMING_CONNECTION_FILE, true));
2479a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                for (String devAddress: mIncomingConnections.keySet()) {
2480a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  Pair<Integer, String> val = mIncomingConnections.get(devAddress);
2481a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  value.append(devAddress);
2482a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  value.append(",");
2483a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  value.append(val.first.toString());
2484a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  value.append(",");
2485a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  value.append(val.second);
2486a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                  value.append("\n");
2487a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                }
2488a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                out.write(value.toString());
2489a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } catch (FileNotFoundException e) {
2490a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                log("FileNotFoundException: writeIncomingConnectionState" + e.toString());
2491a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } catch (IOException e) {
2492a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                log("IOException: writeIncomingConnectionState" + e.toString());
2493a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } finally {
2494a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                if (out != null) {
2495a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    try {
2496a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                        out.close();
2497a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    } catch (IOException e) {
2498a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                        // Ignore
2499a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                    }
2500a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                }
2501a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            }
2502a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
2503a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2504a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2505a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    private static void log(String msg) {
2506a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        Log.d(TAG, msg);
2507a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
2508a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
2509d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native static void classInitNative();
2510d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native void initializeNativeDataNative();
2511d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setupNativeDataNative();
2512d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean tearDownNativeDataNative();
2513d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native void cleanupNativeDataNative();
25149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    /*package*/ native String getAdapterPathNative();
2515d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
2516d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native int isEnabledNative();
25177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /*package*/ native int enableNative();
25187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie    /*package*/ native int disableNative();
2519d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
25209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby    /*package*/ native Object[] getAdapterPropertiesNative();
2521d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native Object[] getDevicePropertiesNative(String objectPath);
2522d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setAdapterPropertyStringNative(String key, String value);
2523d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setAdapterPropertyIntegerNative(String key, int value);
2524d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setAdapterPropertyBooleanNative(String key, int value);
2525d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
2526d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean startDiscoveryNative();
2527d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean stopDiscoveryNative();
2528d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
2529d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean createPairedDeviceNative(String address, int timeout_ms);
2530cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    private native boolean createPairedDeviceOutOfBandNative(String address, int timeout_ms);
2531cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    private native byte[] readAdapterOutOfBandDataNative();
2532cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
2533d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean cancelDeviceCreationNative(String address);
2534d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean removeDeviceNative(String objectPath);
2535d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native int getDeviceServiceChannelNative(String objectPath, String uuid,
2536d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            int attributeId);
2537d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
2538b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    private native boolean cancelPairingUserInputNative(String address, int nativeData);
2539d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setPinNative(String address, String pin, int nativeData);
2540b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    private native boolean setPasskeyNative(String address, int passkey, int nativeData);
2541b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    private native boolean setPairingConfirmationNative(String address, boolean confirm,
2542b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            int nativeData);
2543cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh    private native boolean setRemoteOutOfBandDataNative(String address, byte[] hash,
2544cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh                                                        byte[] randomizer, int nativeData);
2545cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh
254624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private native boolean setDevicePropertyBooleanNative(String objectPath, String key,
254724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            int value);
25481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private native boolean createDeviceNative(String address);
254916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    /*package*/ native boolean discoverServicesNative(String objectPath, String pattern);
255010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
255124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb,
255224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly            short channel);
255324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly    private native boolean removeServiceRecordNative(int handle);
2554b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh    private native boolean setLinkTimeoutNative(String path, int num_slots);
2555a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
255630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    native boolean connectInputDeviceNative(String path);
255730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh    native boolean disconnectInputDeviceNative(String path);
25586fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang
2559a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh    native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge);
2560a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh    native boolean connectPanDeviceNative(String path, String dstRole);
2561a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh    native boolean disconnectPanDeviceNative(String path);
2562a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh    native boolean disconnectPanServerDeviceNative(String path,
2563a44a1e77ef435942b2ff60e9e60d3a64b43d775bJaikumar Ganesh            String address, String iface);
256484690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh
256584690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh    private native int[] addReservedServiceRecordsNative(int[] uuuids);
256684690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh    private native boolean removeReservedServiceRecordsNative(int[] handles);
25672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh
25682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    // Health API
25692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native String registerHealthApplicationNative(int dataType, String role, String name,
25702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh            String channelType);
25712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native String registerHealthApplicationNative(int dataType, String role, String name);
25722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native boolean unregisterHealthApplicationNative(String path);
25732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native boolean createChannelNative(String devicePath, String appPath, String channelType);
25742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native boolean destroyChannelNative(String devicePath, String channelpath);
25752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native String getMainChannelNative(String path);
25762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native String getChannelApplicationNative(String channelPath);
25772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native ParcelFileDescriptor getChannelFdNative(String channelPath);
25782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh    native boolean releaseChannelFdNative(String channelPath);
2579a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    native boolean setAuthorizationNative(String address, boolean value, int data);
25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2581