BluetoothEventManager.java revision 436b29e68e6608bed9e8e7d54385b8f62d89208e
1436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/* 2436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Copyright (C) 2011 The Android Open Source Project 3436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 4436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Licensed under the Apache License, Version 2.0 (the "License"); 5436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * you may not use this file except in compliance with the License. 6436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * You may obtain a copy of the License at 7436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 8436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * http://www.apache.org/licenses/LICENSE-2.0 9436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 10436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Unless required by applicable law or agreed to in writing, software 11436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * distributed under the License is distributed on an "AS IS" BASIS, 12436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * See the License for the specific language governing permissions and 14436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * limitations under the License. 15436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 16436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 17436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambypackage com.android.settings.bluetooth; 18436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 19436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport com.android.settings.R; 20436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 21436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothAdapter; 22436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothClass; 23436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothDevice; 24436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.BroadcastReceiver; 25436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.Context; 26436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.Intent; 27436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.IntentFilter; 28436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.util.Log; 29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 30436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.ArrayList; 31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection; 32436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.HashMap; 33436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Map; 34436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Set; 35436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 36436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/** 37436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * BluetoothEventManager receives broadcasts and callbacks from the Bluetooth 38436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * API and dispatches the event on the UI thread to the right class in the 39436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Settings. 40436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 41436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class BluetoothEventManager { 42436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final String TAG = "BluetoothEventManager"; 43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final LocalBluetoothAdapter mLocalAdapter; 45436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final CachedBluetoothDeviceManager mDeviceManager; 46436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private LocalBluetoothProfileManager mProfileManager; 47436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final IntentFilter mIntentFilter; 48436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Map<String, Handler> mHandlerMap; 49436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 50436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final Collection<BluetoothCallback> mCallbacks = 51436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new ArrayList<BluetoothCallback>(); 52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 53436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby interface Handler { 54436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void onReceive(Context context, Intent intent, BluetoothDevice device); 55436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 56436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 57436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void addHandler(String action, Handler handler) { 58436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mHandlerMap.put(action, handler); 59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mIntentFilter.addAction(action); 60436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 61436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 62436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Set profile manager after construction due to circular dependency 63436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void setProfileManager(LocalBluetoothProfileManager manager) { 64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager = manager; 65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothEventManager(LocalBluetoothAdapter adapter, 68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDeviceManager deviceManager) { 69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = adapter; 70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager = deviceManager; 71436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mIntentFilter = new IntentFilter(); 72436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mHandlerMap = new HashMap<String, Handler>(); 73436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 74436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Bluetooth on/off broadcasts 75436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler()); 76436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Discovery broadcasts 78436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true)); 79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false)); 80436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler()); 81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler()); 82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler()); 83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Pairing broadcasts 85436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler()); 86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothDevice.ACTION_PAIRING_CANCEL, new PairingCancelHandler()); 87436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 88436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Fine-grained state broadcasts 89436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler()); 90436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler()); 91436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 92436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Dock event broadcasts 93436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler()); 94436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 95436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 96436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 97436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * A Bluetooth-related activity is now in the foreground. Register to 98436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * start receiving Bluetooth events. 99436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param context a Context object for the current Activity 100436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void resume(Context context) { 102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mLocalAdapter.syncBluetoothState()) { 103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // adapter state changed while we were paused: send callbacks 104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int newState = mLocalAdapter.getState(); 105436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothCallback callback : mCallbacks) { 107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby callback.onBluetoothStateChanged(newState); 108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 109436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 111436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby context.registerReceiver(mBroadcastReceiver, mIntentFilter); 112436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 113436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 114436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void pause(Context context) { 115436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby context.unregisterReceiver(mBroadcastReceiver); 116436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** Register to start receiving callbacks for Bluetooth events. */ 119436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void registerCallback(BluetoothCallback callback) { 120436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 121436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mCallbacks.add(callback); 122436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 123436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 124436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 125436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** Unregister to stop receiving callbacks for Bluetooth events. */ 126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby void unregisterCallback(BluetoothCallback callback) { 127436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mCallbacks.remove(callback); 129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // This can't be called from a broadcast receiver where the filter is set in the Manifest. 133436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static String getDockedDeviceAddress(Context context) { 134436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // This works only because these broadcast intents are "sticky" 135436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Intent i = context.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT)); 136436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (i != null) { 137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); 138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) { 139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (device != null) { 141436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return device.getAddress(); 142436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 143436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return null; 146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 148436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 149436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby @Override 150436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent) { 151436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.v(TAG, "Received " + intent.getAction()); 152436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby String action = intent.getAction(); 154436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device = intent 155436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 156436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 157436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Handler handler = mHandlerMap.get(action); 158436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (handler != null) { 159436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby handler.onReceive(context, intent, device); 160436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 161436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby }; 163436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class AdapterStateChangedHandler implements Handler { 165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 166436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 167436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 168436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothAdapter.ERROR); 169436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // update local profiles and get paired devices 170436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.setBluetoothStateInt(state); 171436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // send callback to update UI and possibly start scanning 172436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 173436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothCallback callback : mCallbacks) { 174436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby callback.onBluetoothStateChanged(state); 175436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 176436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 177436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 178436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 179436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 180436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class ScanningStateChangedHandler implements Handler { 181436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final boolean mStarted; 182436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 183436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ScanningStateChangedHandler(boolean started) { 184436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mStarted = started; 185436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 186436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 187436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 188436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 189436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothCallback callback : mCallbacks) { 190436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby callback.onScanningStateChanged(mStarted); 191436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 192436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 193436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager.onScanningStateChanged(mStarted); 194436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothPreferences.persistDiscoveringTimestamp(context); 195436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 196436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 197436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 198436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class DeviceFoundHandler implements Handler { 199436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 200436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 201436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE); 202436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS); 203436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME); 204436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // TODO Pick up UUID. They should be available for 2.1 devices. 205436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1. 206436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 207436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice == null) { 208436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device); 209436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: " 210436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby + cachedDevice); 211436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // callback to UI to create Preference for new device 212436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby dispatchDeviceAdded(cachedDevice); 213436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 214436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.setRssi(rssi); 215436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.setBtClass(btClass); 216436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.setName(name); 217436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.setVisible(true); 218436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 219436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 220436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 221436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) { 222436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 223436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothCallback callback : mCallbacks) { 224436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby callback.onDeviceAdded(cachedDevice); 225436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 226436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 227436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 228436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 229436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class DeviceDisappearedHandler implements Handler { 230436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 231436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 232436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 233436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice == null) { 234436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.w(TAG, "received ACTION_DISAPPEARED for an unknown device: " + device); 235436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 236436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 237436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mDeviceManager.onDeviceDisappeared(cachedDevice)) { 238436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 239436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothCallback callback : mCallbacks) { 240436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby callback.onDeviceDeleted(cachedDevice); 241436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 242436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 243436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 244436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 245436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 246436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 247436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class NameChangedHandler implements Handler { 248436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 249436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 250436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager.onDeviceNameUpdated(device); 251436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 252436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 253436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 254436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class BondStateChangedHandler implements Handler { 255436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 256436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 257436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (device == null) { 258436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); 259436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 260436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 261436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 262436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice.ERROR); 263436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 264436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice == null) { 265436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.w(TAG, "CachedBluetoothDevice for device " + device + 266436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby " not found, calling readPairedDevices()."); 267436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!readPairedDevices()) { 268436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.e(TAG, "Got bonding state changed for " + device + 269436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ", but we have no record of that device."); 270436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 271436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 272436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice = mDeviceManager.findDevice(device); 273436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice == null) { 274436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.e(TAG, "Got bonding state changed for " + device + 275436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ", but device not added in cache."); 276436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 277436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 278436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 279436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 280436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized (mCallbacks) { 281436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothCallback callback : mCallbacks) { 282436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby callback.onDeviceBondStateChanged(cachedDevice, bondState); 283436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 284436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.onBondingStateChanged(bondState); 286436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 287436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (bondState == BluetoothDevice.BOND_NONE) { 288436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (device.isBluetoothDock()) { 289436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // After a dock is unpaired, we will forget the settings 290436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothPreferences 291436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby .removeDockAutoConnectSetting(context, device.getAddress()); 292436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 293436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // if the device is undocked, remove it from the list as well 294436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!device.getAddress().equals(getDockedDeviceAddress(context))) { 295436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager.onDeviceDisappeared(cachedDevice); 296436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 297436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 298436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON, 299436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice.ERROR); 300436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 301436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby showUnbondMessage(context, cachedDevice.getName(), reason); 302436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 303436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 304436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 305436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 306436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Called when we have reached the unbonded state. 307436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 308436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @param reason one of the error reasons from 309436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * BluetoothDevice.UNBOND_REASON_* 310436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 311436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void showUnbondMessage(Context context, String name, int reason) { 312436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int errorMsg; 313436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 314436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby switch(reason) { 315436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothDevice.UNBOND_REASON_AUTH_FAILED: 316436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby errorMsg = R.string.bluetooth_pairing_pin_error_message; 317436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby break; 318436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED: 319436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby errorMsg = R.string.bluetooth_pairing_rejected_error_message; 320436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby break; 321436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN: 322436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby errorMsg = R.string.bluetooth_pairing_device_down_error_message; 323436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby break; 324436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS: 325436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT: 326436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS: 327436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED: 328436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby errorMsg = R.string.bluetooth_pairing_error_message; 329436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby break; 330436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby default: 331436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason); 332436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 333436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 334436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Utils.showError(context, name, errorMsg); 335436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 336436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 337436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 338436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class ClassChangedHandler implements Handler { 339436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 340436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 341436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager.onBtClassChanged(device); 342436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 343436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 344436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 345436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class UuidChangedHandler implements Handler { 346436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, 347436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device) { 348436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager.onUuidChanged(device); 349436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 350436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 351436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 352436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class PairingCancelHandler implements Handler { 353436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, BluetoothDevice device) { 354436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (device == null) { 355436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.e(TAG, "ACTION_PAIRING_CANCEL with no EXTRA_DEVICE"); 356436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 357436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 358436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int errorMsg = R.string.bluetooth_pairing_error_message; 359436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 360436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Utils.showError(context, cachedDevice.getName(), errorMsg); 361436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 362436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 363436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 364436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private class DockEventHandler implements Handler { 365436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onReceive(Context context, Intent intent, BluetoothDevice device) { 366436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Remove if unpair device upon undocking 367436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int anythingButUnDocked = Intent.EXTRA_DOCK_STATE_UNDOCKED + 1; 368436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, anythingButUnDocked); 369436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) { 370436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) { 371436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 372436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice != null) { 373436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager.onDeviceDisappeared(cachedDevice); 374436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 375436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 376436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 377436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 378436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 379436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 380436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean readPairedDevices() { 381436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices(); 382436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (bondedDevices == null) { 383436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 384436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 385436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 386436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean deviceAdded = false; 387436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothDevice device : bondedDevices) { 388436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 389436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice == null) { 390436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device); 391436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby dispatchDeviceAdded(cachedDevice); 392436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby deviceAdded = true; 393436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 394436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 395436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 396436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return deviceAdded; 397436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 398436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby} 399