blob: 6439bea104e6207bb84d3b6a454e86ad1e71f4c2 [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
John Spurlockd1c86e22014-06-01 00:04:53 -040043 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
Jason Monkbe3c5db2015-02-04 13:00:55 -050044 private final LocalBluetoothManager mLocalBluetoothManager;
Sudheer Shankab6fc9312016-01-27 19:59:03 +000045 private final UserManager mUserManager;
46 private final int mCurrentUser;
Jason Monk4ae97d32014-12-17 10:14:33 -050047
John Spurlockd1c86e22014-06-01 00:04:53 -040048 private boolean mEnabled;
Jason Monka7d92b62015-05-27 10:20:37 -040049 private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
Jason Monkbe3c5db2015-02-04 13:00:55 -050050 private CachedBluetoothDevice mLastDevice;
John Spurlockaf8d6c42014-05-07 17:49:08 -040051
Jason Monk744cf642015-05-19 12:04:41 -040052 private final H mHandler = new H();
53
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);
81 pw.print(" mCallbacks.size="); pw.println(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
John Spurlockd1c86e22014-06-01 00:04:53 -0400108 public void addStateChangedCallback(Callback cb) {
109 mCallbacks.add(cb);
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
John Spurlockd1c86e22014-06-01 00:04:53 -0400114 public void removeStateChangedCallback(Callback cb) {
115 mCallbacks.remove(cb);
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
124 public boolean isBluetoothConnected() {
Jason Monka7d92b62015-05-27 10:20:37 -0400125 return mConnectionState == BluetoothAdapter.STATE_CONNECTED;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400126 }
127
128 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -0400129 public boolean isBluetoothConnecting() {
Jason Monka7d92b62015-05-27 10:20:37 -0400130 return mConnectionState == BluetoothAdapter.STATE_CONNECTING;
John Spurlockd1c86e22014-06-01 00:04:53 -0400131 }
132
133 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400134 public void setBluetoothEnabled(boolean enabled) {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500135 if (mLocalBluetoothManager != null) {
136 mLocalBluetoothManager.getBluetoothAdapter().setBluetoothEnabled(enabled);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400137 }
138 }
139
140 @Override
141 public boolean isBluetoothSupported() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500142 return mLocalBluetoothManager != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400143 }
144
John Spurlock486b78e2014-07-07 08:37:56 -0400145 @Override
Jason Monkbe3c5db2015-02-04 13:00:55 -0500146 public void connect(final CachedBluetoothDevice device) {
147 if (mLocalBluetoothManager == null || device == null) return;
148 device.connect(true);
John Spurlock486b78e2014-07-07 08:37:56 -0400149 }
150
151 @Override
Jason Monkbe3c5db2015-02-04 13:00:55 -0500152 public void disconnect(CachedBluetoothDevice device) {
153 if (mLocalBluetoothManager == null || device == null) return;
154 device.disconnect();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400155 }
156
157 @Override
John Spurlockd1c86e22014-06-01 00:04:53 -0400158 public String getLastDeviceName() {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500159 return mLastDevice != null ? mLastDevice.getName() : null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400160 }
161
Jason Monkbe3c5db2015-02-04 13:00:55 -0500162 @Override
163 public Collection<CachedBluetoothDevice> getDevices() {
164 return mLocalBluetoothManager != null
165 ? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
166 : null;
Jason Monk4630c892014-12-08 16:36:16 -0500167 }
168
Jason Monkbe3c5db2015-02-04 13:00:55 -0500169 private void updateConnected() {
Jason Monk90970562015-06-19 10:04:49 -0400170 // Make sure our connection state is up to date.
171 int state = mLocalBluetoothManager.getBluetoothAdapter().getConnectionState();
172 if (state != mConnectionState) {
173 mConnectionState = state;
174 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
175 }
Jason Monkbe3c5db2015-02-04 13:00:55 -0500176 if (mLastDevice != null && mLastDevice.isConnected()) {
177 // Our current device is still valid.
178 return;
Jason Monk4ae97d32014-12-17 10:14:33 -0500179 }
Jason Monkbba73172015-08-12 16:17:34 -0400180 mLastDevice = null;
Jason Monkbe3c5db2015-02-04 13:00:55 -0500181 for (CachedBluetoothDevice device : getDevices()) {
182 if (device.isConnected()) {
John Spurlock486b78e2014-07-07 08:37:56 -0400183 mLastDevice = device;
John Spurlock486b78e2014-07-07 08:37:56 -0400184 }
John Spurlock486b78e2014-07-07 08:37:56 -0400185 }
Jason Monkbba73172015-08-12 16:17:34 -0400186 if (mLastDevice == null && mConnectionState == BluetoothAdapter.STATE_CONNECTED) {
187 // If somehow we think we are connected, but have no connected devices, we aren't
188 // connected.
189 mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
190 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
191 }
John Spurlock486b78e2014-07-07 08:37:56 -0400192 }
193
Jason Monkbe3c5db2015-02-04 13:00:55 -0500194 @Override
195 public void onBluetoothStateChanged(int bluetoothState) {
196 mEnabled = bluetoothState == BluetoothAdapter.STATE_ON;
Jason Monk744cf642015-05-19 12:04:41 -0400197 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
John Spurlock486b78e2014-07-07 08:37:56 -0400198 }
199
Jason Monkbe3c5db2015-02-04 13:00:55 -0500200 @Override
201 public void onScanningStateChanged(boolean started) {
202 // Don't care.
203 }
Jason Monk4ae97d32014-12-17 10:14:33 -0500204
Jason Monkbe3c5db2015-02-04 13:00:55 -0500205 @Override
206 public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
207 cachedDevice.registerCallback(this);
208 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400209 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500210 }
Jason Monk4ae97d32014-12-17 10:14:33 -0500211
Jason Monkbe3c5db2015-02-04 13:00:55 -0500212 @Override
213 public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
214 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400215 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500216 }
217
218 @Override
219 public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
220 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400221 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500222 }
223
224 @Override
225 public void onDeviceAttributesChanged() {
226 updateConnected();
Jason Monk744cf642015-05-19 12:04:41 -0400227 mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
Jason Monkbe3c5db2015-02-04 13:00:55 -0500228 }
229
230 @Override
231 public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
Jason Monkbe3c5db2015-02-04 13:00:55 -0500232 mLastDevice = cachedDevice;
233 updateConnected();
Jason Monk90970562015-06-19 10:04:49 -0400234 mConnectionState = state;
Jason Monk744cf642015-05-19 12:04:41 -0400235 mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
236 }
237
238 private final class H extends Handler {
239 private static final int MSG_PAIRED_DEVICES_CHANGED = 1;
240 private static final int MSG_STATE_CHANGED = 2;
241
242 @Override
243 public void handleMessage(Message msg) {
244 switch (msg.what) {
245 case MSG_PAIRED_DEVICES_CHANGED:
246 firePairedDevicesChanged();
247 break;
248 case MSG_STATE_CHANGED:
249 fireStateChange();
250 break;
251 }
252 }
253
254 private void firePairedDevicesChanged() {
255 for (BluetoothController.Callback cb : mCallbacks) {
256 cb.onBluetoothDevicesChanged();
257 }
258 }
259
260 private void fireStateChange() {
261 for (BluetoothController.Callback cb : mCallbacks) {
262 fireStateChange(cb);
263 }
264 }
265
266 private void fireStateChange(BluetoothController.Callback cb) {
Jason Monka7d92b62015-05-27 10:20:37 -0400267 cb.onBluetoothStateChange(mEnabled);
Jason Monk744cf642015-05-19 12:04:41 -0400268 }
John Spurlock486b78e2014-07-07 08:37:56 -0400269 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400270}