BluetoothControllerImpl.java revision fac2538e463138a8a1a92bc94af3f310d28718b4
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.statusbar.policy; 18 19import android.app.ActivityManager; 20import android.bluetooth.BluetoothAdapter; 21import android.content.Context; 22import android.os.Handler; 23import android.os.Looper; 24import android.os.Message; 25import android.os.UserHandle; 26import android.os.UserManager; 27import android.util.Log; 28 29import com.android.settingslib.bluetooth.BluetoothCallback; 30import com.android.settingslib.bluetooth.CachedBluetoothDevice; 31import com.android.settingslib.bluetooth.LocalBluetoothManager; 32 33import java.io.FileDescriptor; 34import java.io.PrintWriter; 35import java.util.ArrayList; 36import java.util.Collection; 37 38public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback, 39 CachedBluetoothDevice.Callback { 40 private static final String TAG = "BluetoothController"; 41 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 42 43 private final LocalBluetoothManager mLocalBluetoothManager; 44 private final UserManager mUserManager; 45 private final int mCurrentUser; 46 47 private boolean mEnabled; 48 private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 49 private CachedBluetoothDevice mLastDevice; 50 51 private final H mHandler = new H(); 52 private int mState; 53 54 public BluetoothControllerImpl(Context context, Looper bgLooper) { 55 mLocalBluetoothManager = LocalBluetoothManager.getInstance(context, null); 56 if (mLocalBluetoothManager != null) { 57 mLocalBluetoothManager.getEventManager().setReceiverHandler(new Handler(bgLooper)); 58 mLocalBluetoothManager.getEventManager().registerCallback(this); 59 onBluetoothStateChanged( 60 mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState()); 61 } 62 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 63 mCurrentUser = ActivityManager.getCurrentUser(); 64 } 65 66 @Override 67 public boolean canConfigBluetooth() { 68 return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, 69 UserHandle.of(mCurrentUser)); 70 } 71 72 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 73 pw.println("BluetoothController state:"); 74 pw.print(" mLocalBluetoothManager="); pw.println(mLocalBluetoothManager); 75 if (mLocalBluetoothManager == null) { 76 return; 77 } 78 pw.print(" mEnabled="); pw.println(mEnabled); 79 pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState)); 80 pw.print(" mLastDevice="); pw.println(mLastDevice); 81 pw.print(" mCallbacks.size="); pw.println(mHandler.mCallbacks.size()); 82 pw.println(" Bluetooth Devices:"); 83 for (CachedBluetoothDevice device : 84 mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) { 85 pw.println(" " + getDeviceString(device)); 86 } 87 } 88 89 private static String stateToString(int state) { 90 switch (state) { 91 case BluetoothAdapter.STATE_CONNECTED: 92 return "CONNECTED"; 93 case BluetoothAdapter.STATE_CONNECTING: 94 return "CONNECTING"; 95 case BluetoothAdapter.STATE_DISCONNECTED: 96 return "DISCONNECTED"; 97 case BluetoothAdapter.STATE_DISCONNECTING: 98 return "DISCONNECTING"; 99 } 100 return "UNKNOWN(" + state + ")"; 101 } 102 103 private String getDeviceString(CachedBluetoothDevice device) { 104 return device.getName() + " " + device.getBondState() + " " + device.isConnected(); 105 } 106 107 @Override 108 public void addStateChangedCallback(Callback cb) { 109 mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget(); 110 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); 111 } 112 113 @Override 114 public void removeStateChangedCallback(Callback cb) { 115 mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget(); 116 } 117 118 @Override 119 public boolean isBluetoothEnabled() { 120 return mEnabled; 121 } 122 123 @Override 124 public int getBluetoothState() { 125 return mState; 126 } 127 128 @Override 129 public boolean isBluetoothConnected() { 130 return mConnectionState == BluetoothAdapter.STATE_CONNECTED; 131 } 132 133 @Override 134 public boolean isBluetoothConnecting() { 135 return mConnectionState == BluetoothAdapter.STATE_CONNECTING; 136 } 137 138 @Override 139 public void setBluetoothEnabled(boolean enabled) { 140 if (mLocalBluetoothManager != null) { 141 mLocalBluetoothManager.getBluetoothAdapter().setBluetoothEnabled(enabled); 142 } 143 } 144 145 @Override 146 public boolean isBluetoothSupported() { 147 return mLocalBluetoothManager != null; 148 } 149 150 @Override 151 public void connect(final CachedBluetoothDevice device) { 152 if (mLocalBluetoothManager == null || device == null) return; 153 device.connect(true); 154 } 155 156 @Override 157 public void disconnect(CachedBluetoothDevice device) { 158 if (mLocalBluetoothManager == null || device == null) return; 159 device.disconnect(); 160 } 161 162 @Override 163 public String getLastDeviceName() { 164 return mLastDevice != null ? mLastDevice.getName() : null; 165 } 166 167 @Override 168 public Collection<CachedBluetoothDevice> getDevices() { 169 return mLocalBluetoothManager != null 170 ? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy() 171 : null; 172 } 173 174 private void updateConnected() { 175 // Make sure our connection state is up to date. 176 int state = mLocalBluetoothManager.getBluetoothAdapter().getConnectionState(); 177 if (state != mConnectionState) { 178 mConnectionState = state; 179 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); 180 } 181 if (mLastDevice != null && mLastDevice.isConnected()) { 182 // Our current device is still valid. 183 return; 184 } 185 mLastDevice = null; 186 for (CachedBluetoothDevice device : getDevices()) { 187 if (device.isConnected()) { 188 mLastDevice = device; 189 } 190 } 191 if (mLastDevice == null && mConnectionState == BluetoothAdapter.STATE_CONNECTED) { 192 // If somehow we think we are connected, but have no connected devices, we aren't 193 // connected. 194 mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 195 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); 196 } 197 } 198 199 @Override 200 public void onBluetoothStateChanged(int bluetoothState) { 201 mEnabled = bluetoothState == BluetoothAdapter.STATE_ON 202 || bluetoothState == BluetoothAdapter.STATE_TURNING_ON; 203 mState = bluetoothState; 204 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); 205 } 206 207 @Override 208 public void onScanningStateChanged(boolean started) { 209 // Don't care. 210 } 211 212 @Override 213 public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { 214 cachedDevice.registerCallback(this); 215 updateConnected(); 216 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); 217 } 218 219 @Override 220 public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { 221 updateConnected(); 222 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); 223 } 224 225 @Override 226 public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { 227 updateConnected(); 228 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); 229 } 230 231 @Override 232 public void onDeviceAttributesChanged() { 233 updateConnected(); 234 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); 235 } 236 237 @Override 238 public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { 239 mLastDevice = cachedDevice; 240 updateConnected(); 241 mConnectionState = state; 242 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); 243 } 244 245 private final class H extends Handler { 246 private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>(); 247 248 private static final int MSG_PAIRED_DEVICES_CHANGED = 1; 249 private static final int MSG_STATE_CHANGED = 2; 250 private static final int MSG_ADD_CALLBACK = 3; 251 private static final int MSG_REMOVE_CALLBACK = 4; 252 253 @Override 254 public void handleMessage(Message msg) { 255 switch (msg.what) { 256 case MSG_PAIRED_DEVICES_CHANGED: 257 firePairedDevicesChanged(); 258 break; 259 case MSG_STATE_CHANGED: 260 fireStateChange(); 261 break; 262 case MSG_ADD_CALLBACK: 263 mCallbacks.add((BluetoothController.Callback) msg.obj); 264 break; 265 case MSG_REMOVE_CALLBACK: 266 mCallbacks.remove((BluetoothController.Callback) msg.obj); 267 break; 268 } 269 } 270 271 private void firePairedDevicesChanged() { 272 for (BluetoothController.Callback cb : mCallbacks) { 273 cb.onBluetoothDevicesChanged(); 274 } 275 } 276 277 private void fireStateChange() { 278 for (BluetoothController.Callback cb : mCallbacks) { 279 fireStateChange(cb); 280 } 281 } 282 283 private void fireStateChange(BluetoothController.Callback cb) { 284 cb.onBluetoothStateChange(mEnabled); 285 } 286 } 287} 288