17ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/* 27ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Copyright (C) 2011 The Android Open Source Project 37ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * 47ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 57ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * you may not use this file except in compliance with the License. 67ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * You may obtain a copy of the License at 77ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * 87ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 97ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * 107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Unless required by applicable law or agreed to in writing, software 117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * distributed under the License is distributed on an "AS IS" BASIS, 127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * See the License for the specific language governing permissions and 147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * limitations under the License. 157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */ 167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpackage com.android.settingslib.bluetooth; 187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothAdapter; 207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothClass; 217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothDevice; 227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.BroadcastReceiver; 237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.Context; 247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.Intent; 257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.IntentFilter; 267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.util.Log; 277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport com.android.settingslib.R; 297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.ArrayList; 317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.Collection; 327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.HashMap; 337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.Map; 347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.Set; 357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/** 377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * BluetoothEventManager receives broadcasts and callbacks from the Bluetooth 387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * API and dispatches the event on the UI thread to the right class in the 397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Settings. 407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */ 417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpublic final class BluetoothEventManager { 427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private static final String TAG = "BluetoothEventManager"; 437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final LocalBluetoothAdapter mLocalAdapter; 457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final CachedBluetoothDeviceManager mDeviceManager; 467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private LocalBluetoothProfileManager mProfileManager; 477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter; 487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final Map<String, Handler> mHandlerMap; 497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private Context mContext; 507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final Collection<BluetoothCallback> mCallbacks = 527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk new ArrayList<BluetoothCallback>(); 537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 54744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk private android.os.Handler mReceiverHandler; 55744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk 567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk interface Handler { 577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk void onReceive(Context context, Intent intent, BluetoothDevice device); 587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 60744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk private void addHandler(String action, Handler handler) { 617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mHandlerMap.put(action, handler); 627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mAdapterIntentFilter.addAction(action); 637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk void addProfileHandler(String action, Handler handler) { 667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mHandlerMap.put(action, handler); 677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mProfileIntentFilter.addAction(action); 687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Set profile manager after construction due to circular dependency 717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk void setProfileManager(LocalBluetoothProfileManager manager) { 727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mProfileManager = manager; 737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothEventManager(LocalBluetoothAdapter adapter, 767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDeviceManager deviceManager, Context context) { 777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mLocalAdapter = adapter; 787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mDeviceManager = deviceManager; 797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mAdapterIntentFilter = new IntentFilter(); 807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mProfileIntentFilter = new IntentFilter(); 817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mHandlerMap = new HashMap<String, Handler>(); 827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mContext = context; 837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Bluetooth on/off broadcasts 857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler()); 86be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk // Generic connected/not broadcast 87be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED, 88be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk new ConnectionStateChangedHandler()); 897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Discovery broadcasts 917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true)); 927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false)); 937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler()); 947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler()); 957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler()); 968c495be48fc6973cc291fb4e6200154e2f28d571Jason Monk addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler()); 977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Pairing broadcasts 997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler()); 1007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothDevice.ACTION_PAIRING_CANCEL, new PairingCancelHandler()); 1017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Fine-grained state broadcasts 1037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler()); 1047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler()); 1057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Dock event broadcasts 1077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler()); 1087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 109744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter, null, mReceiverHandler); 1107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk void registerProfileIntentReceiver() { 113744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk mContext.registerReceiver(mBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler); 114744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk } 115744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk 116744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk public void setReceiverHandler(android.os.Handler handler) { 117744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk mContext.unregisterReceiver(mBroadcastReceiver); 118744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk mReceiverHandler = handler; 119744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter, null, mReceiverHandler); 120744cf647f71b1e5a012a90ef195bf2c3c486f418Jason Monk registerProfileIntentReceiver(); 1217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk /** Register to start receiving callbacks for Bluetooth events. */ 1247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void registerCallback(BluetoothCallback callback) { 1257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk synchronized (mCallbacks) { 1267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mCallbacks.add(callback); 1277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk /** Unregister to stop receiving callbacks for Bluetooth events. */ 1317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void unregisterCallback(BluetoothCallback callback) { 1327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk synchronized (mCallbacks) { 1337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mCallbacks.remove(callback); 1347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 1387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk @Override 1397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent) { 1407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk String action = intent.getAction(); 1417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device = intent 1427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 1437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Handler handler = mHandlerMap.get(action); 1457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (handler != null) { 1467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk handler.onReceive(context, intent, device); 1477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk }; 1507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class AdapterStateChangedHandler implements Handler { 1527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 1537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 1547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 1557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothAdapter.ERROR); 1567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // update local profiles and get paired devices 1577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mLocalAdapter.setBluetoothStateInt(state); 1587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // send callback to update UI and possibly start scanning 1597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk synchronized (mCallbacks) { 1607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk for (BluetoothCallback callback : mCallbacks) { 1617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk callback.onBluetoothStateChanged(state); 1627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Inform CachedDeviceManager that the adapter state has changed 1657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mDeviceManager.onBluetoothStateChanged(state); 1667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class ScanningStateChangedHandler implements Handler { 1707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final boolean mStarted; 1717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk ScanningStateChangedHandler(boolean started) { 1737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mStarted = started; 1747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 1767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 1777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk synchronized (mCallbacks) { 1787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk for (BluetoothCallback callback : mCallbacks) { 1797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk callback.onScanningStateChanged(mStarted); 1807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mDeviceManager.onScanningStateChanged(mStarted); 1837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class DeviceFoundHandler implements Handler { 1877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 1887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 1897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE); 1907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS); 1917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME); 1927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // TODO Pick up UUID. They should be available for 2.1 devices. 1937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1. 1947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 1957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (cachedDevice == null) { 1967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device); 1977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: " 1987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk + cachedDevice); 1997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice.setRssi(rssi); 2017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice.setBtClass(btClass); 2027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice.setNewName(name); 2037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice.setVisible(true); 2047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 207be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk private class ConnectionStateChangedHandler implements Handler { 208be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk @Override 209be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk public void onReceive(Context context, Intent intent, BluetoothDevice device) { 210be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 211be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 212be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk BluetoothAdapter.ERROR); 213be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk dispatchConnectionStateChanged(cachedDevice, state); 214be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk } 215be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk } 216be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk 217be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { 218be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk synchronized (mCallbacks) { 219be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk for (BluetoothCallback callback : mCallbacks) { 220be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk callback.onConnectionStateChanged(cachedDevice, state); 221be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk } 222be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk } 223be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk } 224be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk 225be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) { 2267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk synchronized (mCallbacks) { 2277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk for (BluetoothCallback callback : mCallbacks) { 2287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk callback.onDeviceAdded(cachedDevice); 2297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class DeviceDisappearedHandler implements Handler { 2347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 2357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 2367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 2377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (cachedDevice == null) { 2387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.w(TAG, "received ACTION_DISAPPEARED for an unknown device: " + device); 2397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return; 2407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (CachedBluetoothDeviceManager.onDeviceDisappeared(cachedDevice)) { 2427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk synchronized (mCallbacks) { 2437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk for (BluetoothCallback callback : mCallbacks) { 2447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk callback.onDeviceDeleted(cachedDevice); 2457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class NameChangedHandler implements Handler { 2527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 2537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 2547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mDeviceManager.onDeviceNameUpdated(device); 2557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class BondStateChangedHandler implements Handler { 2597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 2607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 2617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (device == null) { 2627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); 2637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return; 2647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 2667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice.ERROR); 2677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 2687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (cachedDevice == null) { 2697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.w(TAG, "CachedBluetoothDevice for device " + device + 2707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk " not found, calling readPairedDevices()."); 2717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (!readPairedDevices()) { 2727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.e(TAG, "Got bonding state changed for " + device + 2737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk ", but we have no record of that device."); 2747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return; 2757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice = mDeviceManager.findDevice(device); 2777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (cachedDevice == null) { 2787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.e(TAG, "Got bonding state changed for " + device + 2797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk ", but device not added in cache."); 2807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return; 2817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk synchronized (mCallbacks) { 2857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk for (BluetoothCallback callback : mCallbacks) { 2867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk callback.onDeviceBondStateChanged(cachedDevice, bondState); 2877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice.onBondingStateChanged(bondState); 2907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (bondState == BluetoothDevice.BOND_NONE) { 2927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON, 2937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice.ERROR); 2947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk showUnbondMessage(context, cachedDevice.getName(), reason); 2967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk /** 3007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Called when we have reached the unbonded state. 3017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * 3027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * @param reason one of the error reasons from 3037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * BluetoothDevice.UNBOND_REASON_* 3047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */ 3057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private void showUnbondMessage(Context context, String name, int reason) { 3067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk int errorMsg; 3077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 3087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk switch(reason) { 3097ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothDevice.UNBOND_REASON_AUTH_FAILED: 3107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk errorMsg = R.string.bluetooth_pairing_pin_error_message; 3117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk break; 3127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED: 3137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk errorMsg = R.string.bluetooth_pairing_rejected_error_message; 3147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk break; 3157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN: 3167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk errorMsg = R.string.bluetooth_pairing_device_down_error_message; 3177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk break; 3187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS: 3197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT: 3207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS: 3217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED: 3227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk errorMsg = R.string.bluetooth_pairing_error_message; 3237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk break; 3247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk default: 3257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason); 3267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return; 3277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Utils.showError(context, name, errorMsg); 3297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 3327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class ClassChangedHandler implements Handler { 3337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 3347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 3357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mDeviceManager.onBtClassChanged(device); 3367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 3397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class UuidChangedHandler implements Handler { 3407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, 3417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice device) { 3427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mDeviceManager.onUuidChanged(device); 3437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 3467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class PairingCancelHandler implements Handler { 3477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, BluetoothDevice device) { 3487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (device == null) { 3497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.e(TAG, "ACTION_PAIRING_CANCEL with no EXTRA_DEVICE"); 3507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return; 3517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 353d2b033aeb4123ec92892495c262e0272ffb7ecdcPavlin Radoslavov if (cachedDevice == null) { 354d2b033aeb4123ec92892495c262e0272ffb7ecdcPavlin Radoslavov Log.e(TAG, "ACTION_PAIRING_CANCEL with no cached device"); 355d2b033aeb4123ec92892495c262e0272ffb7ecdcPavlin Radoslavov return; 356d2b033aeb4123ec92892495c262e0272ffb7ecdcPavlin Radoslavov } 357d2b033aeb4123ec92892495c262e0272ffb7ecdcPavlin Radoslavov int errorMsg = R.string.bluetooth_pairing_error_message; 3584d08a485db5021638b0abcb8675ba00579bd7fccSanket Padawe if (context != null && cachedDevice != null) { 3594d08a485db5021638b0abcb8675ba00579bd7fccSanket Padawe Utils.showError(context, cachedDevice.getName(), errorMsg); 3604d08a485db5021638b0abcb8675ba00579bd7fccSanket Padawe } 3617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 3647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private class DockEventHandler implements Handler { 3657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onReceive(Context context, Intent intent, BluetoothDevice device) { 3667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Remove if unpair device upon undocking 3677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk int anythingButUnDocked = Intent.EXTRA_DOCK_STATE_UNDOCKED + 1; 3687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, anythingButUnDocked); 3697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 3707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) { 3717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 3727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (cachedDevice != null) { 3737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice.setVisible(false); 3747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk boolean readPairedDevices() { 3807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices(); 3817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (bondedDevices == null) { 3827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return false; 3837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 3857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk boolean deviceAdded = false; 3867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk for (BluetoothDevice device : bondedDevices) { 3877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 3887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (cachedDevice == null) { 3897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device); 3907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk dispatchDeviceAdded(cachedDevice); 3917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk deviceAdded = true; 3927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 3957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return deviceAdded; 3967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 3977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk} 398