blob: a04edf77ea542fb19cc28a513225b0910b3d28cf [file] [log] [blame]
John Spurlockaf8d6c42014-05-07 17:49:08 -04001/*
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.bluetooth.BluetoothAdapter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040020import android.content.Context;
Jason Monk744cf642015-05-19 12:04:41 -040021import android.os.Handler;
Jason Monk4ae97d32014-12-17 10:14:33 -050022import android.os.Looper;
Jason Monk744cf642015-05-19 12:04:41 -040023import android.os.Message;
John Spurlock486b78e2014-07-07 08:37:56 -040024import android.util.Log;
John Spurlockaf8d6c42014-05-07 17:49:08 -040025
Jason Monkbe3c5db2015-02-04 13:00:55 -050026import com.android.settingslib.bluetooth.BluetoothCallback;
27import com.android.settingslib.bluetooth.CachedBluetoothDevice;
28import com.android.settingslib.bluetooth.LocalBluetoothManager;
John Spurlock486b78e2014-07-07 08:37:56 -040029
30import java.io.FileDescriptor;
31import java.io.PrintWriter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040032import java.util.ArrayList;
Jason Monkbe3c5db2015-02-04 13:00:55 -050033import java.util.Collection;
John Spurlockaf8d6c42014-05-07 17:49:08 -040034
Jason Monkbe3c5db2015-02-04 13:00:55 -050035public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback,
36 CachedBluetoothDevice.Callback {
John Spurlock486b78e2014-07-07 08:37:56 -040037 private static final String TAG = "BluetoothController";
38 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Jason Monk4ae97d32014-12-17 10:14:33 -050039
John Spurlockd1c86e22014-06-01 00:04:53 -040040 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
Jason Monkbe3c5db2015-02-04 13:00:55 -050041 private final LocalBluetoothManager mLocalBluetoothManager;
Jason Monk4ae97d32014-12-17 10:14:33 -050042
John Spurlockd1c86e22014-06-01 00:04:53 -040043 private boolean mEnabled;
Jason Monka7d92b62015-05-27 10:20:37 -040044 private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
Jason Monkbe3c5db2015-02-04 13:00:55 -050045 private CachedBluetoothDevice mLastDevice;
John Spurlockaf8d6c42014-05-07 17:49:08 -040046
Jason Monk744cf642015-05-19 12:04:41 -040047 private final H mHandler = new H();
48
Jason Monk4ae97d32014-12-17 10:14:33 -050049 public BluetoothControllerImpl(Context context, Looper bgLooper) {
Jason Monkbe3c5db2015-02-04 13:00:55 -050050 mLocalBluetoothManager = LocalBluetoothManager.getInstance(context, null);
51 if (mLocalBluetoothManager != null) {
Jason Monk744cf642015-05-19 12:04:41 -040052 mLocalBluetoothManager.getEventManager().setReceiverHandler(new Handler(bgLooper));
Jason Monkbe3c5db2015-02-04 13:00:55 -050053 mLocalBluetoothManager.getEventManager().registerCallback(this);
54 onBluetoothStateChanged(
55 mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
John Spurlockaf8d6c42014-05-07 17:49:08 -040056 }
John Spurlockaf8d6c42014-05-07 17:49:08 -040057 }
58
John Spurlock486b78e2014-07-07 08:37:56 -040059 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
60 pw.println("BluetoothController state:");
Jason Monkbe3c5db2015-02-04 13:00:55 -050061 pw.print(" mLocalBluetoothManager="); pw.println(mLocalBluetoothManager);
Jason Monk09389a92015-05-19 16:06:52 -040062 if (mLocalBluetoothManager == null) {
63 return;
64 }
John Spurlock486b78e2014-07-07 08:37:56 -040065 pw.print(" mEnabled="); pw.println(mEnabled);
Jason Monka7d92b62015-05-27 10:20:37 -040066 pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState));
John Spurlock486b78e2014-07-07 08:37:56 -040067 pw.print(" mLastDevice="); pw.println(mLastDevice);
68 pw.print(" mCallbacks.size="); pw.println(mCallbacks.size());
Jason Monkbe3c5db2015-02-04 13:00:55 -050069 pw.println(" Bluetooth Devices:");
70 for (CachedBluetoothDevice device :
71 mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) {
72 pw.println(" " + getDeviceString(device));
John Spurlock486b78e2014-07-07 08:37:56 -040073 }
74 }
75
Jason Monka7d92b62015-05-27 10:20:37 -040076 private static String stateToString(int state) {
77 switch (state) {
78 case BluetoothAdapter.STATE_CONNECTED:
79 return "CONNECTED";
80 case BluetoothAdapter.STATE_CONNECTING:
81 return "CONNECTING";
82 case BluetoothAdapter.STATE_DISCONNECTED:
83 return "DISCONNECTED";
84 case BluetoothAdapter.STATE_DISCONNECTING:
85 return "DISCONNECTING";
86 }
87 return "UNKNOWN(" + state + ")";
88 }
89
Jason Monkbe3c5db2015-02-04 13:00:55 -050090 private String getDeviceString(CachedBluetoothDevice device) {
91 return device.getName() + " " + device.getBondState() + " " + device.isConnected();
John Spurlock486b78e2014-07-07 08:37:56 -040092 }
93
Jason Monka7d92b62015-05-27 10:20:37 -040094 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -040095 public void addStateChangedCallback(Callback cb) {
96 mCallbacks.add(cb);
Jason Monk744cf642015-05-19 12:04:41 -040097 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -040098 }
99
100 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -0400101 public void removeStateChangedCallback(Callback cb) {
102 mCallbacks.remove(cb);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400103 }
104
105 @Override
106 public boolean isBluetoothEnabled() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500107 return mEnabled;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400108 }
109
110 @Override
111 public boolean isBluetoothConnected() {
Jason Monka7d92b62015-05-27 10:20:37 -0400112 return mConnectionState == BluetoothAdapter.STATE_CONNECTED;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400113 }
114
115 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -0400116 public boolean isBluetoothConnecting() {
Jason Monka7d92b62015-05-27 10:20:37 -0400117 return mConnectionState == BluetoothAdapter.STATE_CONNECTING;
John Spurlockd1c86e22014-06-01 00:04:53 -0400118 }
119
120 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400121 public void setBluetoothEnabled(boolean enabled) {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500122 if (mLocalBluetoothManager != null) {
123 mLocalBluetoothManager.getBluetoothAdapter().setBluetoothEnabled(enabled);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400124 }
125 }
126
127 @Override
128 public boolean isBluetoothSupported() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500129 return mLocalBluetoothManager != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400130 }
131
John Spurlock486b78e2014-07-07 08:37:56 -0400132 @Override
Jason Monkbe3c5db2015-02-04 13:00:55 -0500133 public void connect(final CachedBluetoothDevice device) {
134 if (mLocalBluetoothManager == null || device == null) return;
135 device.connect(true);
John Spurlock486b78e2014-07-07 08:37:56 -0400136 }
137
138 @Override
Jason Monkbe3c5db2015-02-04 13:00:55 -0500139 public void disconnect(CachedBluetoothDevice device) {
140 if (mLocalBluetoothManager == null || device == null) return;
141 device.disconnect();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400142 }
143
144 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -0400145 public String getLastDeviceName() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500146 return mLastDevice != null ? mLastDevice.getName() : null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400147 }
148
Jason Monkbe3c5db2015-02-04 13:00:55 -0500149 @Override
150 public Collection<CachedBluetoothDevice> getDevices() {
151 return mLocalBluetoothManager != null
152 ? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
153 : null;
Jason Monk4630c892014-12-08 16:36:16 -0500154 }
155
Jason Monkbe3c5db2015-02-04 13:00:55 -0500156 private void updateConnected() {
Jason Monk90970562015-06-19 10:04:49 -0400157 // Make sure our connection state is up to date.
158 int state = mLocalBluetoothManager.getBluetoothAdapter().getConnectionState();
159 if (state != mConnectionState) {
160 mConnectionState = state;
161 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
162 }
Jason Monkbe3c5db2015-02-04 13:00:55 -0500163 if (mLastDevice != null && mLastDevice.isConnected()) {
164 // Our current device is still valid.
165 return;
Jason Monk4ae97d32014-12-17 10:14:33 -0500166 }
Jason Monkbba73172015-08-12 16:17:34 -0400167 mLastDevice = null;
Jason Monkbe3c5db2015-02-04 13:00:55 -0500168 for (CachedBluetoothDevice device : getDevices()) {
169 if (device.isConnected()) {
John Spurlock486b78e2014-07-07 08:37:56 -0400170 mLastDevice = device;
John Spurlock486b78e2014-07-07 08:37:56 -0400171 }
John Spurlock486b78e2014-07-07 08:37:56 -0400172 }
Jason Monkbba73172015-08-12 16:17:34 -0400173 if (mLastDevice == null && mConnectionState == BluetoothAdapter.STATE_CONNECTED) {
174 // If somehow we think we are connected, but have no connected devices, we aren't
175 // connected.
176 mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
177 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
178 }
John Spurlock486b78e2014-07-07 08:37:56 -0400179 }
180
Jason Monkbe3c5db2015-02-04 13:00:55 -0500181 @Override
182 public void onBluetoothStateChanged(int bluetoothState) {
183 mEnabled = bluetoothState == BluetoothAdapter.STATE_ON;
Jason Monk744cf642015-05-19 12:04:41 -0400184 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
John Spurlock486b78e2014-07-07 08:37:56 -0400185 }
186
Jason Monkbe3c5db2015-02-04 13:00:55 -0500187 @Override
188 public void onScanningStateChanged(boolean started) {
189 // Don't care.
190 }
Jason Monk4ae97d32014-12-17 10:14:33 -0500191
Jason Monkbe3c5db2015-02-04 13:00:55 -0500192 @Override
193 public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
194 cachedDevice.registerCallback(this);
195 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400196 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500197 }
Jason Monk4ae97d32014-12-17 10:14:33 -0500198
Jason Monkbe3c5db2015-02-04 13:00:55 -0500199 @Override
200 public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
201 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400202 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500203 }
204
205 @Override
206 public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
207 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400208 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500209 }
210
211 @Override
212 public void onDeviceAttributesChanged() {
213 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400214 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500215 }
216
217 @Override
218 public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500219 mLastDevice = cachedDevice;
220 updateConnected();
Jason Monk90970562015-06-19 10:04:49 -0400221 mConnectionState = state;
Jason Monk744cf642015-05-19 12:04:41 -0400222 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
223 }
224
225 private final class H extends Handler {
226 private static final int MSG_PAIRED_DEVICES_CHANGED = 1;
227 private static final int MSG_STATE_CHANGED = 2;
228
229 @Override
230 public void handleMessage(Message msg) {
231 switch (msg.what) {
232 case MSG_PAIRED_DEVICES_CHANGED:
233 firePairedDevicesChanged();
234 break;
235 case MSG_STATE_CHANGED:
236 fireStateChange();
237 break;
238 }
239 }
240
241 private void firePairedDevicesChanged() {
242 for (BluetoothController.Callback cb : mCallbacks) {
243 cb.onBluetoothDevicesChanged();
244 }
245 }
246
247 private void fireStateChange() {
248 for (BluetoothController.Callback cb : mCallbacks) {
249 fireStateChange(cb);
250 }
251 }
252
253 private void fireStateChange(BluetoothController.Callback cb) {
Jason Monka7d92b62015-05-27 10:20:37 -0400254 cb.onBluetoothStateChange(mEnabled);
Jason Monk744cf642015-05-19 12:04:41 -0400255 }
John Spurlock486b78e2014-07-07 08:37:56 -0400256 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400257}