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; 42ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport android.bluetooth.IBluetoothStateChangeCallback; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 486e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganeshimport android.content.SharedPreferences; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.IBinder; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.ParcelFileDescriptor; 543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport android.os.ParcelUuid; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 56105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 59cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganeshimport android.util.Pair; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 61fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganeshimport com.android.internal.app.IBatteryStats; 62fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedInputStream; 64a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.BufferedReader; 653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.BufferedWriter; 66a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.DataInputStream; 67a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.File; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileInputStream; 703fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileNotFoundException; 713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.FileWriter; 723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganeshimport java.io.IOException; 73ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport java.io.InputStreamReader; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 75a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xieimport java.io.RandomAccessFile; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 79ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport java.util.Collection; 80ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganeshimport java.util.Collections; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 8216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator; 835a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub { 87bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private static final String TAG = "BluetoothService"; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BluetoothEventLoop mEventLoop; 9298f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie private BluetoothHeadset mHeadsetProxy; 934ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private BluetoothInputDevice mInputDevice; 9474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private BluetoothPan mPan; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAirplaneSensitive; 9644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey private boolean mIsAirplaneToggleable; 977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private BluetoothAdapterStateMachine mBluetoothState; 9884690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private int[] mAdapterSdpHandles; 9950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private ParcelUuid[] mAdapterUuids; 100997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 101bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private BluetoothAdapter mAdapter; // constant after init() 1029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothBondState mBondState; // local cache of bondings 103105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final IBatteryStats mBatteryStats; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 105ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private Map<Integer, IBluetoothStateChangeCallback> mStateChangeTracker = 106ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Collections.synchronizedMap(new HashMap<Integer, IBluetoothStateChangeCallback>()); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 109a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1113fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr"; 1123fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin"; 1133fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1146e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; 1156e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; 1166e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 1177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final int MESSAGE_UUID_INTENT = 1; 1187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2; 119484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie private static final int MESSAGE_REMOVE_SERVICE_RECORD = 3; 120a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 121ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private static final int RFCOMM_RECORD_REAPER = 10; 122ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh private static final int STATE_CHANGE_REAPER = 11; 123ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 124a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // The time (in millisecs) to delay the pairing attempt after the first 125a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // auto pairing attempt fails. We use an exponential delay with 126a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and 127a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value. 128a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000; 129a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000; 1301caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1311caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // The timeout used to sent the UUIDs Intent 1321caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // This timeout should be greater than the page timeout 1331caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int UUID_INTENT_DELAY = 6000; 134105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 13516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** Always retrieve RFCOMM channel for these SDP UUIDs */ 13616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final ParcelUuid[] RFCOMM_UUIDS = { 13716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.Handsfree, 13816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.HSP, 13916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.ObexObjectPush }; 14016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothAdapterProperties mAdapterProperties; 1429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private final BluetoothDeviceProperties mDeviceProperties; 143d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 14416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache; 14516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final ArrayList<String> mUuidIntentTracker; 14616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker; 1471caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 148c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons private static class ServiceRecordClient { 149c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons int pid; 150c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons IBinder binder; 151c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons IBinder.DeathRecipient death; 152c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons } 153c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons private final HashMap<Integer, ServiceRecordClient> mServiceRecordToPid; 15424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 155f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState; 156f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mA2dpProfileState; 157f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh private final BluetoothProfileState mHfpProfileState; 1589b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 1599b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private BluetoothA2dpService mA2dpService; 160cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData; 161545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 162a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0; 163707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh 1643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private static String mDockAddress; 1653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private String mDockPin; 1663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 167c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 168a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh private BluetoothPanProfileHandler mBluetoothPanProfileHandler; 16930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh private BluetoothInputProfileHandler mBluetoothInputProfileHandler; 1702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler; 171a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private static final String INCOMING_CONNECTION_FILE = 172a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie "/data/misc/bluetooth/incoming_connection.conf"; 173a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private HashMap<String, Pair<Integer, String>> mIncomingConnections; 174cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh private HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState; 175c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 17616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static class RemoteService { 17716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public String address; 17816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public ParcelUuid uuid; 17916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public RemoteService(String address, ParcelUuid uuid) { 18016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.address = address; 18116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.uuid = uuid; 18216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 18316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly @Override 18416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public boolean equals(Object o) { 18516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (o instanceof RemoteService) { 18616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = (RemoteService)o; 18716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return address.equals(service.address) && uuid.equals(service.uuid); 18816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 18916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 19016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1915f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root 1925f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root @Override 1935f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root public int hashCode() { 1945f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root int hash = 1; 1955f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (address == null ? 0 : address.hashCode()); 1965f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode()); 1975f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root return hash; 1985f61416305c47c4db0b94c0cf500e9a9d11d4cdbKenny Root } 19916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 20016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 205bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothService(Context context) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 207105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 208105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Need to do this in place of: 209105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // mBatteryStats = BatteryStatsService.getService(); 210105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Since we can not import BatteryStatsService from here. This class really needs to be 211105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // moved to java/services/com/android/server/ 212105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 215ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 216ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isEnabledNative() == 1) { 217ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.w(TAG, "Bluetooth daemons already running - runtime restart? "); 218ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project disableNative(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 220ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 2219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState = new BluetoothBondState(context, this); 2229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mAdapterProperties = new BluetoothAdapterProperties(context, this); 2239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties = new BluetoothDeviceProperties(this); 22410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 22510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>(); 226cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>(); 2271caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker = new ArrayList<String>(); 22816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>(); 229c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons mServiceRecordToPid = new HashMap<Integer, ServiceRecordClient>(); 230f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>(); 231f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); 232f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP); 233f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh 234f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.start(); 235f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.start(); 2363fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh IntentFilter filter = new IntentFilter(); 2386e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh registerForAirplaneMode(filter); 2396e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 2403fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh filter.addAction(Intent.ACTION_DOCK_EVENT); 2416e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.registerReceiver(mReceiver, filter); 24230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this); 243a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this); 2442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this); 245a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections = new HashMap<String, Pair<Integer, String>>(); 246cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh mProfileConnectionState = new HashMap<Integer, Pair<Integer, Integer>>(); 2473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2483fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2499b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public static synchronized String readDockBluetoothAddress() { 2503fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (mDockAddress != null) return mDockAddress; 2513fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedInputStream file = null; 2533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh String dockAddress; 2543fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2553fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH)); 2563fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh byte[] address = new byte[17]; 2573fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.read(address); 2583fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = new String(address); 2593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh dockAddress = dockAddress.toUpperCase(); 2603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) { 2613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = dockAddress; 2623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockAddress; 2633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } else { 2649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "CheckBluetoothAddress failed for car dock address: " 2659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + dockAddress); 2663fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2673fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to read dock address"); 2693fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while trying to read dock address"); 2713fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 2723fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (file != null) { 2733fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2743fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh file.close(); 2753fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2763fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 2773fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2783fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2793fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2803fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockAddress = null; 2813fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return null; 2823fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 2833fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2843fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh private synchronized boolean writeDockPin() { 2853fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh BufferedWriter out = null; 2863fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 2873fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH)); 2883fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2893fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Generate a random 4 digit pin between 0000 and 9999 2903fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // This is not truly random but good enough for our purposes. 2913fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh int pin = (int) Math.floor(Math.random() * 10000); 2923fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 2933fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = String.format("%04d", pin); 2943fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.write(mDockPin); 2953fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return true; 2963fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (FileNotFoundException e) { 2979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "FileNotFoundException while trying to write dock pairing pin"); 2983fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 2999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "IOException while while trying to write dock pairing pin"); 3003fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } finally { 3013fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (out != null) { 3023fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh try { 3033fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh out.close(); 3043fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } catch (IOException e) { 3053fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Ignore 3063fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3073fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3083fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3093fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mDockPin = null; 3103fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 3113fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 3123fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 3133fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh /*package*/ synchronized String getDockPin() { 3143fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return mDockPin; 315bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly } 316bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 317bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public synchronized void initAfterRegistration() { 318f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 3197f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter); 3207f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.start(); 3219de1feb673499519cb380a142ba1e453109480bdMatthew Xie if (mContext.getResources().getBoolean 3229de1feb673499519cb380a142ba1e453109480bdMatthew Xie (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 3239de1feb673499519cb380a142ba1e453109480bdMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.TURN_HOT); 3249de1feb673499519cb380a142ba1e453109480bdMatthew Xie } 3257f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mEventLoop = mBluetoothState.getBluetoothEventLoop(); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3287d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh public synchronized void initAfterA2dpRegistration() { 3297d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh mEventLoop.getProfileProxy(); 3307d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh } 3317d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 3346e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.unregisterReceiver(mReceiver); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled() { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 3448c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh return isEnabledInternal(); 3458c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh } 3468c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 3478c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh private boolean isEnabledInternal() { 3487f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 351105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public int getBluetoothState() { 352105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 3537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return getBluetoothStateInternal(); 354105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 355105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int getBluetoothStateInternal() { 3577f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return mBluetoothState.getBluetoothAdapterState(); 3589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 359105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth and disable BT in settings. Returns true on success. 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean disable() { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return disable(true); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth. Returns true on success. 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 370e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly * @param saveSetting If true, persist the new setting 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean disable(boolean saveSetting) { 373e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3757f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie int adapterState = getBluetoothStateInternal(); 3767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 3777f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switch (adapterState) { 378de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 379105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 380de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 381105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 382105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project default: 383105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 384105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 3857a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 3867f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting); 387105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 388105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 389105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3907f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void disconnectDevices() { 3917a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh // Disconnect devices handled by BluetoothService. 3927a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedInputDevices()) { 3937a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectInputDevice(device); 3947a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3957a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh 3967a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh for (BluetoothDevice device: getConnectedPanDevices()) { 3977a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh disconnectPanDevice(device); 3987a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 3997a0f816916abb200d9337a5afde5d6d2a637a20aJaikumar Ganesh } 400105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 4017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 402dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie * The Bluetooth has been turned off, but hot. Do bonding, profile cleanup 4037f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 4047f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void finishDisable() { 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mark in progress bondings as cancelled 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { 407005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4112d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh // Stop the profile state machine for bonded devices. 4122d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDED)) { 4132d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh removeProfileState(address); 4142d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh } 4152d1fc4e3f5eb612f9ef8a50080310ced1dfaaadfJaikumar Ganesh 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update mode 417de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 418de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 420dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 422dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie /** 423dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie * Local clean up after broadcasting STATE_OFF intent 424dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie */ 425dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie synchronized void cleanupAfterFinishDisable() { 426bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 427dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie 428dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie for (Integer srHandle : mServiceRecordToPid.keySet()) { 429dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie removeServiceRecordNative(srHandle); 430dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie } 43124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.clear(); 432105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 433a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected = 0; 434a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting = 0; 435a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting = 0; 436c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 43750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = null; 43850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = null; 439a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 440105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth off to battery stats. 441105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 442105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 443105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOff(); 444105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 447105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4507f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 4517f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * power off Bluetooth 4527f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 4537f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie synchronized void shutoffBluetooth() { 45414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles); 45514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE, 45614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie BluetoothPanProfileHandler.NAP_BRIDGE); 4577f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie tearDownNativeDataNative(); 45814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 45914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 46014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie /** 46114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * Data clean up after Bluetooth shutoff 46214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie */ 46314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie synchronized void cleanNativeAfterShutoffBluetooth() { 46414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // Ths method is called after shutdown of event loop in the Bluetooth shut down 46514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // procedure 46614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 46714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie // the adapter property could be changed before event loop is stoped, clear it again 46814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mAdapterProperties.clear(); 4697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie disableNative(); 4707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 472105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** Bring up BT and persist BT on in settings */ 473105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean enable() { 474105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return enable(true); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enable this Bluetooth device, asynchronously. 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This turns on/off the underlying hardware. 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 481105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @param saveSetting If true, persist the new state of BT in settings 482105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return True on success (so far) 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 484105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public synchronized boolean enable(boolean saveSetting) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Airplane mode can prevent Bluetooth radio from being turned on. 48944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting); 4937f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie return true; 4947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 4957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 4967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 4977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * Turn on Bluetooth Module, Load firmware, and do all the preparation 4987f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * needed to get the Bluetooth Module ready but keep it not discoverable 4997f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * and not connectable. 5007f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 5017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /* package */ synchronized boolean prepareBluetooth() { 5027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (!setupNativeDataNative()) { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5057f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie switchConnectable(false); 5067f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie updateSdpRecords(); 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 5141caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh case MESSAGE_UUID_INTENT: 5151caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = (String)msg.obj; 51616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (address != null) { 5171caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh sendUuidIntent(address); 51816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly makeServiceChannelCallbacks(address); 51916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 5201caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh break; 521a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: 522a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh address = (String)msg.obj; 5238adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh if (address == null) return; 5248adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh int attempt = mBondState.getAttempt(address); 5258adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh 5268adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // Try only if attemps are in progress and cap it 2 attempts 5278adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // The 2 attempts cap is a fail safe if the stack returns 5288adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // an incorrect error code for bonding failures and if the pin 5298adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh // is entered wrongly twice we should abort. 5308adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh if (attempt > 0 && attempt <= 2) { 5318adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh mBondState.attempt(address); 532a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh createBond(address); 533a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 534a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 5358adcacbf83697d1299812f5365380b097898567aJaikumar Ganesh if (attempt > 0) mBondState.clearPinAttempts(address); 536a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh break; 537484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie case MESSAGE_REMOVE_SERVICE_RECORD: 538484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie Pair<Integer, Integer> pair = (Pair<Integer, Integer>) msg.obj; 539484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie checkAndRemoveRecord(pair.first, pair.second); 540484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie break; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 54550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) { 54650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh //Register SDP records. 54750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh int[] svcIdentifiers = new int[uuids.size()]; 54850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 54950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i)); 55050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 55150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers); 55250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 553105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 55450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh private synchronized void updateSdpRecords() { 55550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); 55650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 55750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add the default records 55850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.HSP_AG); 55950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.ObexObjectPush); 56050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 56150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (mContext.getResources(). 56250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh getBoolean(com.android.internal.R.bool.config_voice_capable)) { 56350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.Handsfree_AG); 56450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.PBAP_PSE); 56550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 56650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 56750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Android userspace 56850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh addReservedSdpRecords(uuids); 56950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 57050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Enable profiles maintained by Bluez userspace. 57174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE, 57274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothPanProfileHandler.NAP_BRIDGE); 57350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 57450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Add SDP records for profiles maintained by Bluez userspace 57550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AudioSource); 57650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.AvrcpTarget); 57750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh uuids.add(BluetoothUuid.NAP); 57850b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 57950b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh // Cannot cast uuids.toArray directly since ParcelUuid is parcelable 58050b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids = new ParcelUuid[uuids.size()]; 58150b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh for (int i = 0; i < uuids.size(); i++) { 58250b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mAdapterUuids[i] = uuids.get(i); 58350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 58450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 58550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh 5869efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh /** 5879efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * This function is called from Bluetooth Event Loop when onPropertyChanged 5889efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * for adapter comes in with UUID property. 5899efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh * @param uuidsThe uuids of adapter as reported by Bluez. 5909efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh */ 5917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ synchronized void updateBluetoothState(String uuids) { 5927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids); 5939efb1343a018c479ff57d70e8058658faa8a926dJaikumar Ganesh 5947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (mAdapterUuids != null && 5957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { 5967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6007f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /** 6018594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie * This method is called immediately before Bluetooth module is turned on after 6028594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie * the adapter became pariable. 6038594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie * It inits bond state and profile state before STATE_ON intent is broadcasted. 6048594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie */ 6058594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie /*package*/ void initBluetoothAfterTurningOn() { 606d96daf1ae5f314ea5f56b3e0b465e3f3b0314235Matthew Xie String discoverable = getProperty("Discoverable", false); 607d96daf1ae5f314ea5f56b3e0b465e3f3b0314235Matthew Xie String timeout = getProperty("DiscoverableTimeout", false); 608d96daf1ae5f314ea5f56b3e0b465e3f3b0314235Matthew Xie if (discoverable.equals("true") && Integer.valueOf(timeout) != 0) { 609d96daf1ae5f314ea5f56b3e0b465e3f3b0314235Matthew Xie setAdapterPropertyBooleanNative("Discoverable", 0); 610d96daf1ae5f314ea5f56b3e0b465e3f3b0314235Matthew Xie } 6118594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie mBondState.initBondState(); 6128594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie initProfileState(); 61398f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie getProfileProxy(); 6148594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie } 6158594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie 6168594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie /** 6177f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * This method is called immediately after Bluetooth module is turned on. 6187f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * It starts auto-connection and places bluetooth on sign onto the battery 6197f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * stats 6207f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie */ 6217f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ void runBluetooth() { 6227f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie autoConnect(); 6237f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 6247f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie // Log bluetooth on to battery stats. 6257f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie long ident = Binder.clearCallingIdentity(); 6267f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie try { 6277f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBatteryStats.noteBluetoothOn(); 6287f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } catch (RemoteException e) { 6297f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Log.e(TAG, "", e); 6307f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } finally { 6317f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie Binder.restoreCallingIdentity(ident); 6327f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 635a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean attemptAutoPair(String address) { 636a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!mBondState.hasAutoPairingFailed(address) && 637a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh !mBondState.isAutoPairingBlacklisted(address)) { 638a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.attempt(address); 639a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setPin(address, BluetoothDevice.convertPinToBytes("0000")); 640a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 641a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 642a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return false; 643a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 644a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 645f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) { 646f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh // Check for keyboards which have fixed PIN 0000 as the pairing pin 647f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh return mBondState.isFixedPinZerosAutoPairKeyboard(address); 648f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh } 649f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh 650a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) { 651a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (result == BluetoothDevice.BOND_SUCCESS) { 652a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_BONDED); 653a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 654a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 655a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 656a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED && 657a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.getAttempt(address) == 1) { 658a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.addAutoPairingFailure(address); 659a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 660a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN && 661a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.isAutoPairingAttemptsInProgress(address)) { 662a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh pairingAttempt(address, result); 663a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } else { 664a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 665a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBondState.isAutoPairingAttemptsInProgress(address)) { 666a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 667a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 668a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 669a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 670a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 671a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String getPendingOutgoingBonding() { 672a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.getPendingOutgoingBonding(); 673a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 674a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 675a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh private void pairingAttempt(String address, int result) { 676a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // This happens when our initial guess of "0000" as the pass key 677a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // fails. Try to create the bond again and display the pin dialog 678a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // to the user. Use back-off while posting the delayed 679a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // message. The initial value is 680a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is 681a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is 682a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh // reached, display an error to the user. 683a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh int attempt = mBondState.getAttempt(address); 684a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY > 685a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) { 686a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 687a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, BluetoothDevice.BOND_NONE, result); 688a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 689a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 690a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 691a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 692a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh message.obj = address; 693a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh boolean postResult = mHandler.sendMessageDelayed(message, 694a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY); 695a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (!postResult) { 696a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBondState.clearPinAttempts(address); 697a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh setBondState(address, 698a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh BluetoothDevice.BOND_NONE, result); 699a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return; 700a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ BluetoothDevice getRemoteDevice(String address) { 7049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapter.getRemoteDevice(address); 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toBondStateString(int bondState) { 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (bondState) { 709005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly case BluetoothDevice.BOND_NONE: 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "not bonded"; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDING: 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonding"; 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDED: 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonded"; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "??????"; 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setName(String name) { 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 726d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyString("Name", name); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean 730d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Either have a single property function with Object as the parameter 731d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or have a function for each property and then obfuscate in the JNI layer. 732d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The following looks dirty. 733d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyString(String key, String value) { 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7358c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 736d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyStringNative(key, value); 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyInteger(String key, int value) { 740d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7418c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 742d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyIntegerNative(key, value); 743d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 745d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyBoolean(String key, boolean value) { 746d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 7478c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 748d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyBooleanNative(key, value ? 1 : 0); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 751d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /** 752d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Set the discoverability window for the device. A timeout of zero 753d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * makes the device permanently discoverable (if the device is 754d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * discoverable). Setting the timeout to a nonzero value does not make 755d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * a device discoverable; you need to call setMode() to make the device 756d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * explicitly discoverable. 757d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 758f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * @param timeout The discoverable timeout in seconds. 759d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh */ 760d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean setDiscoverableTimeout(int timeout) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 763d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyInteger("DiscoverableTimeout", timeout); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 76612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly public synchronized boolean setScanMode(int mode, int duration) { 76718b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 76818b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly "Need WRITE_SECURE_SETTINGS permission"); 7699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean pairable; 7709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean discoverable; 77112835478ee687a493d1b5882e67b6725bd539c26Nick Pelly 772de893f550301a60274e87aa8168225e7a7a42184Nick Pelly switch (mode) { 773de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 774d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = false; 775d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 776de893f550301a60274e87aa8168225e7a7a42184Nick Pelly break; 777de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 778d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 779d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 780005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 781de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 782d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 783d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = true; 78412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds"); 785005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 786de893f550301a60274e87aa8168225e7a7a42184Nick Pelly default: 787de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Log.w(TAG, "Requested invalid scan mode " + mode); 788de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return false; 789d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie setPropertyBoolean("Discoverable", discoverable); 79214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie setPropertyBoolean("Pairable", pairable); 793d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return true; 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie /** 79714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * @param on true set the local Bluetooth module to be connectable 79814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * The dicoverability is recovered to what it was before 79914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * switchConnectable(false) call 80014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * false set the local Bluetooth module to be not connectable 80114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie * and not dicoverable 80214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie */ 80314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie /*package*/ synchronized void switchConnectable(boolean on) { 80414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie setAdapterPropertyBooleanNative("Powered", on ? 1 : 0); 80514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 80614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 80714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie /*package*/ synchronized void setPairable() { 80814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie String pairableString = getProperty("Pairable", false); 80914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (pairableString == null) { 81014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie Log.e(TAG, "null pairableString"); 81114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie return; 81214e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 81314e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (pairableString.equals("false")) { 81414e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie setAdapterPropertyBooleanNative("Pairable", 1); 81514e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 81614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 81714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 81844b58ab89e59b3d8241901232c8f7dc9617b206eMatthew Xie /*package*/ String getProperty(String name, boolean checkState) { 819a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh // If checkState is false, check if the event loop is running. 820a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh // before making the call to Bluez 821a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh if (checkState) { 822a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh if (!isEnabledInternal()) return null; 823a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh } else if (!mEventLoop.isEventLoopRunning()) { 824a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh return null; 825a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh } 826a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh 8279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties.getProperty(name); 828b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh } 829b148bc844e5eddb07bef2fd1b4b754716decb43eJaikumar Ganesh 8309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothAdapterProperties getAdapterProperties() { 8319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mAdapterProperties; 8329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProperties getDeviceProperties() { 8359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties; 8369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby boolean isRemoteDeviceInCache(String address) { 8399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.isInCache(address); 8409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void setRemoteDeviceProperty(String address, String name, String value) { 8439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.setProperty(address, name, value); 8449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 8459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 8469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void updateRemoteDevicePropertiesCache(String address) { 8479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceProperties.updateCache(address); 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 850d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getAddress() { 851d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 852a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh // Don't check state since we want to provide address, even if BT is off 853a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh return getProperty("Address", false); 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 856d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getName() { 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 858a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh // Don't check state since we want to provide name, even if BT is off 859a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh return getProperty("Name", false); 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86244b58ab89e59b3d8241901232c8f7dc9617b206eMatthew Xie public ParcelUuid[] getUuids() { 86358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 864a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh String value = getProperty("UUIDs", true); 86558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh if (value == null) return null; 86650b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh return convertStringToParcelUuid(value); 86750b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 86858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 86944b58ab89e59b3d8241901232c8f7dc9617b206eMatthew Xie private ParcelUuid[] convertStringToParcelUuid(String value) { 87058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh String[] uuidStrings = null; 87158b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 87258b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuidStrings = value.split(","); 87358b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 87458b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 87558b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 87658b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 87758b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 87858b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh return uuids; 87958b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh } 88058b93c36409c7fb91a644605f004b6d247d9b540Jaikumar Ganesh 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 882d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Returns the user-friendly name of a remote device. This value is 883d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * returned from our local cache, which is updated when onPropertyChange 884d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * event is received. 885d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Do not expect to retrieve the updated remote name immediately after 886d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * changing the name on the remote device. 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 888d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Bluetooth address of remote device. 889d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 890d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return The user-friendly name of the specified remote device. 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 892d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getRemoteName(String address) { 893d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 894005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 895d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 896d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 8979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return mDeviceProperties.getProperty(address, "Name"); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 901269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * Returns alias of a remote device. This value is returned from our 902269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * local cache, which is updated when onPropertyChange event is received. 903269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * 904269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * @param address Bluetooth address of remote device. 905269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * 906269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * @return The alias of the specified remote device. 907269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie */ 908269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie public synchronized String getRemoteAlias(String address) { 909269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie 910269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 911269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie if (!BluetoothAdapter.checkBluetoothAddress(address)) { 912269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie return null; 913269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie } 914269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie return mDeviceProperties.getProperty(address, "Alias"); 915269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie } 916269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie 917269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie /** 918269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * Set the alias of a remote device. 919269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * 920269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * @param address Bluetooth address of remote device. 921269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * @param alias new alias to change to 922269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie * @return true on success, false on error 923269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie */ 924269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie public synchronized boolean setRemoteAlias(String address, String alias) { 925269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 926269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie if (!BluetoothAdapter.checkBluetoothAddress(address)) { 927269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie return false; 928269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie } 929269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie 930269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie return setDevicePropertyStringNative(getObjectPathFromAddress(address), 931269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie "Alias", alias); 932269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie } 933269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie 934269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie /** 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the discoverability window for the device. A timeout of zero 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * means that the device is permanently discoverable (if the device is 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the discoverable mode). 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The discoverability window of the device, in seconds. A negative 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value indicates an error. 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 94244b58ab89e59b3d8241901232c8f7dc9617b206eMatthew Xie public int getDiscoverableTimeout() { 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 944a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh String timeout = getProperty("DiscoverableTimeout", true); 945d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (timeout != null) 946d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(timeout); 947d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 948d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return -1; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 95144b58ab89e59b3d8241901232c8f7dc9617b206eMatthew Xie public int getScanMode() { 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9538c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) 954de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 955d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 956a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh boolean pairable = getProperty("Pairable", true).equals("true"); 957a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh boolean discoverable = getProperty("Discoverable", true).equals("true"); 958d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return bluezStringToScanMode (pairable, discoverable); 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 961d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean startDiscovery() { 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9648c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9658c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 966d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return startDiscoveryNative(); 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean cancelDiscovery() { 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9728c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9738c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 974d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return stopDiscoveryNative(); 975d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 976d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 97744b58ab89e59b3d8241901232c8f7dc9617b206eMatthew Xie public boolean isDiscovering() { 978d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 979d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 980a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh String discoveringProperty = getProperty("Discovering", false); 9818594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie if (discoveringProperty == null) { 9828594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie return false; 9838594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie } 9848594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie 9858594394aadeaaa3f834d33d7b198fb071e0f31feMatthew Xie return discoveringProperty.equals("true"); 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 988cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private boolean isBondingFeasible(String address) { 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 9918c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 9928c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 993005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9982092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (mBondState.getPendingOutgoingBonding() != null) { 9999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): another device is bonding"); 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a different device is currently bonding, fail 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for bond state only if we are not performing auto 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pairing exponential back-off attempts. 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mBondState.isAutoPairingAttemptsInProgress(address) && 1007005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) { 10089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Ignoring createBond(): this device is already bonding or bonded"); 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10123fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (address.equals(mDockAddress)) { 10133fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (!writeDockPin()) { 10149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error while writing Pin for the dock"); 10153fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return false; 10163fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 10173fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 1018cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 1019cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 10203fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1021cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBond(String address) { 1022cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 1023cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1024cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceNative(address, 60000 /*1 minute*/ )) { 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10282092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 10302092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1034cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean createBondOutOfBand(String address, byte[] hash, 1035cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 1036cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isBondingFeasible(address)) return false; 10373fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 1038cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!createPairedDeviceOutOfBandNative(address, 60000 /* 1 minute */)) { 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1042cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh setDeviceOutOfBandData(address, hash, randomizer); 10432092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 10452092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setDeviceOutOfBandData(String address, byte[] hash, 1050cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer) { 1051cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1052cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1053cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 1054cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1055cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair <byte[], byte[]> value = new Pair<byte[], byte[]>(hash, randomizer); 1056cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1057cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (DBG) { 10589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "Setting out of band data for: " + address + ":" + 10599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Arrays.toString(hash) + ":" + Arrays.toString(randomizer)); 1060cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1061cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1062cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mDeviceOobData.put(address, value); 1063cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 1064cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1065cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1066cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> getDeviceOutOfBandData(BluetoothDevice device) { 1067cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return mDeviceOobData.get(device.getAddress()); 1068cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1069cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1070cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1071cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized byte[] readOutOfBandData() { 1072cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1073cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH permission"); 1074cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return null; 1075cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1076cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return readAdapterOutOfBandDataNative(); 1077cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1078cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean cancelBondProcess(String address) { 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 10828c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 10838c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1084005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1092005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 1094d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh cancelDeviceCreationNative(address); 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean removeBond(String address) { 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 11018c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11028c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1103005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1106f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 11079b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 1108f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh state.sendMessage(BluetoothDeviceProfileState.UNPAIR); 11099b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 11109b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 11119b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 11129b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 11139b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 11149b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 11159b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public synchronized boolean removeBondInternal(String address) { 1116cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh // Unset the trusted device state and then unpair 1117cc2c06656ceafbcd91ec5b679aa6c9eae0d9982cJaikumar Ganesh setTrust(address, false); 1118d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return removeDeviceNative(getObjectPathFromAddress(address)); 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String[] listBonds() { 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.listInState(BluetoothDevice.BOND_BONDED); 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1126a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized String[] listInState(int state) { 1127a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return mBondState.listInState(state); 1128a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1129a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1132005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1133b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.getBondState(address.toUpperCase()); 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1138a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state) { 1139a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return setBondState(address, state, 0); 1140a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1141a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 1142a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /*package*/ synchronized boolean setBondState(String address, int state, int reason) { 1143ae5fbb0b4363a2a399e92e310777d7a955a25370Arek Lichwa mBondState.setBondState(address.toUpperCase(), state, reason); 1144a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh return true; 1145a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh } 1146a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh 11473fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh public synchronized boolean isBluetoothDock(String address) { 11486e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 11499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Context.MODE_PRIVATE); 11506e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 11516e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address); 11523fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 11533fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 11549488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ String[] getRemoteDeviceProperties(String address) { 11558c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return null; 11568c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 11579488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String objectPath = getObjectPathFromAddress(address); 11589488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return (String [])getDevicePropertiesNative(objectPath); 11599488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 11609488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1162efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Sets the remote device trust state. 1163efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1164efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate operation success or fail 1165efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1166efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean setTrust(String address, boolean value) { 1167005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1168e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1169e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly "Need BLUETOOTH_ADMIN permission"); 1170efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1171efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1172efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 11738c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 11748c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 11759a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return setDevicePropertyBooleanNative( 11769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getObjectPathFromAddress(address), "Trusted", value ? 1 : 0); 1177efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1178efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1179efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1180efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Gets the remote device trust state as boolean. 1181efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Note: this value may be 1182efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * retrieved from cache if we retrieved the data before * 1183efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 11849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @return boolean to indicate trusted or untrusted state 1185efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1186efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean getTrustState(String address) { 1187005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1188efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1189efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1190efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1191efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 11929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Trusted"); 1193efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (val == null) { 1194efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1195efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else { 11969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return val.equals("true"); 1197efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1198efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1199efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1200efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1201d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the remote major, minor classes encoded as a 32-bit 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * integer. 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: this value is retrieved from cache, because we get it during 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remote-device discovery. 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 32-bit integer encoding the remote major, minor, and service 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes. 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getRemoteClass(String address) { 1211005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1212ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1213ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly return BluetoothClass.ERROR; 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String val = mDeviceProperties.getProperty(address, "Class"); 1216d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val == null) 1217d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return BluetoothClass.ERROR; 1218d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else { 1219d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(val); 1220d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1222d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1225dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * Gets the UUIDs supported by the remote device 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1227dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @return array of 128bit ParcelUuids 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1229dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public synchronized ParcelUuid[] getRemoteUuids(String address) { 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1231005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12341caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return getUuidFromCache(address); 12351caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12361caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] getUuidFromCache(String address) { 12389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String value = mDeviceProperties.getProperty(address, "UUIDs"); 1239dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh if (value == null) return null; 1240dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1241dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh String[] uuidStrings = null; 1242d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 1243dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuidStrings = value.split(","); 1244dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 1245dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1246dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 1247dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 1248dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh } 1249d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return uuids; 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 125216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** 125316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Connect and fetch new UUID's using SDP. 125416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * The UUID's found are broadcast as intents. 125516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Optionally takes a uuid and callback to fetch the RFCOMM channel for the 125616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * a given uuid. 125716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success 125816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for 125916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * callback and broadcast intents. 126016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly */ 126116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid, 126216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback) { 12631caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 12648c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 12658c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 12661caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(address)) { 12671caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return false; 12681caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12691caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 127016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = new RemoteService(address, uuid); 127116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null && mUuidCallbackTracker.get(service) != null) { 127216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // An SDP query for this address & uuid is already in progress 127316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Do not add this callback for the uuid 127416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 127516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 127616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 12771caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (mUuidIntentTracker.contains(address)) { 12781caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // An SDP query for this address is already in progress 127916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Add this uuid onto the in-progress SDP query 128016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 128116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 128216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12831caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return true; 12841caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 12851caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 1286421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh // If the device is already created, we will 1287421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh // do the SDP on the callback of createDeviceNative. 1288421f0101087bbede1152ccc6d8212f6686a10e54Jaikumar Ganesh boolean ret= createDeviceNative(address); 12891caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12901caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.add(address); 129116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 129216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 129316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12941caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 12951caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 12961caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh message.obj = address; 12971caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 12981caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return ret; 12991caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 13001caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1302d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the rfcomm channel associated with the UUID. 130316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Pulls records from the cache only. 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1305d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Address of the remote device 1306dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @param uuid ParcelUuid of the service attribute 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1308d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return rfcomm channel associated with the service attribute 130910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh * -1 on error 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1311dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public int getRemoteServiceChannel(String address, ParcelUuid uuid) { 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 13138c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 13148c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1315005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1316b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 131810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Check if we are recovering from a crash. 131910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (mDeviceProperties.isEmpty()) { 13209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (mDeviceProperties.updateCache(address) == null) 132110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 132210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 132310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 132410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); 132510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (value != null && value.containsKey(uuid)) 132610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return value.get(uuid); 132710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setPin(String address, byte[] pin) { 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 13338c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13348c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pin == null || pin.length <= 0 || pin.length > 16 || 1336005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly !BluetoothAdapter.checkBluetoothAddress(address)) { 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setPin(" + address + ") called but no native data available, " + 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " or by bluez.\n"); 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bluez API wants pin as a string 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pinString; 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinString = new String(pin, "UTF8"); 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException uee) { 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "UTF8 not supported?!?"); 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return setPinNative(address, pinString, data.intValue()); 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1358b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPasskey(String address, int passkey) { 1359b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1360b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 13618c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13628c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1363005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) { 1364b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1365b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1366b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1367b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1368b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1369b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1370b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1371b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1372b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1373b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1374b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPasskeyNative(address, passkey, data.intValue()); 1375b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1376b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1377b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPairingConfirmation(String address, boolean confirm) { 1378b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1379b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 13808c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 13818c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1382b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1383b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1384b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1385b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1386b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1387b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1388b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1389b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1390b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPairingConfirmationNative(address, confirm, data.intValue()); 1391b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1392b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1393cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh public synchronized boolean setRemoteOutOfBandData(String address) { 1394cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1395cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1396cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!isEnabledInternal()) return false; 1397cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh address = address.toUpperCase(); 1398cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1399cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (data == null) { 1400cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Log.w(TAG, "setRemoteOobData(" + address + ") called but no native data available, " + 1401cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1402cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh " or by bluez.\n"); 1403cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return false; 1404cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1405cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1406cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Pair<byte[], byte[]> val = mDeviceOobData.get(address); 1407cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] hash, randomizer; 1408cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (val == null) { 1409cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh // TODO: check what should be passed in this case. 1410cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = new byte[16]; 1411cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = new byte[16]; 1412cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } else { 1413cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh hash = val.first; 1414cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh randomizer = val.second; 1415cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1416cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return setRemoteOutOfBandDataNative(address, hash, randomizer, data.intValue()); 1417cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 1418cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 1419b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean cancelPairingUserInput(String address) { 14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 14228c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return false; 14238c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 1424005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1427005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 1428397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 1432b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " + 1433b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " + 1434b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "by the remote or by bluez.\n"); 14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1437b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return cancelPairingUserInputNative(address, data.intValue()); 14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14408c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh /*package*/ void updateDeviceServiceChannelCache(String address) { 14419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "updateDeviceServiceChannelCache(" + address + ")"); 14429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 144310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We are storing the rfcomm channel numbers only for the uuids 144410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // we are interested in. 14459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid[] deviceUuids = getRemoteUuids(address); 144616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 14479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ArrayList<ParcelUuid> applicationUuids = new ArrayList<ParcelUuid>(); 144816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 144916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 145016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 145116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 145216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly applicationUuids.add(service.uuid); 145316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 145416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 145516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 145610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 14579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map <ParcelUuid, Integer> uuidToChannelMap = new HashMap<ParcelUuid, Integer>(); 145816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 145916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for default uuids 146016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : RFCOMM_UUIDS) { 146110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 14629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 14639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 14649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(system): " + uuid + " " + channel); 146510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 146610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 146716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for application requested uuids 146816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : applicationUuids) { 146916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 14709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = getDeviceServiceChannelForUuid(address, uuid); 14719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuidToChannelMap.put(uuid, channel); 14729a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "\tuuid(application): " + uuid + " " + channel); 147316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 147416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 147516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 147616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 147716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Make application callbacks 147816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 147916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 148016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 148116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 14829a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidToChannelMap.containsKey(service.uuid)) { 14839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int channel = uuidToChannelMap.get(service.uuid); 14849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 14859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Making callback for " + service.uuid + 14869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby " with result " + channel); 148716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 148816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 148916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 149016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(channel); 149116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 149216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 149316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 149416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 149516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 149616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 149716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 149816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 149916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Update cache 15009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mDeviceServiceChannelCache.put(address, uuidToChannelMap); 150116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 150210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 150310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 15049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int getDeviceServiceChannelForUuid(String address, 15059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby ParcelUuid uuid) { 15069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return getDeviceServiceChannelNative(getObjectPathFromAddress(address), 15079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby uuid.toString(), 0x0004); 15089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 15099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 151024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly /** 151124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * b is a handle to a Binder instance, so that this service can be notified 151224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * for Applications that terminate unexpectedly, to clean there service 151324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * records 151424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly */ 151524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid, 151624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int channel, IBinder b) { 15178c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 15188c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh if (!isEnabledInternal()) return -1; 15198c9dd7d8b99e1b064fc064a3c6737eaf179eae68Jaikumar Ganesh 152024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (serviceName == null || uuid == null || channel < 1 || 152124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) { 152224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 152324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 152424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) { 152524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Log.w(TAG, "Attempted to register a reserved UUID: " + uuid); 152624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 152724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 152824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle = addRfcommServiceRecordNative(serviceName, 152924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(), 153024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly (short)channel); 15319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "new handle " + Integer.toHexString(handle)); 153224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (handle == -1) { 153324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 153424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 153524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 1536c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons ServiceRecordClient client = new ServiceRecordClient(); 1537c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons client.pid = Binder.getCallingPid(); 1538c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons client.binder = b; 1539c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons client.death = new Reaper(handle, client.pid, RFCOMM_RECORD_REAPER); 1540c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons mServiceRecordToPid.put(new Integer(handle), client); 154124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly try { 1542c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons b.linkToDeath(client.death, 0); 1543c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons } catch (RemoteException e) { 1544c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons Log.e(TAG, "", e); 1545c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons client.death = null; 1546c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons } 154724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return handle; 154824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 154924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 155024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void removeServiceRecord(int handle) { 155124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 155224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 1553dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie // Since this is a binder call check if Bluetooth is off 1554dcbc97fc28f4eb5910acc11dfac5efcd597c737dMatthew Xie if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return; 1555484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie Message message = mHandler.obtainMessage(MESSAGE_REMOVE_SERVICE_RECORD); 1556484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie message.obj = new Pair<Integer, Integer>(handle, Binder.getCallingPid()); 1557484867a8ed3d46fbb8df493c77f2e2d46a0db654Matthew Xie mHandler.sendMessage(message); 155824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 155924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 156024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private synchronized void checkAndRemoveRecord(int handle, int pid) { 1561c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons ServiceRecordClient client = mServiceRecordToPid.get(handle); 1562c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons if (client != null && pid == client.pid) { 15639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Removing service record " + 15649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer.toHexString(handle) + " for pid " + pid); 1565c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons 1566c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons if (client.death != null) { 1567c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons client.binder.unlinkToDeath(client.death, 0); 1568c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons } 1569c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons 1570f1754050ceaadb4603aaaa0b1f0b193a305834afMatthew Xie mServiceRecordToPid.remove(handle); 157124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly removeServiceRecordNative(handle); 157224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 157324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 157424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 157524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private class Reaper implements IBinder.DeathRecipient { 1576ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int mPid; 1577ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int mHandle; 1578ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int mType; 1579ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1580ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Reaper(int handle, int pid, int type) { 1581ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mPid = pid; 1582ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mHandle = handle; 1583ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mType = type; 158424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1585ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1586ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Reaper(int pid, int type) { 1587ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mPid = pid; 1588ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mType = type; 1589ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1590ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1591ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh @Override 159224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void binderDied() { 159324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly synchronized (BluetoothService.this) { 1594ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (DBG) Log.d(TAG, "Tracked app " + mPid + " died" + "Type:" + mType); 1595ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (mType == RFCOMM_RECORD_REAPER) { 1596ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh checkAndRemoveRecord(mHandle, mPid); 1597ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else if (mType == STATE_CHANGE_REAPER) { 1598ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.remove(mPid); 1599ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1600ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1601ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1602ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1603ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1604ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1605ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh @Override 1606ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh public boolean changeApplicationBluetoothState(boolean on, 1607ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh IBluetoothStateChangeCallback callback, IBinder binder) { 1608f5fb6c8ce36a98da47f32f4142d372bd5f650bfaJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1609f5fb6c8ce36a98da47f32f4142d372bd5f650bfaJaikumar Ganesh 1610ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int pid = Binder.getCallingPid(); 1611ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh //mStateChangeTracker is a synchronized map 1612ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (!mStateChangeTracker.containsKey(pid)) { 1613ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (on) { 1614ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.put(pid, callback); 1615ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else { 1616ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return false; 161724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1618ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else if (!on) { 1619ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.remove(pid); 162024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1621ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1622ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (binder != null) { 1623ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh try { 1624ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh binder.linkToDeath(new Reaper(pid, STATE_CHANGE_REAPER), 0); 1625ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } catch (RemoteException e) { 1626f1754050ceaadb4603aaaa0b1f0b193a305834afMatthew Xie Log.e(TAG, "", e); 1627ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return false; 1628ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1629ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1630ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1631ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int type; 1632ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh if (on) { 1633ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_ON; 1634ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } else { 1635ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_OFF; 1636ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1637ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1638ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mBluetoothState.sendMessage(type, callback); 1639ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return true; 1640ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1641ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1642ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh boolean isApplicationStateChangeTrackerEmpty() { 1643ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return mStateChangeTracker.isEmpty(); 1644ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1645ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1646ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh void clearApplicationStateChangeTracker() { 1647ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh mStateChangeTracker.clear(); 1648ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1649ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1650ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh Collection<IBluetoothStateChangeCallback> getApplicationStateChangeCallbacks() { 1651ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return mStateChangeTracker.values(); 1652ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh } 1653ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh 1654ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh int getNumberOfApplicationStateChangeTrackers() { 1655ef2cb7c93a99096799d415e721dda46d1bf7a005Jaikumar Ganesh return mStateChangeTracker.size(); 165624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 165724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 16616e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (intent == null) return; 16626e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh 16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Query the airplane mode from Settings.System just to make sure that 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some random app is not sending this intent and disabling bluetooth 16687f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (isAirplaneModeOn()) { 16697f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON); 16707f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } else { 16717f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF); 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16736e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else if (Intent.ACTION_DOCK_EVENT.equals(action)) { 16746e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 16756e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh Intent.EXTRA_DOCK_STATE_UNDOCKED); 16766e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state); 16776e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 16786e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockAddress = null; 16796e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mDockPin = null; 16806e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } else { 16816e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh SharedPreferences.Editor editor = 16826e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 16836e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh mContext.MODE_PRIVATE).edit(); 16846e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true); 168566fce5068a8a3aeb28aaf713843891b286a75280Brad Fitzpatrick editor.apply(); 16866e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh } 16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16916e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh private void registerForAirplaneMode(IntentFilter filter) { 169244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final ContentResolver resolver = mContext.getContentResolver(); 169344303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String airplaneModeRadios = Settings.System.getString(resolver, 16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_RADIOS); 169544303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey final String toggleableRadios = Settings.System.getString(resolver, 169644303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 169744303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 169844303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneSensitive = airplaneModeRadios == null ? true : 169944303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 170044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey mIsAirplaneToggleable = toggleableRadios == null ? false : 170144303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 170244303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey 17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 17046e9c443460e40e9d663c117ba836585335e7c2c1Jaikumar Ganesh filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Returns true if airplane mode is currently on */ 1709f3171fb60c840a9bc0220fad651338346dddfff7Matthew Xie /*package*/ final boolean isAirplaneModeOn() { 17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Settings.System.getInt(mContext.getContentResolver(), 17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_ON, 0) == 1; 17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17141caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /* Broadcast the Uuid intent */ 17151caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /*package*/ synchronized void sendUuidIntent(String address) { 17166179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh ParcelUuid[] uuid = getUuidFromCache(address); 17176179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 17182d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 17196179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); 17206179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 17219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mUuidIntentTracker.remove(address); 172216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 172316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 172416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ synchronized void makeServiceChannelCallbacks(String address) { 172516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 172616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 172716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 172816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 17299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (DBG) Log.d(TAG, "Cleaning up failed UUID channel lookup: " 17309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + service.address + " " + service.uuid); 173116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 173216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 173316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 173416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(-1); 173516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 173616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 173716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 173816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 173916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 174016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 17411caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 17421caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 17457f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) { 1746105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1747105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1748105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 174924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive); 175044303922f14ac71b446a6e50e1180be4c8fed2c7Jeff Sharkey pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable); 175124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 175224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local address = " + getAddress()); 175324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local name = " + getName()); 175424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("isDiscovering() = " + isDiscovering()); 1755105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 175696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mAdapter.getProfileProxy(mContext, 175796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); 17584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 17594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE); 176074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter.getProfileProxy(mContext, 176174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mBluetoothProfileServiceListener, BluetoothProfile.PAN); 1762105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 17639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpKnownDevices(pw); 17649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpAclConnectedDevices(pw); 17659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetService(pw); 17664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh dumpInputDeviceProfile(pw); 176774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh dumpPanProfile(pw); 17689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpApplicationServiceRecords(pw); 1769cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh dumpProfileState(pw); 1770cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 1771cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 1772cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh private void dumpProfileState(PrintWriter pw) { 1773cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh pw.println("\n--Profile State dump--"); 1774cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh pw.println("\n Headset profile state:" + 1775cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh mAdapter.getProfileConnectionState(BluetoothProfile.HEADSET)); 1776cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh pw.println("\n A2dp profile state:" + 1777cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh mAdapter.getProfileConnectionState(BluetoothProfile.A2DP)); 1778cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh pw.println("\n HID profile state:" + 1779cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh mAdapter.getProfileConnectionState(BluetoothProfile.INPUT_DEVICE)); 1780cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh pw.println("\n PAN profile state:" + 1781cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh mAdapter.getProfileConnectionState(BluetoothProfile.PAN)); 17824ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 17834ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 17849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetService(PrintWriter pw) { 1785105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Headset Service--"); 178698f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie if (mHeadsetProxy != null) { 178798f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie List<BluetoothDevice> deviceList = mHeadsetProxy.getConnectedDevices(); 1788bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh if (deviceList.size() == 0) { 178974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No headsets connected"); 1790bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh } else { 1791bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 17929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\ngetConnectedDevices[0] = " + device); 17939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby dumpHeadsetConnectionState(pw, device); 1794bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh pw.println("getBatteryUsageHint() = " + 179598f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie mHeadsetProxy.getBatteryUsageHint(device)); 179696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 179796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 17985a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh deviceList.clear(); 179998f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie deviceList = mHeadsetProxy.getDevicesMatchingConnectionStates(new int[] { 180096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 180174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Headsets"); 1802bb0773fac888c6748cbf778ab5c99c7d0a2c1309Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 180396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println(device); 180498f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie if (mHeadsetProxy.isAudioConnected(device)) { 180596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh pw.println("SCO audio connected to device:" + device); 180696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 180796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 1808105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 18094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 18106c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 18114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh private void dumpInputDeviceProfile(PrintWriter pw) { 18124ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("\n--Bluetooth Service- Input Device Profile"); 18134ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (mInputDevice != null) { 18144ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices(); 18154ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (deviceList.size() == 0) { 181674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No input devices connected"); 18174ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else { 181874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 18194ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 18204ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 18214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("Priority of Connected device = " + mInputDevice.getPriority(device)); 18224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 18234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh switch (mInputDevice.getConnectionState(device)) { 18244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 18254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 18264ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 18274ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 18284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 18294ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 18304ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 18314ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 18324ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh break; 18334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 18344ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 18354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList.clear(); 18364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] { 18374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 18384ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println("--Connected and Disconnected input devices"); 18394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 18404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh pw.println(device); 18414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 184224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 184574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private void dumpPanProfile(PrintWriter pw) { 184674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("\n--Bluetooth Service- Pan Profile"); 184774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (mPan != null) { 184874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh List<BluetoothDevice> deviceList = mPan.getConnectedDevices(); 184974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (deviceList.size() == 0) { 185074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("No Pan devices connected"); 185174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else { 185274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("Number of connected devices:" + deviceList.size()); 185374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothDevice device = deviceList.get(0); 185474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectedDevices[0] = " + device); 185574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 185674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh switch (mPan.getConnectionState(device)) { 185774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTING: 185874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTING"); 185974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 186074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_CONNECTED: 186174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_CONNECTED"); 186274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 186374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh case BluetoothInputDevice.STATE_DISCONNECTING: 186474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("getConnectionState() = STATE_DISCONNECTING"); 186574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh break; 186674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 186774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 186874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList.clear(); 186974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh deviceList = mPan.getDevicesMatchingConnectionStates(new int[] { 187074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); 187174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println("--Connected and Disconnected Pan devices"); 187274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh for (BluetoothDevice device: deviceList) { 187374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh pw.println(device); 187474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 187574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 18769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18789a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpHeadsetConnectionState(PrintWriter pw, 18799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDevice device) { 188098f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie switch (mHeadsetProxy.getConnectionState(device)) { 18819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTING: 18829a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTING"); 18839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_CONNECTED: 18859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_CONNECTED"); 18869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_DISCONNECTING: 18889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_DISCONNECTING"); 18899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothHeadset.STATE_AUDIO_CONNECTED: 18919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("getConnectionState() = STATE_AUDIO_CONNECTED"); 18929a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 18939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 18959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 18969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpApplicationServiceRecords(PrintWriter pw) { 18979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Application Service Records--"); 18989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (Integer handle : mServiceRecordToPid.keySet()) { 1899c980a495a6d357219a9e0860129ae6bb6d541843Jason Simmons Integer pid = mServiceRecordToPid.get(handle).pid; 19009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); 19019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 190274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 190374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 19049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpAclConnectedDevices(PrintWriter pw) { 19059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] devicesObjectPath = getKnownDevices(); 19069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--ACL connected devices--"); 19079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (devicesObjectPath != null) { 19089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String device : devicesObjectPath) { 19099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println(getAddressFromObjectPath(device)); 19109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 19149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void dumpKnownDevices(PrintWriter pw) { 19159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\n--Known devices--"); 19169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String address : mDeviceProperties.keySet()) { 19179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby int bondState = mBondState.getBondState(address); 19189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.printf("%s %10s (%d) %s\n", address, 19199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby toBondStateString(bondState), 19209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBondState.getAttempt(address), 19219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby getRemoteName(address)); 19229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 19239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address); 19249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (uuidChannels == null) { 19259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tuuids = null"); 19269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 19279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (ParcelUuid uuid : uuidChannels.keySet()) { 19289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Integer channel = uuidChannels.get(uuid); 19299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (channel == null) { 19309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid); 19319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } else { 19329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\t" + uuid + " RFCOMM channel = " + channel); 19339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (RemoteService service : mUuidCallbackTracker.keySet()) { 19379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (service.address.equals(address)) { 19389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby pw.println("\tPENDING CALLBACK: " + service.uuid); 19399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 19439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 194498f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie private void getProfileProxy() { 194598f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie mAdapter.getProfileProxy(mContext, 194698f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); 194798f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie } 194898f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie 194996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 195096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh new BluetoothProfile.ServiceListener() { 195196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 19524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 195398f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie mHeadsetProxy = (BluetoothHeadset) proxy; 19544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 19554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = (BluetoothInputDevice) proxy; 195674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 195774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = (BluetoothPan) proxy; 19584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 19594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 196096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceDisconnected(int profile) { 19614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.HEADSET) { 196298f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie mHeadsetProxy = null; 19634ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } else if (profile == BluetoothProfile.INPUT_DEVICE) { 19644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mInputDevice = null; 196574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } else if (profile == BluetoothProfile.PAN) { 196674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mPan = null; 19674ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 196896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 196996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh }; 197096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 1971d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) { 1972d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable && discoverable) 1973bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1974d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else if (pairable && !discoverable) 1975bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1976d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1977bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static String scanModeToBluezString(int mode) { 19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mode) { 1982bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "off"; 1984bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connectable"; 1986bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "discoverable"; 19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1992d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getAddressFromObjectPath(String objectPath) { 19939a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String adapterObjectPath = mAdapterProperties.getObjectPath(); 1994d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterObjectPath == null || objectPath == null) { 1995f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 1996d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " or deviceObjectPath:" + objectPath + " is null"); 1997d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1998d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1999d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!objectPath.startsWith(adapterObjectPath)) { 2000f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath + 2001d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " is not a prefix of deviceObjectPath:" + objectPath + 2002d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh "bluetoothd crashed ?"); 2003d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 2004d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2005d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = objectPath.substring(adapterObjectPath.length()); 2006d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address != null) return address.replace('_', ':'); 2007d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2008d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: Address being returned is null"); 2009d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 2010d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2011d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2012d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getObjectPathFromAddress(String address) { 20139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String path = mAdapterProperties.getObjectPath(); 2014d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (path == null) { 2015d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Error: Object Path is null"); 2016d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 2017d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2018d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh path = path + address.replace(":", "_"); 2019d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return path; 2020d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 2021d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2022b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh /*package */ void setLinkTimeout(String address, int num_slots) { 2023b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh String path = getObjectPathFromAddress(address); 2024b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh boolean result = setLinkTimeoutNative(path, num_slots); 2025b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 20269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (!result) Log.d(TAG, "Set Link Timeout to " + num_slots + " slots failed"); 2027b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh } 2028b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh 202930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for PAN Profile ****/ 20306003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh // TODO: This needs to be converted to a state machine. 203130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20326003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean isTetheringOn() { 203330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20346003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20356003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.isTetheringOn(); 20366003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 203730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 203830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20396003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/boolean allowIncomingTethering() { 20406003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20416003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.allowIncomingTethering(); 20426003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 204330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 204430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20456003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public void setBluetoothTethering(boolean value) { 204630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20476003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20486003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.setBluetoothTethering(value); 20496003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 205030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 205130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20526003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getPanDeviceConnectionState(BluetoothDevice device) { 205330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20546003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20556003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device); 20566003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 205730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 205830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20596003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectPanDevice(BluetoothDevice device) { 206030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 206130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 20626003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20636003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.connectPanDevice(device); 20646003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 206530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 206630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20676003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getConnectedPanDevices() { 206830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20696003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20706003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getConnectedPanDevices(); 20716003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 207230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 207330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20746003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getPanDevicesMatchingConnectionStates( 207574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh int[] states) { 207674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 20776003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20786003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states); 20796003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 208074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 208174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 20826003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectPanDevice(BluetoothDevice device) { 208330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 208430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 20856003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20866003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothPanProfileHandler.disconnectPanDevice(device); 20876003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 208830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 208930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20906003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handlePanDeviceStateChange(BluetoothDevice device, 209130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh String iface, 209230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, 209330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int role) { 20946003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 20956003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role); 20966003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 209730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 209830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 20996003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handlePanDeviceStateChange(BluetoothDevice device, 210030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh int state, int role) { 21016003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothPanProfileHandler) { 21026003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role); 21036003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 210430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 210530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 210630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh /**** Handlers for Input Device Profile ****/ 21076003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh // This needs to be converted to state machine 210830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21096003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectInputDevice(BluetoothDevice device) { 211030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 211130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 211230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 21136003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21146003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDevice(device, state); 21156003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 211630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 211730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21186003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean connectInputDeviceInternal(BluetoothDevice device) { 21196003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21206003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.connectInputDeviceInternal(device); 21216003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 212230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 212330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21246003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectInputDevice(BluetoothDevice device) { 212530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 212630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 212730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress()); 21286003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21296003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDevice(device, state); 21306003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 213130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 213230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21336003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean disconnectInputDeviceInternal(BluetoothDevice device) { 21346003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21356003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device); 21366003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 213730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 213830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21396003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getInputDeviceConnectionState(BluetoothDevice device) { 214030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 21416003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21426003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device); 21436003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 214430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 214530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21466003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getConnectedInputDevices() { 214730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 21486003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21496003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getConnectedInputDevices(); 21506003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 215130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 215230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21536003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public List<BluetoothDevice> getInputDevicesMatchingConnectionStates( 21544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh int[] states) { 21554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 21566003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21576003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states); 21586003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 21594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 21604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 21614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh 21626003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public int getInputDevicePriority(BluetoothDevice device) { 216330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 21646003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21656003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.getInputDevicePriority(device); 21666003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 216730b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 216830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 21696003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh public boolean setInputDevicePriority(BluetoothDevice device, int priority) { 217030b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 217130b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 21726003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 21736003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority); 21746003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 217530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 217630b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 2177bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh /** 2178bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh * Handle incoming profile acceptance for profiles handled by Bluetooth Service, 2179bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh * currently PAN and HID. This also is the catch all for all rejections for profiles 2180bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh * that is not supported. 2181bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh * 2182bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh * @param device - Bluetooth Device 2183bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh * @param allow - true / false 2184bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh * @return 2185bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh */ 2186bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh public boolean allowIncomingProfileConnect(BluetoothDevice device, boolean allow) { 2187a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 2188a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie "Need BLUETOOTH_ADMIN permission"); 2189a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String address = device.getAddress(); 2190a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (!BluetoothAdapter.checkBluetoothAddress(address)) { 2191a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2192a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2193a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2194a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer data = getAuthorizationAgentRequestData(address); 2195a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (data == null) { 2196bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh Log.w(TAG, "allowIncomingProfileConnect(" + device + 2197a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie ") called but no native data available"); 2198a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2199a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2200bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh if (DBG) log("allowIncomingProfileConnect: " + device + " : " + allow + " : " + data); 2201a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return setAuthorizationNative(address, allow, data.intValue()); 2202a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2203a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 22046003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) { 22056003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 22066003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states); 22076003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 220830b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 220930b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 22106003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh /*package*/void handleInputDevicePropertyChange(String address, boolean connected) { 22116003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh synchronized (mBluetoothInputProfileHandler) { 22126003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected); 22136003fe9af08b134485ebac61ee312528325f6c3cJaikumar Ganesh } 221430b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh } 221530b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh 22162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /**** Handlers for Health Device Profile ****/ 22172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh // TODO: All these need to be converted to a state machine. 22182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2219fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config, 2220fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh IBluetoothHealthCallback callback) { 22212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 22232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 2224fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh return mBluetoothHealthProfileHandler.registerAppConfiguration(config, callback); 22252ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22262ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { 22292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 22312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 22322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.unregisterAppConfiguration(config); 22332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22352ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSource(BluetoothDevice device, 22382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 22392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22402ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 22412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 22422ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.connectChannelToSource(device, 22432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh config); 22442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSink(BluetoothDevice device, 22482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config, int channelType) { 22492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 22512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 22522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.connectChannel(device, config, 22532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelType); 22542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22562ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean disconnectChannel(BluetoothDevice device, 2258eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh BluetoothHealthAppConfiguration config, int id) { 22592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22602ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 22612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 2262eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh return mBluetoothHealthProfileHandler.disconnectChannel(device, config, id); 22632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22642ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, 22672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 22682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 22702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 22712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getMainChannelFd(device, config); 22722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /*package*/ void onHealthDevicePropertyChanged(String devicePath, 22762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelPath) { 22772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 22782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler.onHealthDevicePropertyChanged(devicePath, 22792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelPath); 22802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 22832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /*package*/ void onHealthDeviceChannelChanged(String devicePath, 22842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelPath, boolean exists) { 22852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized(mBluetoothHealthProfileHandler) { 22862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothHealthProfileHandler.onHealthDeviceChannelChanged(devicePath, 22872ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelPath, exists); 22882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 22902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2291b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /*package*/ void onHealthDeviceChannelConnectionError(int channelCode, 2292b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh int newState) { 2293b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh synchronized(mBluetoothHealthProfileHandler) { 2294b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh mBluetoothHealthProfileHandler.onHealthDeviceChannelConnectionError(channelCode, 2295b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh newState); 2296b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh } 2297b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh } 2298b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh 22992ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public int getHealthDeviceConnectionState(BluetoothDevice device) { 23002ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 23012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 23022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 23032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getHealthDeviceConnectionState(device); 23042ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 23052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 23062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 23072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getConnectedHealthDevices() { 23082ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 23092ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 23102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 23112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler.getConnectedHealthDevices(); 23122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 23132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 23142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 23152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates( 23162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh int[] states) { 23172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 23182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh "Need BLUETOOTH permission"); 23192ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh synchronized (mBluetoothHealthProfileHandler) { 23202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mBluetoothHealthProfileHandler. 23212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh getHealthDevicesMatchingConnectionStates(states); 23222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 23232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 23242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2325a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /*package*/boolean notifyIncomingHidConnection(String address) { 2326a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 2327a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (state == null) { 2328a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 2329a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2330a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Message msg = new Message(); 2331a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie msg.what = BluetoothDeviceProfileState.CONNECT_HID_INCOMING; 2332a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie state.sendMessage(msg); 2333a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return true; 2334a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2335a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 23369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectHeadset(String address) { 233796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 233896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2339f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 23409b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2341f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2342f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING; 2343f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2344f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 2345f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 23469b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 23489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23499b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 23509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectHeadset(String address) { 235196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 235296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2353f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 23549b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2355f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2356f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING; 2357f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2358f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mHfpProfileState.sendMessage(msg); 23599b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 23609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23619b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 23629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 23649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean connectSink(String address) { 236596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 236696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2367f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 23689b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2369f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2370f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; 2371f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2372f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 2373f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh return true; 23749b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 23769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 23789b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean disconnectSink(String address) { 237996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false; 238096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 2381f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 23829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 2383f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh Message msg = new Message(); 2384f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING; 2385f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh msg.obj = state; 2386f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mA2dpProfileState.sendMessage(msg); 23879b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 23889b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 23909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23919b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2392d3728cb32fbd0a85bc77f4bcbdfea386ede2c75fJaikumar Ganesh BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) { 23939bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh BluetoothDeviceProfileState state = 23949bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust); 2395f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.put(address, state); 23969b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh state.start(); 23979b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return state; 23989b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 23999b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 24009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby void removeProfileState(String address) { 24019bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 24029bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh if (state == null) return; 24039bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh 24049bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh state.quit(); 2405f1048cdb68d4e4671be2060ca31a3adfc613e88eJaikumar Ganesh mDeviceProfileState.remove(address); 24069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24079b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 240844b58ab89e59b3d8241901232c8f7dc9617b206eMatthew Xie String[] getKnownDevices() { 24099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 2410a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh String val = getProperty("Devices", true); 24119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (val != null) { 24129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby bonds = val.split(","); 24139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return bonds; 24159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 24179b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh private void initProfileState() { 24189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = null; 2419a66590ed78d0ec8e837dab80a4376a10d7023e9aJaikumar Ganesh String val = getProperty("Devices", false); 24209b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (val != null) { 24219b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh bonds = val.split(","); 24229b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24239b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (bonds == null) { 24249b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return; 24259b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh for (String path : bonds) { 24279b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh String address = getAddressFromObjectPath(path); 2428d3728cb32fbd0a85bc77f4bcbdfea386ede2c75fJaikumar Ganesh BluetoothDeviceProfileState state = addProfileState(address, false); 24299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 24329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void autoConnect() { 24339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String[] bonds = getKnownDevices(); 24349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (bonds == null) { 24359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return; 24369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby for (String path : bonds) { 24389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String address = getAddressFromObjectPath(path); 24399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 24409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (state != null) { 24419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Message msg = new Message(); 24429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES; 24439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state.sendMessage(msg); 24449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 24459b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24469b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 244898f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie public boolean notifyIncomingConnection(String address, boolean rejected) { 244998f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 24509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 24519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 245298f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie if (rejected) { 245398f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie if (mA2dpService.getPriority(getRemoteDevice(address)) >= 245498f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie BluetoothProfile.PRIORITY_ON) { 245598f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES; 245698f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; 245798f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie state.sendMessageDelayed(msg, 245898f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY); 245998f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie } 246098f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie } else { 246198f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING; 246298f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie state.sendMessage(msg); 246398f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie } 24649b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 24659b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24669b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 24679b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24689b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 246998f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie /*package*/ boolean notifyIncomingA2dpConnection(String address, boolean rejected) { 247098f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie BluetoothDeviceProfileState state = mDeviceProfileState.get(address); 24719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (state != null) { 24729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Message msg = new Message(); 247398f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie if (rejected) { 247498f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie if (mHeadsetProxy.getPriority(getRemoteDevice(address)) >= 247598f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie BluetoothProfile.PRIORITY_ON) { 247698f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES; 247798f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING; 247898f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie state.sendMessageDelayed(msg, 247998f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY); 248098f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie } 248198f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie } else { 248298f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING; 248398f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie state.sendMessage(msg); 248498f06da8ed2851a768358de1979838ad1bb6d187Matthew Xie } 24859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return true; 24869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24879b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 24889b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 24909b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) { 24919b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh mA2dpService = a2dpService; 24929b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 24939b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 2494a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /*package*/ Integer getAuthorizationAgentRequestData(String address) { 2495a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer data = mEventLoop.getAuthorizationAgentRequestData().remove(address); 2496a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return data; 2497a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2498a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 249970a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh public void sendProfileStateMessage(int profile, int cmd) { 250070a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh Message msg = new Message(); 250170a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh msg.what = cmd; 250270a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh if (profile == BluetoothProfileState.HFP) { 250370a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mHfpProfileState.sendMessage(msg); 250470a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } else if (profile == BluetoothProfileState.A2DP) { 250570a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh mA2dpProfileState.sendMessage(msg); 250670a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 250770a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh } 250870a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh 2509c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh public int getAdapterConnectionState() { 2510c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh return mAdapterConnectionState; 2511c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh } 2512c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2513cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh public int getProfileConnectionState(int profile) { 2514cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2515cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2516cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh Pair<Integer, Integer> state = mProfileConnectionState.get(profile); 2517cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh if (state == null) return BluetoothProfile.STATE_DISCONNECTED; 2518cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2519cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh return state.first; 2520cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 2521cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2522cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh private void updateProfileConnectionState(int profile, int newState, int oldState) { 2523cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // mProfileConnectionState is a hashmap - 2524cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // <Integer, Pair<Integer, Integer>> 2525cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // The key is the profile, the value is a pair. first element 2526cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // is the state and the second element is the number of devices 2527cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // in that state. 2528cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh int numDev = 1; 2529cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh int newHashState = newState; 2530cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh boolean update = true; 2531cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2532cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // The following conditions are considered in this function: 2533cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // 1. If there is no record of profile and state - update 2534cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // 2. If a new device's state is current hash state - increment 2535cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // number of devices in the state. 2536cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // 3. If a state change has happened to Connected or Connecting 2537cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // (if current state is not connected), update. 2538cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // 4. If numDevices is 1 and that device state is being updated, update 2539cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // 5. If numDevices is > 1 and one of the devices is changing state, 2540cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // decrement numDevices but maintain oldState if it is Connected or 2541cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // Connecting 2542cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile); 2543cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh if (stateNumDev != null) { 2544cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh int currHashState = stateNumDev.first; 2545cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh numDev = stateNumDev.second; 2546cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2547cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh if (newState == currHashState) { 2548cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh numDev ++; 2549cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } else if (newState == BluetoothProfile.STATE_CONNECTED || 2550cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh (newState == BluetoothProfile.STATE_CONNECTING && 2551cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh currHashState != BluetoothProfile.STATE_CONNECTED)) { 2552cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh numDev = 1; 2553cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } else if (numDev == 1 && oldState == currHashState) { 2554cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh update = true; 2555cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } else if (numDev > 1 && oldState == currHashState) { 2556cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh numDev --; 2557cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2558cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh if (currHashState == BluetoothProfile.STATE_CONNECTED || 2559cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh currHashState == BluetoothProfile.STATE_CONNECTING) { 2560cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh newHashState = currHashState; 2561cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 2562cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } else { 2563cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh update = false; 2564cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 2565cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 2566cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2567cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh if (update) { 2568cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState, 2569cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh numDev)); 2570cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 2571cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 2572cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2573cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh public synchronized void sendConnectionStateChange(BluetoothDevice 2574cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh device, int profile, int state, int prevState) { 25759a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Since this is a binder call check if Bluetooth is on still 25767f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return; 25779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2578cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh if (!validateProfileConnectionState(state) || 2579cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh !validateProfileConnectionState(prevState)) { 2580cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // Previously, an invalid state was broadcast anyway, 2581cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // with the invalid state converted to -1 in the intent. 2582cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // Better to log an error and not send an intent with 2583cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh // invalid contents or set mAdapterConnectionState to -1. 2584cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh Log.e(TAG, "Error in sendConnectionStateChange: " 2585cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh + "prevState " + prevState + " state " + state); 2586cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh return; 2587cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh } 2588c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 2589cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh updateProfileConnectionState(profile, state, prevState); 2590cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh 2591cb1d354c1e9b458a0426cd08520d938012e32b34Jaikumar Ganesh if (updateCountersAndCheckForConnectionStateChange(state, prevState)) { 2592c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh mAdapterConnectionState = state; 2593c53cab20b225ba69057441ecb06db6478ab8ff9bJaikumar Ganesh 25947f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie if (state == BluetoothProfile.STATE_DISCONNECTED) { 25957f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED); 25967f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie } 25977f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie 2598a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 2599a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 26009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 26019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(state)); 26029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, 26039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby convertToAdapterState(prevState)); 260460b4d2a2bd232a7116fd037501cac704f328c0a1Jaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2605a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 26069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": " 26079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby + prevState + " -> " + state); 2608a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2609a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2610a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 26119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean validateProfileConnectionState(int state) { 26129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (state == BluetoothProfile.STATE_DISCONNECTED || 26139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTING || 26149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_CONNECTED || 26159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby state == BluetoothProfile.STATE_DISCONNECTING); 26169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 26179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 26189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private int convertToAdapterState(int state) { 2619a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 26209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTED: 26219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTED; 26229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_DISCONNECTING: 26239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_DISCONNECTING; 26249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTED: 26259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return BluetoothAdapter.STATE_CONNECTED; 2626a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2627a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh return BluetoothAdapter.STATE_CONNECTING; 26289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 26299a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "Error in convertToAdapterState"); 26309a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return -1; 26319a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby } 26329a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 26339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) { 26349a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby switch (prevState) { 26359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby case BluetoothProfile.STATE_CONNECTING: 26369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnecting--; 26379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 26389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2639a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 26409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesConnected--; 26419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 26429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 2643a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 26449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mProfilesDisconnecting--; 26459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby break; 2646a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 2647a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2648a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh switch (state) { 2649a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTING: 2650a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnecting++; 26519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 1); 2652a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2653a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_CONNECTED: 2654a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesConnected++; 26559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 1); 2656a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2657a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTING: 2658a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh mProfilesDisconnecting++; 26599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesDisconnecting == 1); 2660a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 2661a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh case BluetoothProfile.STATE_DISCONNECTED: 26629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return (mProfilesConnected == 0 && mProfilesConnecting == 0); 2663a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh 26649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby default: 26659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby return true; 2666a46f2fb152355fe591f9dddeb41f01fef5ccad1dJaikumar Ganesh } 26679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2668d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2669a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void createIncomingConnectionStateFile() { 2670a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie File f = new File(INCOMING_CONNECTION_FILE); 2671a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (!f.exists()) { 2672a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2673a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie f.createNewFile(); 2674a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2675a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.e(TAG, "IOException: cannot create file"); 2676a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2677a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2678a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2679a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2680a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /** @hide */ 2681a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public Pair<Integer, String> getIncomingState(String address) { 2682a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (mIncomingConnections.isEmpty()) { 2683a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie createIncomingConnectionStateFile(); 2684a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie readIncomingConnectionState(); 2685a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2686a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return mIncomingConnections.get(address); 2687a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2688a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2689a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void readIncomingConnectionState() { 2690a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie synchronized(mIncomingConnections) { 2691a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie FileInputStream fstream = null; 2692a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2693a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie fstream = new FileInputStream(INCOMING_CONNECTION_FILE); 2694a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie DataInputStream in = new DataInputStream(fstream); 2695a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BufferedReader file = new BufferedReader(new InputStreamReader(in)); 2696a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String line; 2697a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie while((line = file.readLine()) != null) { 2698a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie line = line.trim(); 2699a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (line.length() == 0) continue; 2700a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie String[] value = line.split(","); 2701a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (value != null && value.length == 3) { 2702a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Integer val1 = Integer.parseInt(value[1]); 2703a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Pair<Integer, String> val = new Pair(val1, value[2]); 2704a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections.put(value[0], val); 2705a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2706a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2707a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2708a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: readIncomingConnectionState" + e.toString()); 2709a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2710a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: readIncomingConnectionState" + e.toString()); 2711a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2712a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (fstream != null) { 2713a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2714a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie fstream.close(); 2715a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2716a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // Ignore 2717a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2718a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2719a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2720a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2721a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2722a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2723a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void truncateIncomingConnectionFile() { 2724a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie RandomAccessFile r = null; 2725a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2726a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r = new RandomAccessFile(INCOMING_CONNECTION_FILE, "rw"); 2727a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r.setLength(0); 2728a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2729a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: truncateIncomingConnectionState" + e.toString()); 2730a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2731a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: truncateIncomingConnectionState" + e.toString()); 2732a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2733a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (r != null) { 2734a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2735a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie r.close(); 2736a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2737a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // ignore 2738a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2739a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2740a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2741a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2742a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2743a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /** @hide */ 2744a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public void writeIncomingConnectionState(String address, Pair<Integer, String> data) { 2745a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie synchronized(mIncomingConnections) { 2746a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mIncomingConnections.put(address, data); 2747a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2748a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie truncateIncomingConnectionFile(); 2749a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie BufferedWriter out = null; 2750a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie StringBuilder value = new StringBuilder(); 2751a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2752a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out = new BufferedWriter(new FileWriter(INCOMING_CONNECTION_FILE, true)); 2753a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie for (String devAddress: mIncomingConnections.keySet()) { 2754a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Pair<Integer, String> val = mIncomingConnections.get(devAddress); 2755a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(devAddress); 2756a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(","); 2757a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(val.first.toString()); 2758a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(","); 2759a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append(val.second); 2760a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie value.append("\n"); 2761a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2762a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out.write(value.toString()); 2763a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (FileNotFoundException e) { 2764a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("FileNotFoundException: writeIncomingConnectionState" + e.toString()); 2765a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2766a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie log("IOException: writeIncomingConnectionState" + e.toString()); 2767a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } finally { 2768a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (out != null) { 2769a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 2770a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie out.close(); 2771a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (IOException e) { 2772a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie // Ignore 2773a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2774a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2775a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2776a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2777a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2778a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2779a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private static void log(String msg) { 2780a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.d(TAG, msg); 2781a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 2782a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 2783d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native static void classInitNative(); 2784d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 2785d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setupNativeDataNative(); 2786d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean tearDownNativeDataNative(); 2787d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 27889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native String getAdapterPathNative(); 2789d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2790d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int isEnabledNative(); 27917f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ native int enableNative(); 27927f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie /*package*/ native int disableNative(); 2793d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 27949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /*package*/ native Object[] getAdapterPropertiesNative(); 2795d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getDevicePropertiesNative(String objectPath); 2796d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyStringNative(String key, String value); 2797d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyIntegerNative(String key, int value); 2798d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyBooleanNative(String key, int value); 2799d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2800d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean startDiscoveryNative(); 2801d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean stopDiscoveryNative(); 2802d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2803d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean createPairedDeviceNative(String address, int timeout_ms); 2804cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean createPairedDeviceOutOfBandNative(String address, int timeout_ms); 2805cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native byte[] readAdapterOutOfBandDataNative(); 2806cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 2807d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean cancelDeviceCreationNative(String address); 2808d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean removeDeviceNative(String objectPath); 2809d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int getDeviceServiceChannelNative(String objectPath, String uuid, 2810d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh int attributeId); 2811d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2812b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean cancelPairingUserInputNative(String address, int nativeData); 2813d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setPinNative(String address, String pin, int nativeData); 2814b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPasskeyNative(String address, int passkey, int nativeData); 2815b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPairingConfirmationNative(String address, boolean confirm, 2816b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh int nativeData); 2817cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private native boolean setRemoteOutOfBandDataNative(String address, byte[] hash, 2818cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh byte[] randomizer, int nativeData); 2819cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 282024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean setDevicePropertyBooleanNative(String objectPath, String key, 282124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int value); 2822269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie private native boolean setDevicePropertyStringNative(String objectPath, String key, 2823269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie String value); 28241caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private native boolean createDeviceNative(String address); 282516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ native boolean discoverServicesNative(String objectPath, String pattern); 282610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 282724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, 282824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly short channel); 282924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean removeServiceRecordNative(int handle); 2830b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh private native boolean setLinkTimeoutNative(String path, int num_slots); 2831a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 283230b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean connectInputDeviceNative(String path); 283330b8cbe059b9addff643242e8a1fc86ca72ba54eJaikumar Ganesh native boolean disconnectInputDeviceNative(String path); 28346fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2835a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge); 2836a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean connectPanDeviceNative(String path, String dstRole); 2837a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanDeviceNative(String path); 2838a8571f15c39da2b7c6e672fef26106f5ac60dea0Jaikumar Ganesh native boolean disconnectPanServerDeviceNative(String path, 2839a44a1e77ef435942b2ff60e9e60d3a64b43d775bJaikumar Ganesh String address, String iface); 284084690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh 284184690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native int[] addReservedServiceRecordsNative(int[] uuuids); 284284690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh private native boolean removeReservedServiceRecordsNative(int[] handles); 28432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 28442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh // Health API 28452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String registerHealthApplicationNative(int dataType, String role, String name, 28462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh String channelType); 28472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String registerHealthApplicationNative(int dataType, String role, String name); 28482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean unregisterHealthApplicationNative(String path); 2849b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh native boolean createChannelNative(String devicePath, String appPath, String channelType, 2850b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh int code); 2851b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh native boolean destroyChannelNative(String devicePath, String channelpath, int code); 28522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String getMainChannelNative(String path); 28532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native String getChannelApplicationNative(String channelPath); 28542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native ParcelFileDescriptor getChannelFdNative(String channelPath); 28552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh native boolean releaseChannelFdNative(String channelPath); 2856a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie native boolean setAuthorizationNative(String address, boolean value, int data); 28579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2858