blob: 15c4afeba5814513a47f1841ebc40c7323cd2d8e [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
Sudheer Shankab6fc9312016-01-27 19:59:03 +000019import android.app.ActivityManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040020import android.bluetooth.BluetoothAdapter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040021import android.content.Context;
Jason Monk744cf642015-05-19 12:04:41 -040022import android.os.Handler;
Jason Monk4ae97d32014-12-17 10:14:33 -050023import android.os.Looper;
Jason Monk744cf642015-05-19 12:04:41 -040024import android.os.Message;
Sudheer Shankab6fc9312016-01-27 19:59:03 +000025import android.os.UserHandle;
26import android.os.UserManager;
John Spurlock486b78e2014-07-07 08:37:56 -040027import android.util.Log;
John Spurlockaf8d6c42014-05-07 17:49:08 -040028
Jason Monkbe3c5db2015-02-04 13:00:55 -050029import com.android.settingslib.bluetooth.BluetoothCallback;
30import com.android.settingslib.bluetooth.CachedBluetoothDevice;
31import com.android.settingslib.bluetooth.LocalBluetoothManager;
John Spurlock486b78e2014-07-07 08:37:56 -040032
33import java.io.FileDescriptor;
34import java.io.PrintWriter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040035import java.util.ArrayList;
Jason Monkbe3c5db2015-02-04 13:00:55 -050036import java.util.Collection;
John Spurlockaf8d6c42014-05-07 17:49:08 -040037
Jason Monkbe3c5db2015-02-04 13:00:55 -050038public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback,
39 CachedBluetoothDevice.Callback {
John Spurlock486b78e2014-07-07 08:37:56 -040040 private static final String TAG = "BluetoothController";
41 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Jason Monk4ae97d32014-12-17 10:14:33 -050042
Jason Monkbe3c5db2015-02-04 13:00:55 -050043 private final LocalBluetoothManager mLocalBluetoothManager;
Sudheer Shankab6fc9312016-01-27 19:59:03 +000044 private final UserManager mUserManager;
45 private final int mCurrentUser;
Jason Monk4ae97d32014-12-17 10:14:33 -050046
John Spurlockd1c86e22014-06-01 00:04:53 -040047 private boolean mEnabled;
Jason Monka7d92b62015-05-27 10:20:37 -040048 private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
Jason Monkbe3c5db2015-02-04 13:00:55 -050049 private CachedBluetoothDevice mLastDevice;
John Spurlockaf8d6c42014-05-07 17:49:08 -040050
Jason Monk744cf642015-05-19 12:04:41 -040051 private final H mHandler = new H();
Jason Monkfac25382016-07-19 14:13:37 -040052 private int mState;
Jason Monk744cf642015-05-19 12:04:41 -040053
Jason Monk4ae97d32014-12-17 10:14:33 -050054 public BluetoothControllerImpl(Context context, Looper bgLooper) {
Jason Monkbe3c5db2015-02-04 13:00:55 -050055 mLocalBluetoothManager = LocalBluetoothManager.getInstance(context, null);
56 if (mLocalBluetoothManager != null) {
Jason Monk744cf642015-05-19 12:04:41 -040057 mLocalBluetoothManager.getEventManager().setReceiverHandler(new Handler(bgLooper));
Jason Monkbe3c5db2015-02-04 13:00:55 -050058 mLocalBluetoothManager.getEventManager().registerCallback(this);
59 onBluetoothStateChanged(
60 mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
John Spurlockaf8d6c42014-05-07 17:49:08 -040061 }
Sudheer Shankab6fc9312016-01-27 19:59:03 +000062 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));
John Spurlockaf8d6c42014-05-07 17:49:08 -040070 }
71
John Spurlock486b78e2014-07-07 08:37:56 -040072 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
73 pw.println("BluetoothController state:");
Jason Monkbe3c5db2015-02-04 13:00:55 -050074 pw.print(" mLocalBluetoothManager="); pw.println(mLocalBluetoothManager);
Jason Monk09389a92015-05-19 16:06:52 -040075 if (mLocalBluetoothManager == null) {
76 return;
77 }
John Spurlock486b78e2014-07-07 08:37:56 -040078 pw.print(" mEnabled="); pw.println(mEnabled);
Jason Monka7d92b62015-05-27 10:20:37 -040079 pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState));
John Spurlock486b78e2014-07-07 08:37:56 -040080 pw.print(" mLastDevice="); pw.println(mLastDevice);
Adrian Roosa4b54862016-06-17 14:28:27 -070081 pw.print(" mCallbacks.size="); pw.println(mHandler.mCallbacks.size());
Jason Monkbe3c5db2015-02-04 13:00:55 -050082 pw.println(" Bluetooth Devices:");
83 for (CachedBluetoothDevice device :
84 mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) {
85 pw.println(" " + getDeviceString(device));
John Spurlock486b78e2014-07-07 08:37:56 -040086 }
87 }
88
Jason Monka7d92b62015-05-27 10:20:37 -040089 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
Jason Monkbe3c5db2015-02-04 13:00:55 -0500103 private String getDeviceString(CachedBluetoothDevice device) {
104 return device.getName() + " " + device.getBondState() + " " + device.isConnected();
John Spurlock486b78e2014-07-07 08:37:56 -0400105 }
106
Jason Monka7d92b62015-05-27 10:20:37 -0400107 @Override
Jason Monk88529052016-11-04 13:29:58 -0400108 public void addCallback(Callback cb) {
Adrian Roosa4b54862016-06-17 14:28:27 -0700109 mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
Jason Monk744cf642015-05-19 12:04:41 -0400110 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400111 }
112
113 @Override
Jason Monk88529052016-11-04 13:29:58 -0400114 public void removeCallback(Callback cb) {
Adrian Roosa4b54862016-06-17 14:28:27 -0700115 mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400116 }
117
118 @Override
119 public boolean isBluetoothEnabled() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500120 return mEnabled;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400121 }
122
123 @Override
Jason Monkfac25382016-07-19 14:13:37 -0400124 public int getBluetoothState() {
125 return mState;
126 }
127
128 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400129 public boolean isBluetoothConnected() {
Jason Monka7d92b62015-05-27 10:20:37 -0400130 return mConnectionState == BluetoothAdapter.STATE_CONNECTED;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400131 }
132
133 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -0400134 public boolean isBluetoothConnecting() {
Jason Monka7d92b62015-05-27 10:20:37 -0400135 return mConnectionState == BluetoothAdapter.STATE_CONNECTING;
John Spurlockd1c86e22014-06-01 00:04:53 -0400136 }
137
138 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400139 public void setBluetoothEnabled(boolean enabled) {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500140 if (mLocalBluetoothManager != null) {
141 mLocalBluetoothManager.getBluetoothAdapter().setBluetoothEnabled(enabled);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400142 }
143 }
144
145 @Override
146 public boolean isBluetoothSupported() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500147 return mLocalBluetoothManager != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400148 }
149
John Spurlock486b78e2014-07-07 08:37:56 -0400150 @Override
Jason Monkbe3c5db2015-02-04 13:00:55 -0500151 public void connect(final CachedBluetoothDevice device) {
152 if (mLocalBluetoothManager == null || device == null) return;
153 device.connect(true);
John Spurlock486b78e2014-07-07 08:37:56 -0400154 }
155
156 @Override
Jason Monkbe3c5db2015-02-04 13:00:55 -0500157 public void disconnect(CachedBluetoothDevice device) {
158 if (mLocalBluetoothManager == null || device == null) return;
159 device.disconnect();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400160 }
161
162 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -0400163 public String getLastDeviceName() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500164 return mLastDevice != null ? mLastDevice.getName() : null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400165 }
166
Jason Monkbe3c5db2015-02-04 13:00:55 -0500167 @Override
168 public Collection<CachedBluetoothDevice> getDevices() {
169 return mLocalBluetoothManager != null
170 ? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
171 : null;
Jason Monk4630c892014-12-08 16:36:16 -0500172 }
173
Jason Monkbe3c5db2015-02-04 13:00:55 -0500174 private void updateConnected() {
Jason Monk90970562015-06-19 10:04:49 -0400175 // 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 }
Jason Monkbe3c5db2015-02-04 13:00:55 -0500181 if (mLastDevice != null && mLastDevice.isConnected()) {
182 // Our current device is still valid.
183 return;
Jason Monk4ae97d32014-12-17 10:14:33 -0500184 }
Jason Monkbba73172015-08-12 16:17:34 -0400185 mLastDevice = null;
Jason Monkbe3c5db2015-02-04 13:00:55 -0500186 for (CachedBluetoothDevice device : getDevices()) {
187 if (device.isConnected()) {
John Spurlock486b78e2014-07-07 08:37:56 -0400188 mLastDevice = device;
John Spurlock486b78e2014-07-07 08:37:56 -0400189 }
John Spurlock486b78e2014-07-07 08:37:56 -0400190 }
Jason Monkbba73172015-08-12 16:17:34 -0400191 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 }
John Spurlock486b78e2014-07-07 08:37:56 -0400197 }
198
Jason Monkbe3c5db2015-02-04 13:00:55 -0500199 @Override
200 public void onBluetoothStateChanged(int bluetoothState) {
Jason Monkfac25382016-07-19 14:13:37 -0400201 mEnabled = bluetoothState == BluetoothAdapter.STATE_ON
202 || bluetoothState == BluetoothAdapter.STATE_TURNING_ON;
203 mState = bluetoothState;
Jason Monk744cf642015-05-19 12:04:41 -0400204 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
John Spurlock486b78e2014-07-07 08:37:56 -0400205 }
206
Jason Monkbe3c5db2015-02-04 13:00:55 -0500207 @Override
208 public void onScanningStateChanged(boolean started) {
209 // Don't care.
210 }
Jason Monk4ae97d32014-12-17 10:14:33 -0500211
Jason Monkbe3c5db2015-02-04 13:00:55 -0500212 @Override
213 public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
214 cachedDevice.registerCallback(this);
215 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400216 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500217 }
Jason Monk4ae97d32014-12-17 10:14:33 -0500218
Jason Monkbe3c5db2015-02-04 13:00:55 -0500219 @Override
220 public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
221 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400222 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500223 }
224
225 @Override
226 public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
227 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400228 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500229 }
230
231 @Override
232 public void onDeviceAttributesChanged() {
233 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400234 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500235 }
236
237 @Override
238 public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500239 mLastDevice = cachedDevice;
240 updateConnected();
Jason Monk90970562015-06-19 10:04:49 -0400241 mConnectionState = state;
Jason Monk744cf642015-05-19 12:04:41 -0400242 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
243 }
244
245 private final class H extends Handler {
Adrian Roosa4b54862016-06-17 14:28:27 -0700246 private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>();
247
Jason Monk744cf642015-05-19 12:04:41 -0400248 private static final int MSG_PAIRED_DEVICES_CHANGED = 1;
249 private static final int MSG_STATE_CHANGED = 2;
Adrian Roosa4b54862016-06-17 14:28:27 -0700250 private static final int MSG_ADD_CALLBACK = 3;
251 private static final int MSG_REMOVE_CALLBACK = 4;
Jason Monk744cf642015-05-19 12:04:41 -0400252
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;
Adrian Roosa4b54862016-06-17 14:28:27 -0700262 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;
Jason Monk744cf642015-05-19 12:04:41 -0400268 }
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) {
Jason Monka7d92b62015-05-27 10:20:37 -0400284 cb.onBluetoothStateChange(mEnabled);
Jason Monk744cf642015-05-19 12:04:41 -0400285 }
John Spurlock486b78e2014-07-07 08:37:56 -0400286 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400287}