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 Projectpackage android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothA2dp; 20bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter; 2132d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganeshimport android.bluetooth.BluetoothClass; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 23b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganeshimport android.bluetooth.BluetoothHealth; 24545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.bluetooth.BluetoothInputDevice; 256fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.bluetooth.BluetoothPan; 2696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganeshimport android.bluetooth.BluetoothProfile; 27d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganeshimport android.bluetooth.BluetoothUuid; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 32577dd1f3e274b84876471c22efac578db94811fcJaikumar Ganeshimport android.os.ParcelUuid; 335a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport android.os.PowerManager; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 375a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 38abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass BluetoothEventLoop { 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "BluetoothEventLoop"; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = false; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Thread mThread; 49b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project private boolean mStarted; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mInterrupted; 51bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 52105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final HashMap<String, Integer> mPasskeyAgentRequestData; 53a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private final HashMap<String, Integer> mAuthorizationAgentRequestData; 54bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private final BluetoothService mBluetoothService; 55bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private final BluetoothAdapter mAdapter; 567f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie private final BluetoothAdapterStateMachine mBluetoothState; 5796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothA2dp mA2dp; 58105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final Context mContext; 59abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni // The WakeLock is used for bringing up the LCD during a pairing request 60abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni // from remote device when Android is in Suspend state. 61abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni private PowerManager.WakeLock mWakeLock; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 63694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 1; 64694c0b833b4235b396ec1b798610d617d0ec7b5cMatthew Xie private static final int EVENT_AGENT_CANCEL = 2; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final int CREATE_DEVICE_ALREADY_EXISTS = 1; 6716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final int CREATE_DEVICE_SUCCESS = 0; 6816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final int CREATE_DEVICE_FAILED = -1; 6916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 7632d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh String address = null; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 7832d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh case EVENT_PAIRING_CONSENT_DELAYED_ACCEPT: 7932d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh address = (String)msg.obj; 8032d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh if (address != null) { 8132d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh mBluetoothService.setPairingConfirmation(address, true); 8232d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh } 8332d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh break; 84e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh case EVENT_AGENT_CANCEL: 85e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh // Set the Bond State to BOND_NONE. 86e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh // We always have only 1 device in BONDING state. 87a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh String[] devices = mBluetoothService.listInState(BluetoothDevice.BOND_BONDING); 88e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh if (devices.length == 0) { 89e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh break; 90e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh } else if (devices.length > 1) { 91e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh Log.e(TAG, " There is more than one device in the Bonding State"); 92e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh break; 93e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh } 94e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh address = devices[0]; 95a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBluetoothService.setBondState(address, 96e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh BluetoothDevice.BOND_NONE, 97e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED); 98e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh break; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { classInitNative(); } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static native void classInitNative(); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 106a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh /* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter, 1077f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothService bluetoothService, 1087f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie BluetoothAdapterStateMachine bluetoothState) { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBluetoothService = bluetoothService; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1117f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie mBluetoothState = bluetoothState; 1129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mPasskeyAgentRequestData = new HashMap<String, Integer>(); 113a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mAuthorizationAgentRequestData = new HashMap<String, Integer>(); 114bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapter = adapter; 115abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni //WakeLock instantiation in BluetoothEventLoop class 116abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 117abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP 118abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni | PowerManager.ON_AFTER_RELEASE, TAG); 119abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.setReferenceCounted(false); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 1217d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh } 12296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 1237d0548d0944e48421857de4aec2822ced325bea0Jaikumar Ganesh /*package*/ void getProfileProxy() { 12496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP); 1254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.INPUT_DEVICE); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private BluetoothProfile.ServiceListener mProfileServiceListener = 12996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh new BluetoothProfile.ServiceListener() { 13096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 1314ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.A2DP) { 1324ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mA2dp = (BluetoothA2dp) proxy; 1334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 13496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 13596a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh public void onServiceDisconnected(int profile) { 1364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh if (profile == BluetoothProfile.A2DP) { 1374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh mA2dp = null; 1384ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh } 13996a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh } 14096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh }; 14196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 14296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 151d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ HashMap<String, Integer> getPasskeyAgentRequestData() { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPasskeyAgentRequestData; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 155a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /* package */ HashMap<String, Integer> getAuthorizationAgentRequestData() { 156a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return mAuthorizationAgentRequestData; 157a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 158a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 15928d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt /* package */ void start() { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16128d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt if (!isEventLoopRunningNative()) { 16228d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt if (DBG) log("Starting Event Loop thread"); 16328d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt startEventLoopNative(); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16628d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt 16728d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt public void stop() { 16828d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt if (isEventLoopRunningNative()) { 16928d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt if (DBG) log("Stopping Event Loop thread"); 17028d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt stopEventLoopNative(); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17428d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt public boolean isEventLoopRunning() { 17528d139fa953c0b3bf2c66d92587e5287ec4dd5abRobert Greenwalt return isEventLoopRunningNative(); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh private void addDevice(String address, String[] properties) { 1799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothDeviceProperties deviceProperties = 1809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBluetoothService.getDeviceProperties(); 1819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby deviceProperties.addProperties(address, properties); 1829a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String rssi = deviceProperties.getProperty(address, "RSSI"); 1839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String classValue = deviceProperties.getProperty(address, "Class"); 1849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby String name = deviceProperties.getProperty(address, "Name"); 1859488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh short rssiValue; 1869488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh // For incoming connections, we don't get the RSSI value. Use a default of MIN_VALUE. 1879488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh // If we accept the pairing, we will automatically show it at the top of the list. 1889488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh if (rssi != null) { 1899488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh rssiValue = (short)Integer.valueOf(rssi).intValue(); 1909488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } else { 1919488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh rssiValue = Short.MIN_VALUE; 1929488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 1939488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh if (classValue != null) { 194005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_FOUND); 195005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 196005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_CLASS, 197005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly new BluetoothClass(Integer.valueOf(classValue))); 198005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_RSSI, rssiValue); 199005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_NAME, name); 200d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 202d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 2039488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh log ("ClassValue: " + classValue + " for remote device: " + address + " is null"); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 2089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DeviceFound signal from org.bluez.Adapter. 2099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 2109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param address the MAC address of the new device 2119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param properties an array of property keys and value strings 2129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 2139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @see BluetoothDeviceProperties#addProperties(String, String[]) 2149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 2159488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh private void onDeviceFound(String address, String[] properties) { 2169488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh if (properties == null) { 2179488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh Log.e(TAG, "ERROR: Remote device properties are null"); 2189488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return; 2199488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 2209488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh addDevice(address, properties); 2219488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 2249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DeviceDisappeared signal from 2259a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Adapter. 2269a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 2279a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param address the MAC address of the disappeared device 2289a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 2299488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh private void onDeviceDisappeared(String address) { 230005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_DISAPPEARED); 231005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 2369a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DisconnectRequested signal from 2379a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Device. 2389a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 2399a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param deviceObjectPath the object path for the disconnecting device 2409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 2415e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh private void onDeviceDisconnectRequested(String deviceObjectPath) { 2425e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); 2435e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh if (address == null) { 2445e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh Log.e(TAG, "onDeviceDisconnectRequested: Address of the remote device in null"); 2455e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh return; 2465e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh } 2475e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED); 2485e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 2495e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 2505e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh } 2515e59ca8ae4e29efb77acbd5513dcc109ea5dd2b4Jaikumar Ganesh 2529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 2539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code for the async response to a CreatePairedDevice 2549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * method call to org.bluez.Adapter. 2559a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 2569a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param address the MAC address of the device to pair 2579a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param result success or error result for the pairing operation 2589a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 259d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private void onCreatePairedDeviceResult(String address, int result) { 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 261a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBluetoothService.onCreatePairedDeviceResult(address, result); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 2659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DeviceCreated signal from org.bluez.Adapter. 2669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 2679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param deviceObjectPath the object path for the created device 2689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 269d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private void onDeviceCreated(String deviceObjectPath) { 2709488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); 27102c4b353f7b2427d8a335e41fc336aea7cede8a3Matthew Xie if (address == null) { 27202c4b353f7b2427d8a335e41fc336aea7cede8a3Matthew Xie Log.e(TAG, "onDeviceCreated: device address null!" + " deviceObjectPath: " + 27302c4b353f7b2427d8a335e41fc336aea7cede8a3Matthew Xie deviceObjectPath); 27402c4b353f7b2427d8a335e41fc336aea7cede8a3Matthew Xie return; 27502c4b353f7b2427d8a335e41fc336aea7cede8a3Matthew Xie } 2769488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh if (!mBluetoothService.isRemoteDeviceInCache(address)) { 2779488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh // Incoming connection, we haven't seen this device, add to cache. 2789488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String[] properties = mBluetoothService.getRemoteDeviceProperties(address); 2799488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh if (properties != null) { 2809488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh addDevice(address, properties); 2819488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 2829488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 2869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DeviceRemoved signal from org.bluez.Adapter. 2879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 2889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param deviceObjectPath the object path for the removed device 2899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 290d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private void onDeviceRemoved(String deviceObjectPath) { 291d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); 292081a9b69a79ad16093122002b27320b23ac656e1Jaikumar Ganesh if (address != null) { 293a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBluetoothService.setBondState(address.toUpperCase(), BluetoothDevice.BOND_NONE, 294a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh BluetoothDevice.UNBOND_REASON_REMOVED); 295081a9b69a79ad16093122002b27320b23ac656e1Jaikumar Ganesh mBluetoothService.setRemoteDeviceProperty(address, "UUIDs", null); 296081a9b69a79ad16093122002b27320b23ac656e1Jaikumar Ganesh } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 3009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a PropertyChanged signal from 3017f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * org.bluez.Adapter. This method is also called from 3027f9ecca8f2dc288f785b37d2478e89b80fc3cefcMatthew Xie * {@link BluetoothAdapterStateMachine} to set the "Pairable" 3039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * property when Bluetooth is enabled. 3049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 3059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param propValues a string array containing the key and one or more 3069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * values. 3079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 308d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ void onPropertyChanged(String[] propValues) { 3099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby BluetoothAdapterProperties adapterProperties = 3109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby mBluetoothService.getAdapterProperties(); 3119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby 3129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby if (adapterProperties.isEmpty()) { 3139519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh // We have got a property change before 3149519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh // we filled up our cache. 3159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby adapterProperties.getAllProperties(); 3169519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh } 317b1ef24473297410872654a6c4ad51c8341b2c40bJaikumar Ganesh log("Property Changed: " + propValues[0] + " : " + propValues[1]); 318d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String name = propValues[0]; 319d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (name.equals("Name")) { 3209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby adapterProperties.setProperty(name, propValues[1]); 3216a9d93cc1abd0f96c68d6b0a6860acd002e9df3dJaikumar Ganesh Intent intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 3226a9d93cc1abd0f96c68d6b0a6860acd002e9df3dJaikumar Ganesh intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, propValues[1]); 3236a3c47391066f2eb0f2edb12208a1af37f953b19Jaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 324d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 325d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else if (name.equals("Pairable") || name.equals("Discoverable")) { 32614e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie adapterProperties.setProperty(name, propValues[1]); 32714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 32814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie if (name.equals("Discoverable")) { 32914e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED); 33014e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie } 33114e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie 332d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String pairable = name.equals("Pairable") ? propValues[1] : 3339a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby adapterProperties.getProperty("Pairable"); 334d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String discoverable = name.equals("Discoverable") ? propValues[1] : 3359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby adapterProperties.getProperty("Discoverable"); 336d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 337d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // This shouldn't happen, unless Adapter Properties are null. 338d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable == null || discoverable == null) 339d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 340d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 341bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly int mode = BluetoothService.bluezStringToScanMode( 342d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable.equals("true"), 343d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable.equals("true")); 344d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (mode >= 0) { 345de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 346de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mode); 347d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 348d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 349d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 350d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else if (name.equals("Discovering")) { 351d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Intent intent; 3529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby adapterProperties.setProperty(name, propValues[1]); 353d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (propValues[1].equals("true")) { 354005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 355d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 35639657b808f087a41a4161de2f8962023bdb04741Jake Hamby // Stop the discovery. 35739657b808f087a41a4161de2f8962023bdb04741Jake Hamby mBluetoothService.cancelDiscovery(); 358005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 359d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 360d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 36184690c88f37f395094147d27ace8319a2803a522Jaikumar Ganesh } else if (name.equals("Devices") || name.equals("UUIDs")) { 3628bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String value = null; 3638bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len = Integer.valueOf(propValues[1]); 3648bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (len > 0) { 365efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 3668bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 2; i < propValues.length; i++) { 367efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(propValues[i]); 368efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 3698bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 370efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh value = str.toString(); 371d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 3729a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby adapterProperties.setProperty(name, value); 37350b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh if (name.equals("UUIDs")) { 37450b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh mBluetoothService.updateBluetoothState(value); 37550b40cec9c43eeeb9389ba2a99bcffd160246132Jaikumar Ganesh } 376d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else if (name.equals("Powered")) { 37714e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED, 37814e48e91f6def5448db9994cb13ddcdc676cba53Matthew Xie propValues[1].equals("true") ? new Boolean(true) : new Boolean(false)); 379ff7db40be166844000749de17382e424617e11b2Jaikumar Ganesh } else if (name.equals("DiscoverableTimeout")) { 3809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby adapterProperties.setProperty(name, propValues[1]); 381d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 382d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 383d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 3849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 3859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a PropertyChanged signal from 3869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Device. 3879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 3889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param deviceObjectPath the object path for the changed device 3899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param propValues a string array containing the key and one or more 3909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * values. 3919a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 392d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private void onDevicePropertyChanged(String deviceObjectPath, String[] propValues) { 393d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String name = propValues[0]; 394d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); 395d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address == null) { 396d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null"); 397d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 398d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 399b1ef24473297410872654a6c4ad51c8341b2c40bJaikumar Ganesh log("Device property changed: " + address + " property: " 400b1ef24473297410872654a6c4ad51c8341b2c40bJaikumar Ganesh + name + " value: " + propValues[1]); 401b1ef24473297410872654a6c4ad51c8341b2c40bJaikumar Ganesh 402bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly BluetoothDevice device = mAdapter.getRemoteDevice(address); 403d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (name.equals("Name")) { 4042dfe1011497b743d4d1fa7786610bc9271ae6d0eJaikumar Ganesh mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); 405005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED); 406005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 407005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_NAME, propValues[1]); 408ee4837b3a08aebd284a2122169e61b8b3f80005eJaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 409d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 410269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie } else if (name.equals("Alias")) { 411269e81a563cfe080d7f241d0d46411d3c946c111Matthew Xie mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); 4125bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown Intent intent = new Intent(BluetoothDevice.ACTION_ALIAS_CHANGED); 4135bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 4145bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4155bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown mContext.sendBroadcast(intent, BLUETOOTH_PERM); 416d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else if (name.equals("Class")) { 4172dfe1011497b743d4d1fa7786610bc9271ae6d0eJaikumar Ganesh mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); 418005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED); 419005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 420005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_CLASS, 421005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly new BluetoothClass(Integer.valueOf(propValues[1]))); 422ee4837b3a08aebd284a2122169e61b8b3f80005eJaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 423d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 424d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else if (name.equals("Connected")) { 4252dfe1011497b743d4d1fa7786610bc9271ae6d0eJaikumar Ganesh mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); 426d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Intent intent = null; 427d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (propValues[1].equals("true")) { 428005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED); 429b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh // Set the link timeout to 8000 slots (5 sec timeout) 430b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh // for bluetooth docks. 431b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh if (mBluetoothService.isBluetoothDock(address)) { 432b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh mBluetoothService.setLinkTimeout(address, 8000); 433b7e029d03c115ed65cdea9b2bba307e882c308e2Jaikumar Ganesh } 434d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 435005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED); 436d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 437005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 438ee4837b3a08aebd284a2122169e61b8b3f80005eJaikumar Ganesh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 439d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_PERM); 440d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else if (name.equals("UUIDs")) { 4418bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String uuid = null; 4428bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len = Integer.valueOf(propValues[1]); 4438bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (len > 0) { 444efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 4458bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 2; i < propValues.length; i++) { 446efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(propValues[i]); 447efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 4488bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 449efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh uuid = str.toString(); 450d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 4518bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh mBluetoothService.setRemoteDeviceProperty(address, name, uuid); 45210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 45310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // UUIDs have changed, query remote service channel and update cache. 45410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mBluetoothService.updateDeviceServiceChannelCache(address); 45510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 4561caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mBluetoothService.sendUuidIntent(address); 4579488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } else if (name.equals("Paired")) { 4589488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh if (propValues[1].equals("true")) { 4594226415bd9f376c41d85f4cd2e11da59a866d241Henrik Backlund // If locally initiated pairing, we will 4604226415bd9f376c41d85f4cd2e11da59a866d241Henrik Backlund // not go to BOND_BONDED state until we have received a 4614226415bd9f376c41d85f4cd2e11da59a866d241Henrik Backlund // successful return value in onCreatePairedDeviceResult 462a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (null == mBluetoothService.getPendingOutgoingBonding()) { 463a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDED); 4644226415bd9f376c41d85f4cd2e11da59a866d241Henrik Backlund } 4659488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } else { 466a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBluetoothService.setBondState(address, BluetoothDevice.BOND_NONE); 467efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mBluetoothService.setRemoteDeviceProperty(address, "Trusted", "false"); 4689488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 469efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else if (name.equals("Trusted")) { 470efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (DBG) 4719a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby log("set trust state succeeded, value is: " + propValues[1]); 472efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); 473d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 4779a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a PropertyChanged signal from 4789a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Input. 4799a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 4809a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param path the object path for the changed input device 4819a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param propValues a string array containing the key and one or more 4829a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * values. 4839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 484545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh private void onInputDevicePropertyChanged(String path, String[] propValues) { 485545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(path); 486545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (address == null) { 4879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.e(TAG, "onInputDevicePropertyChanged: Address of the remote device is null"); 488545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh return; 489545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 4909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby log("Input Device : Name of Property is: " + propValues[0]); 491545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh boolean state = false; 492545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh if (propValues[1].equals("true")) { 493545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh state = true; 494545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 495545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh mBluetoothService.handleInputDevicePropertyChange(address, state); 496545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh } 497545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 4989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 4999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a PropertyChanged signal from 5009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Network. 5019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 5029a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param deviceObjectPath the object path for the changed PAN device 5039a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param propValues a string array containing the key and one or more 5049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * values. 5059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 5066fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang private void onPanDevicePropertyChanged(String deviceObjectPath, String[] propValues) { 5076fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang String name = propValues[0]; 5086fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); 5096fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (address == null) { 5106fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang Log.e(TAG, "onPanDevicePropertyChanged: Address of the remote device in null"); 5116fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang return; 5126fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 5136fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (DBG) { 5146fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang log("Pan Device property changed: " + address + " property: " 5156fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang + name + " value: "+ propValues[1]); 5166fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 5176fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang BluetoothDevice device = mAdapter.getRemoteDevice(address); 5186fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (name.equals("Connected")) { 519707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh if (propValues[1].equals("false")) { 520707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh mBluetoothService.handlePanDeviceStateChange(device, 5215200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh BluetoothPan.STATE_DISCONNECTED, 5225200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh BluetoothPan.LOCAL_PANU_ROLE); 523707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh } 524707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh } else if (name.equals("Interface")) { 525707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh String iface = propValues[1]; 526057898a9b5d50e0d8eed52bdaa74a5f17bf85c1aJaikumar Ganesh if (!iface.equals("")) { 527057898a9b5d50e0d8eed52bdaa74a5f17bf85c1aJaikumar Ganesh mBluetoothService.handlePanDeviceStateChange(device, iface, 528057898a9b5d50e0d8eed52bdaa74a5f17bf85c1aJaikumar Ganesh BluetoothPan.STATE_CONNECTED, 529057898a9b5d50e0d8eed52bdaa74a5f17bf85c1aJaikumar Ganesh BluetoothPan.LOCAL_PANU_ROLE); 530057898a9b5d50e0d8eed52bdaa74a5f17bf85c1aJaikumar Ganesh } 5316fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 5326fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 5336fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 534b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private String checkPairingRequestAndGetAddress(String objectPath, int nativeData) { 535d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(objectPath); 536d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address == null) { 537b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.e(TAG, "Unable to get device address in checkPairingRequestAndGetAddress, " + 538b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "returning null"); 539b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return null; 540d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPasskeyAgentRequestData.put(address, new Integer(nativeData)); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 544de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothService.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF) { 545105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // shutdown path 546b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mBluetoothService.cancelPairingUserInput(address); 547b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return null; 548105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 54937686069ae1d7db2604c8aef96a79904f6ddd2f3Jaikumar Ganesh // Set state to BONDING. For incoming connections it will be set here. 55037686069ae1d7db2604c8aef96a79904f6ddd2f3Jaikumar Ganesh // For outgoing connections, it gets set when we call createBond. 55137686069ae1d7db2604c8aef96a79904f6ddd2f3Jaikumar Ganesh // Also set it only when the state is not already Bonded, we can sometimes 55237686069ae1d7db2604c8aef96a79904f6ddd2f3Jaikumar Ganesh // get an authorization request from the remote end if it doesn't have the link key 55337686069ae1d7db2604c8aef96a79904f6ddd2f3Jaikumar Ganesh // while we still have it. 554a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBluetoothService.getBondState(address) != BluetoothDevice.BOND_BONDED) 555a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDING); 556b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return address; 557b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 558b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 5599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 5609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a RequestPairingConsent method call to 5619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Agent. 5629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 5639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param objectPath the path of the device to request pairing consent for 5649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param nativeData a native pointer to the original D-Bus message 5659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 56632d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh private void onRequestPairingConsent(String objectPath, int nativeData) { 56732d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh String address = checkPairingRequestAndGetAddress(objectPath, nativeData); 56832d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh if (address == null) return; 56932d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh 57032d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh /* The link key will not be stored if the incoming request has MITM 57132d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh * protection switched on. Unfortunately, some devices have MITM 57232d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh * switched on even though their capabilities are NoInputNoOutput, 57332d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh * so we may get this request many times. Also if we respond immediately, 57432d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh * the other end is unable to handle it. Delay sending the message. 57532d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh */ 576a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBluetoothService.getBondState(address) == BluetoothDevice.BOND_BONDED) { 57732d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh Message message = mHandler.obtainMessage(EVENT_PAIRING_CONSENT_DELAYED_ACCEPT); 57832d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh message.obj = address; 57932d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh mHandler.sendMessageDelayed(message, 1500); 58032d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh return; 58132d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh } 582abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni // Acquire wakelock during PIN code request to bring up LCD display 583abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.acquire(); 58432d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 58532d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 58632d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, 58732d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh BluetoothDevice.PAIRING_VARIANT_CONSENT); 58832d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 5899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Release wakelock to allow the LCD to go off after the PIN popup notification. 590abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.release(); 59132d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh return; 59232d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh } 59332d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh 5949a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 5959a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a RequestConfirmation method call to 5969a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Agent. 5979a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 5989a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param objectPath the path of the device to confirm the passkey for 5999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param passkey an integer containing the 6-digit passkey to confirm 6009a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param nativeData a native pointer to the original D-Bus message 6019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 60232d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh private void onRequestPasskeyConfirmation(String objectPath, int passkey, int nativeData) { 603b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh String address = checkPairingRequestAndGetAddress(objectPath, nativeData); 604b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (address == null) return; 605abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni // Acquire wakelock during PIN code request to bring up LCD display 606abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.acquire(); 607005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 608005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 609c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey); 610005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, 61132d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION); 612b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 6139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Release wakelock to allow the LCD to go off after the PIN popup notification. 614abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.release(); 615b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return; 616b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 617b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 6189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 6199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a RequestPasskey method call to 6209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Agent. 6219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 6229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param objectPath the path of the device requesting a passkey 6239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param nativeData a native pointer to the original D-Bus message 6249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 625b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private void onRequestPasskey(String objectPath, int nativeData) { 626b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh String address = checkPairingRequestAndGetAddress(objectPath, nativeData); 627b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (address == null) return; 628abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni // Acquire wakelock during PIN code request to bring up LCD display 629abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.acquire(); 630005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 631005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 632005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, 633005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly BluetoothDevice.PAIRING_VARIANT_PASSKEY); 634b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 6359a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Release wakelock to allow the LCD to go off after the PIN popup notification. 636abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.release(); 637b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return; 638b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 639b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 6409a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 6419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a RequestPinCode method call to 6429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Agent. 6439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 6449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param objectPath the path of the device requesting a PIN code 6459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param nativeData a native pointer to the original D-Bus message 6469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 647b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private void onRequestPinCode(String objectPath, int nativeData) { 648b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh String address = checkPairingRequestAndGetAddress(objectPath, nativeData); 649b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (address == null) return; 650105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 6512092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh String pendingOutgoingAddress = 652a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh mBluetoothService.getPendingOutgoingBonding(); 653c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address)); 654c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh int btDeviceClass = btClass.getDeviceClass(); 655c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh 6562092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (address.equals(pendingOutgoingAddress)) { 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we initiated the bonding 6583fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 6593fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh // Check if its a dock 6603fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh if (mBluetoothService.isBluetoothDock(address)) { 6613fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh String pin = mBluetoothService.getDockPin(); 6623fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes(pin)); 6633fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh return; 6643fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh } 6653fbf7b62bb48b10316353087d09cc3720af00642Jaikumar Ganesh 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try 0000 once if the device looks dumb 667c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh switch (btDeviceClass) { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES: 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO: 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO: 673a224f70b1efc29d9698da5b5c143251a43838f2bJaikumar Ganesh if (mBluetoothService.attemptAutoPair(address)) return; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 676c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh 677ac6f13dc68dadb59fcad1df4af478bf0955e6e87Jaikumar Ganesh if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD || 678ac6f13dc68dadb59fcad1df4af478bf0955e6e87Jaikumar Ganesh btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) { 679ac6f13dc68dadb59fcad1df4af478bf0955e6e87Jaikumar Ganesh // Its a keyboard. Follow the HID spec recommendation of creating the 680f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh // passkey and displaying it to the user. If the keyboard doesn't follow 681f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh // the spec recommendation, check if the keyboard has a fixed PIN zero 682f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh // and pair. 683f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh if (mBluetoothService.isFixedPinZerosAutoPairKeyboard(address)) { 684f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000")); 685f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh return; 686f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh } 687f487d72215421a02e5a1b2fbff4618bc5ee185cbJaikumar Ganesh 688ac6f13dc68dadb59fcad1df4af478bf0955e6e87Jaikumar Ganesh // Generate a variable PIN. This is not truly random but good enough. 689ac6f13dc68dadb59fcad1df4af478bf0955e6e87Jaikumar Ganesh int pin = (int) Math.floor(Math.random() * 10000); 690ac6f13dc68dadb59fcad1df4af478bf0955e6e87Jaikumar Ganesh sendDisplayPinIntent(address, pin); 691ac6f13dc68dadb59fcad1df4af478bf0955e6e87Jaikumar Ganesh return; 692c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh } 693abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni // Acquire wakelock during PIN code request to bring up LCD display 694abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.acquire(); 695005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 696005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 697005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PIN); 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 6999a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby // Release wakelock to allow the LCD to go off after the PIN popup notification. 700abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.release(); 701d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7049a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 7059a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DisplayPasskey method call to 7069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Agent. 7079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 7089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param objectPath the path of the device to display the passkey for 7099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param passkey an integer containing the 6-digit passkey 7109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param nativeData a native pointer to the original D-Bus message 7119a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 71232d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh private void onDisplayPasskey(String objectPath, int passkey, int nativeData) { 71332d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh String address = checkPairingRequestAndGetAddress(objectPath, nativeData); 71432d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh if (address == null) return; 71532d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh 716abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni // Acquire wakelock during PIN code request to bring up LCD display 717abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.acquire(); 71832d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 71932d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 720c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey); 72132d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, 72232d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY); 72332d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 7249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby //Release wakelock to allow the LCD to go off after the PIN popup notification. 725abf9943704f4f71c619d27e0de5f68afdaab5e3bBheemsen Kulkarni mWakeLock.release(); 72632d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh } 72732d8571f509c392dca732c243e9b2138c15daecfJaikumar Ganesh 728c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh private void sendDisplayPinIntent(String address, int pin) { 729c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh // Acquire wakelock during PIN code request to bring up LCD display 730c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh mWakeLock.acquire(); 731c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 732c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 733c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin); 734c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, 735c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN); 736c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 737c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh //Release wakelock to allow the LCD to go off after the PIN popup notifcation. 738c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh mWakeLock.release(); 739c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh } 740c88b0c62c52ab76f1277f3c999d795d8ba527028Jaikumar Ganesh 7419a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 7429a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a RequestOobData method call to 7439a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.Agent. 7449a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 7459a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param objectPath the path of the device requesting OOB data 7469a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param nativeData a native pointer to the original D-Bus message 7479a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 7489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby private void onRequestOobData(String objectPath, int nativeData) { 749cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh String address = checkPairingRequestAndGetAddress(objectPath, nativeData); 750cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (address == null) return; 751cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 752cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 753cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 754cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, 755cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT); 756cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 757cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 758cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 7599a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 7609a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on an Authorize method call to org.bluez.Agent. 7619a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 7629a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param objectPath the path of the device requesting to be authorized 7639a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param deviceUuid the UUID of the requesting device 764a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie * @param nativeData reference for native data 7659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 766a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie private void onAgentAuthorize(String objectPath, String deviceUuid, int nativeData) { 767a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (!mBluetoothService.isEnabled()) return; 768545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh 769d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(objectPath); 770d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address == null) { 771d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Unable to get device address in onAuthAgentAuthorize"); 772a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return; 773d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean authorized = false; 776dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid uuid = ParcelUuid.fromString(deviceUuid); 777a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 778545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh BluetoothDevice device = mAdapter.getRemoteDevice(address); 779a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mAuthorizationAgentRequestData.put(address, new Integer(nativeData)); 780b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh 781b23d4458a91c8e77828fc38ffd81914c2e37d43aNick Pelly // Bluez sends the UUID of the local service being accessed, _not_ the 782b23d4458a91c8e77828fc38ffd81914c2e37d43aNick Pelly // remote service 78396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh if (mA2dp != null && 78496a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh (BluetoothUuid.isAudioSource(uuid) || BluetoothUuid.isAvrcpTarget(uuid) 785545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh || BluetoothUuid.isAdvAudioDist(uuid)) && 78696a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh !isOtherSinkInNonDisconnectedState(address)) { 78796a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh authorized = mA2dp.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 788a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (authorized && !BluetoothUuid.isAvrcpTarget(uuid)) { 789a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.i(TAG, "First check pass for incoming A2DP / AVRCP connection from " + address); 79070a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh // Some headsets try to connect AVCTP before AVDTP - against the recommendation 79170a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh // If AVCTP connection fails, we get stuck in IncomingA2DP state in the state 79270a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh // machine. We don't handle AVCTP signals currently. We only send 79370a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh // intents for AVDTP state changes. We need to handle both of them in 79470a053bf1ba331d727e2fbfca8f39d96b3b324b4Jaikumar Ganesh // some cases. For now, just don't move to incoming state in this case. 7950901e601b53b79e5ff37d9aed7acd4291a6ce9dcMatthew Xie mBluetoothService.notifyIncomingA2dpConnection(address, false); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 797a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.i(TAG, "" + authorized + 798a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie "Incoming A2DP / AVRCP connection from " + address); 799a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie mA2dp.allowIncomingConnect(device, authorized); 8000901e601b53b79e5ff37d9aed7acd4291a6ce9dcMatthew Xie mBluetoothService.notifyIncomingA2dpConnection(address, true); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 802bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh } else if (BluetoothUuid.isInputDevice(uuid)) { 8034ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh // We can have more than 1 input device connected. 804bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh authorized = mBluetoothService.getInputDevicePriority(device) > 805bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh BluetoothInputDevice.PRIORITY_OFF; 806bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh if (authorized) { 807bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh Log.i(TAG, "First check pass for incoming HID connection from " + address); 808bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh // notify profile state change 809bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh mBluetoothService.notifyIncomingHidConnection(address); 810bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh } else { 811bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh Log.i(TAG, "Rejecting incoming HID connection from " + address); 812bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh mBluetoothService.allowIncomingProfileConnect(device, authorized); 813bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh } 814bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh } else if (BluetoothUuid.isBnep(uuid)) { 815bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh // PAN doesn't go to the state machine, accept or reject from here 816bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh authorized = mBluetoothService.allowIncomingTethering(); 817bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh mBluetoothService.allowIncomingProfileConnect(device, authorized); 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 819d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address); 820bbd86750570ff75e428b3810dc2e65db558c14b2Jaikumar Ganesh mBluetoothService.allowIncomingProfileConnect(device, authorized); 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 822b23d4458a91c8e77828fc38ffd81914c2e37d43aNick Pelly log("onAgentAuthorize(" + objectPath + ", " + deviceUuid + ") = " + authorized); 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 825cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh private boolean onAgentOutOfBandDataAvailable(String objectPath) { 826cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (!mBluetoothService.isEnabled()) return false; 827cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 828cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(objectPath); 829cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (address == null) return false; 830cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 831cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh if (mBluetoothService.getDeviceOutOfBandData( 832cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh mAdapter.getRemoteDevice(address)) != null) { 833cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh return true; 834cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 8351510770165b7bc675e5171560e907c0269dbe0faJaikumar Ganesh return false; 836cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh } 837cc5494c9996f809e36539b24e8b6b67683383d29Jaikumar Ganesh 83896a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh private boolean isOtherSinkInNonDisconnectedState(String address) { 8395a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh List<BluetoothDevice> devices = 84096a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh mA2dp.getDevicesMatchingConnectionStates(new int[] {BluetoothA2dp.STATE_CONNECTED, 84196a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh BluetoothA2dp.STATE_CONNECTING, 84296a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh BluetoothA2dp.STATE_DISCONNECTING}); 84396a79830ea1ae3ab3d6d3cce2bd1397fcd40ea0eJaikumar Ganesh 844577dd1f3e274b84876471c22efac578db94811fcJaikumar Ganesh if (devices.size() == 0) return false; 8455a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh for (BluetoothDevice dev: devices) { 846577dd1f3e274b84876471c22efac578db94811fcJaikumar Ganesh if (!dev.getAddress().equals(address)) return true; 847577dd1f3e274b84876471c22efac578db94811fcJaikumar Ganesh } 848577dd1f3e274b84876471c22efac578db94811fcJaikumar Ganesh return false; 849577dd1f3e274b84876471c22efac578db94811fcJaikumar Ganesh } 850577dd1f3e274b84876471c22efac578db94811fcJaikumar Ganesh 8519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 8529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a Cancel method call to org.bluez.Agent. 8539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 854d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private void onAgentCancel() { 855005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL); 856b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 857e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh 858e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_AGENT_CANCEL), 859e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh 1500); 860e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh 861b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 8659a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code for the async response to a DiscoverServices 8669a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * method call to org.bluez.Adapter. 8679a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 8689a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param deviceObjectPath the path for the specified device 8699a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param result true for success; false on error 8709a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 8711caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private void onDiscoverServicesResult(String deviceObjectPath, boolean result) { 8721caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); 87381f8e3c85ff8d134fc21bd103145202ea7f78e49Staffan Lindvall if (address == null) return; 87481f8e3c85ff8d134fc21bd103145202ea7f78e49Staffan Lindvall 8751caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // We don't parse the xml here, instead just query Bluez for the properties. 8761caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (result) { 87710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mBluetoothService.updateRemoteDevicePropertiesCache(address); 8781caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 8791caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mBluetoothService.sendUuidIntent(address); 88016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mBluetoothService.makeServiceChannelCallbacks(address); 8811caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 8821caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 8839a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 8849a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code for the async response to a CreateDevice 8859a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * method call to org.bluez.Adapter. 8869a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 8879a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param address the MAC address of the device to create 8889a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param result {@link #CREATE_DEVICE_SUCCESS}, 8899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * {@link #CREATE_DEVICE_ALREADY_EXISTS} or {@link #CREATE_DEVICE_FAILED}} 8909a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 89116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private void onCreateDeviceResult(String address, int result) { 89216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("Result of onCreateDeviceResult:" + result); 89316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 89416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly switch (result) { 89516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly case CREATE_DEVICE_ALREADY_EXISTS: 89616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly String path = mBluetoothService.getObjectPathFromAddress(address); 89716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (path != null) { 89816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mBluetoothService.discoverServicesNative(path, ""); 89916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly break; 90016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 9019a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby Log.w(TAG, "Device exists, but we don't have the bluez path, failing"); 90216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // fall-through 90316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly case CREATE_DEVICE_FAILED: 9041caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mBluetoothService.sendUuidIntent(address); 90516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mBluetoothService.makeServiceChannelCallbacks(address); 90616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly break; 90716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly case CREATE_DEVICE_SUCCESS: 90816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // nothing to do, UUID intent's will be sent via property changed 9091caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 9101caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 9111caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 9129a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 9139a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code for the async response to a Connect 9149a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * method call to org.bluez.Input. 9159a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 9169a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param path the path of the specified input device 9179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param result Result code of the operation. 9189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 919fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh private void onInputDeviceConnectionResult(String path, int result) { 920de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh // Success case gets handled by Property Change signal 921fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh if (result != BluetoothInputDevice.INPUT_OPERATION_SUCCESS) { 922de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh String address = mBluetoothService.getAddressFromObjectPath(path); 923de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh if (address == null) return; 924de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh 925de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh boolean connected = false; 926de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh BluetoothDevice device = mAdapter.getRemoteDevice(address); 9274ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh int state = mBluetoothService.getInputDeviceConnectionState(device); 928de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh if (state == BluetoothInputDevice.STATE_CONNECTING) { 929fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh if (result == BluetoothInputDevice.INPUT_CONNECT_FAILED_ALREADY_CONNECTED) { 930fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = true; 931fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } else { 932fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = false; 933fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } 934de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } else if (state == BluetoothInputDevice.STATE_DISCONNECTING) { 935fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh if (result == BluetoothInputDevice.INPUT_DISCONNECT_FAILED_NOT_CONNECTED) { 936fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = false; 937fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } else { 938fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh // There is no better way to handle this, this shouldn't happen 939fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = true; 940fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } 941de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } else { 942de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh Log.e(TAG, "Error onInputDeviceConnectionResult. State is:" + state); 943de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } 944de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh mBluetoothService.handleInputDevicePropertyChange(address, connected); 945de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } 946de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh } 947de07503a382e81ba82f4cd4dee81ff2fbf3295bcJaikumar Ganesh 9489a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 9499a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code for the async response to a Connect 9509a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * method call to org.bluez.Network. 9519a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 9529a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param path the path of the specified PAN device 9539a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param result Result code of the operation. 9549a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 955fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh private void onPanDeviceConnectionResult(String path, int result) { 9566fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang log ("onPanDeviceConnectionResult " + path + " " + result); 9576fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang // Success case gets handled by Property Change signal 958fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh if (result != BluetoothPan.PAN_OPERATION_SUCCESS) { 9596fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang String address = mBluetoothService.getAddressFromObjectPath(path); 9606fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (address == null) return; 9616fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 9626fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang boolean connected = false; 9636fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang BluetoothDevice device = mAdapter.getRemoteDevice(address); 96474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh int state = mBluetoothService.getPanDeviceConnectionState(device); 9656fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (state == BluetoothPan.STATE_CONNECTING) { 966fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh if (result == BluetoothPan.PAN_CONNECT_FAILED_ALREADY_CONNECTED) { 967fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = true; 968fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } else { 969fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = false; 970fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } 9716fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } else if (state == BluetoothPan.STATE_DISCONNECTING) { 972fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh if (result == BluetoothPan.PAN_DISCONNECT_FAILED_NOT_CONNECTED) { 973fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = false; 974fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } else { 975fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh // There is no better way to handle this, this shouldn't happen 976fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh connected = true; 977fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh } 9786fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } else { 9796fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang Log.e(TAG, "Error onPanDeviceConnectionResult. State is: " 9806fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang + state + " result: "+ result); 9816fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 9826fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang int newState = connected? BluetoothPan.STATE_CONNECTED : 9836fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang BluetoothPan.STATE_DISCONNECTED; 9845200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh mBluetoothService.handlePanDeviceStateChange(device, newState, 9855200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh BluetoothPan.LOCAL_PANU_ROLE); 9866fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 9876fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 9886fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 9899a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 990b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh * Called by native code for the async response to a Connect 991b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh * method call to org.bluez.Health 992b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh * 993b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh * @param chanCode The internal id of the channel 994b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh * @param result Result code of the operation. 995b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh */ 996b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh private void onHealthDeviceConnectionResult(int chanCode, int result) { 997b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh log ("onHealthDeviceConnectionResult " + chanCode + " " + result); 998b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh // Success case gets handled by Property Change signal 999b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh if (result != BluetoothHealth.HEALTH_OPERATION_SUCCESS) { 1000b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh mBluetoothService.onHealthDeviceChannelConnectionError(chanCode, 1001b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh BluetoothHealth.STATE_CHANNEL_DISCONNECTED); 1002b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh } 1003b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh } 1004b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh 1005b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /** 10069a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DeviceDisconnected signal from 10079a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.NetworkServer. 10089a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 10099a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param address the MAC address of the disconnected device 10109a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 1011c1520ecb41600cd364f03c4c100f927a98924e6aJaikumar Ganesh private void onNetworkDeviceDisconnected(String address) { 1012c1520ecb41600cd364f03c4c100f927a98924e6aJaikumar Ganesh BluetoothDevice device = mAdapter.getRemoteDevice(address); 10135200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED, 10145200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh BluetoothPan.LOCAL_NAP_ROLE); 1015c1520ecb41600cd364f03c4c100f927a98924e6aJaikumar Ganesh } 1016c1520ecb41600cd364f03c4c100f927a98924e6aJaikumar Ganesh 10179a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby /** 10189a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * Called by native code on a DeviceConnected signal from 10199a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * org.bluez.NetworkServer. 10209a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * 10219a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param address the MAC address of the connected device 10229a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param iface interface of remote network 10239a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby * @param destUuid unused UUID parameter 10249a62c9cd6585656f4e29ba971b1f88a510d674bdJake Hamby */ 1025707952ecd4b6cae25aabcf51f94d702a65847e9eJaikumar Ganesh private void onNetworkDeviceConnected(String address, String iface, int destUuid) { 1026c1520ecb41600cd364f03c4c100f927a98924e6aJaikumar Ganesh BluetoothDevice device = mAdapter.getRemoteDevice(address); 10275200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED, 10285200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh BluetoothPan.LOCAL_NAP_ROLE); 1029c1520ecb41600cd364f03c4c100f927a98924e6aJaikumar Ganesh } 1030c1520ecb41600cd364f03c4c100f927a98924e6aJaikumar Ganesh 10312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 10322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Called by native code on a PropertyChanged signal from 10332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * org.bluez.HealthDevice. 10342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 10352ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param devicePath the object path of the remote device 10362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param propValues Properties (Name-Value) of the Health Device. 10372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 10382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private void onHealthDevicePropertyChanged(String devicePath, String[] propValues) { 10392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh log("Health Device : Name of Property is: " + propValues[0] + " Value:" + propValues[1]); 10402ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothService.onHealthDevicePropertyChanged(devicePath, propValues[1]); 10412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 10422ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 10432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 10442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Called by native code on a ChannelCreated/Deleted signal from 10452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * org.bluez.HealthDevice. 10462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 10472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param devicePath the object path of the remote device 10482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param channelPath the path of the health channel. 10492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param exists Boolean to indicate if the channel was created or deleted. 10502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 10512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private void onHealthDeviceChannelChanged(String devicePath, String channelPath, 10522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh boolean exists) { 10532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh log("Health Device : devicePath: " + devicePath + ":channelPath:" + channelPath + 10542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh ":exists" + exists); 10552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mBluetoothService.onHealthDeviceChannelChanged(devicePath, channelPath, exists); 10562ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 10572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void log(String msg) { 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, msg); 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1061d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1062d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 1063d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void startEventLoopNative(); 1064d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void stopEventLoopNative(); 1065d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean isEventLoopRunningNative(); 1066d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1068