| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.systemui.statusbar.policy; |
| |
| import android.app.ActivityManager; |
| import android.bluetooth.BluetoothAdapter; |
| import android.content.Context; |
| import android.os.Handler; |
| import android.os.Looper; |
| import android.os.Message; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.util.Log; |
| |
| import com.android.settingslib.bluetooth.BluetoothCallback; |
| import com.android.settingslib.bluetooth.CachedBluetoothDevice; |
| import com.android.settingslib.bluetooth.LocalBluetoothManager; |
| |
| import java.io.FileDescriptor; |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| |
| public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback, |
| CachedBluetoothDevice.Callback { |
| private static final String TAG = "BluetoothController"; |
| private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); |
| |
| private final LocalBluetoothManager mLocalBluetoothManager; |
| private final UserManager mUserManager; |
| private final int mCurrentUser; |
| |
| private boolean mEnabled; |
| private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; |
| private CachedBluetoothDevice mLastDevice; |
| |
| private final H mHandler = new H(); |
| private int mState; |
| |
| public BluetoothControllerImpl(Context context, Looper bgLooper) { |
| mLocalBluetoothManager = LocalBluetoothManager.getInstance(context, null); |
| if (mLocalBluetoothManager != null) { |
| mLocalBluetoothManager.getEventManager().setReceiverHandler(new Handler(bgLooper)); |
| mLocalBluetoothManager.getEventManager().registerCallback(this); |
| onBluetoothStateChanged( |
| mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState()); |
| } |
| mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); |
| mCurrentUser = ActivityManager.getCurrentUser(); |
| } |
| |
| @Override |
| public boolean canConfigBluetooth() { |
| return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, |
| UserHandle.of(mCurrentUser)); |
| } |
| |
| public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { |
| pw.println("BluetoothController state:"); |
| pw.print(" mLocalBluetoothManager="); pw.println(mLocalBluetoothManager); |
| if (mLocalBluetoothManager == null) { |
| return; |
| } |
| pw.print(" mEnabled="); pw.println(mEnabled); |
| pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState)); |
| pw.print(" mLastDevice="); pw.println(mLastDevice); |
| pw.print(" mCallbacks.size="); pw.println(mHandler.mCallbacks.size()); |
| pw.println(" Bluetooth Devices:"); |
| for (CachedBluetoothDevice device : |
| mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) { |
| pw.println(" " + getDeviceString(device)); |
| } |
| } |
| |
| private static String stateToString(int state) { |
| switch (state) { |
| case BluetoothAdapter.STATE_CONNECTED: |
| return "CONNECTED"; |
| case BluetoothAdapter.STATE_CONNECTING: |
| return "CONNECTING"; |
| case BluetoothAdapter.STATE_DISCONNECTED: |
| return "DISCONNECTED"; |
| case BluetoothAdapter.STATE_DISCONNECTING: |
| return "DISCONNECTING"; |
| } |
| return "UNKNOWN(" + state + ")"; |
| } |
| |
| private String getDeviceString(CachedBluetoothDevice device) { |
| return device.getName() + " " + device.getBondState() + " " + device.isConnected(); |
| } |
| |
| @Override |
| public void addStateChangedCallback(Callback cb) { |
| mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget(); |
| mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); |
| } |
| |
| @Override |
| public void removeStateChangedCallback(Callback cb) { |
| mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget(); |
| } |
| |
| @Override |
| public boolean isBluetoothEnabled() { |
| return mEnabled; |
| } |
| |
| @Override |
| public int getBluetoothState() { |
| return mState; |
| } |
| |
| @Override |
| public boolean isBluetoothConnected() { |
| return mConnectionState == BluetoothAdapter.STATE_CONNECTED; |
| } |
| |
| @Override |
| public boolean isBluetoothConnecting() { |
| return mConnectionState == BluetoothAdapter.STATE_CONNECTING; |
| } |
| |
| @Override |
| public void setBluetoothEnabled(boolean enabled) { |
| if (mLocalBluetoothManager != null) { |
| mLocalBluetoothManager.getBluetoothAdapter().setBluetoothEnabled(enabled); |
| } |
| } |
| |
| @Override |
| public boolean isBluetoothSupported() { |
| return mLocalBluetoothManager != null; |
| } |
| |
| @Override |
| public void connect(final CachedBluetoothDevice device) { |
| if (mLocalBluetoothManager == null || device == null) return; |
| device.connect(true); |
| } |
| |
| @Override |
| public void disconnect(CachedBluetoothDevice device) { |
| if (mLocalBluetoothManager == null || device == null) return; |
| device.disconnect(); |
| } |
| |
| @Override |
| public String getLastDeviceName() { |
| return mLastDevice != null ? mLastDevice.getName() : null; |
| } |
| |
| @Override |
| public Collection<CachedBluetoothDevice> getDevices() { |
| return mLocalBluetoothManager != null |
| ? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy() |
| : null; |
| } |
| |
| private void updateConnected() { |
| // Make sure our connection state is up to date. |
| int state = mLocalBluetoothManager.getBluetoothAdapter().getConnectionState(); |
| if (state != mConnectionState) { |
| mConnectionState = state; |
| mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); |
| } |
| if (mLastDevice != null && mLastDevice.isConnected()) { |
| // Our current device is still valid. |
| return; |
| } |
| mLastDevice = null; |
| for (CachedBluetoothDevice device : getDevices()) { |
| if (device.isConnected()) { |
| mLastDevice = device; |
| } |
| } |
| if (mLastDevice == null && mConnectionState == BluetoothAdapter.STATE_CONNECTED) { |
| // If somehow we think we are connected, but have no connected devices, we aren't |
| // connected. |
| mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; |
| mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); |
| } |
| } |
| |
| @Override |
| public void onBluetoothStateChanged(int bluetoothState) { |
| mEnabled = bluetoothState == BluetoothAdapter.STATE_ON |
| || bluetoothState == BluetoothAdapter.STATE_TURNING_ON; |
| mState = bluetoothState; |
| mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); |
| } |
| |
| @Override |
| public void onScanningStateChanged(boolean started) { |
| // Don't care. |
| } |
| |
| @Override |
| public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { |
| cachedDevice.registerCallback(this); |
| updateConnected(); |
| mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); |
| } |
| |
| @Override |
| public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { |
| updateConnected(); |
| mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); |
| } |
| |
| @Override |
| public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { |
| updateConnected(); |
| mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); |
| } |
| |
| @Override |
| public void onDeviceAttributesChanged() { |
| updateConnected(); |
| mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); |
| } |
| |
| @Override |
| public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { |
| mLastDevice = cachedDevice; |
| updateConnected(); |
| mConnectionState = state; |
| mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); |
| } |
| |
| private final class H extends Handler { |
| private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>(); |
| |
| private static final int MSG_PAIRED_DEVICES_CHANGED = 1; |
| private static final int MSG_STATE_CHANGED = 2; |
| private static final int MSG_ADD_CALLBACK = 3; |
| private static final int MSG_REMOVE_CALLBACK = 4; |
| |
| @Override |
| public void handleMessage(Message msg) { |
| switch (msg.what) { |
| case MSG_PAIRED_DEVICES_CHANGED: |
| firePairedDevicesChanged(); |
| break; |
| case MSG_STATE_CHANGED: |
| fireStateChange(); |
| break; |
| case MSG_ADD_CALLBACK: |
| mCallbacks.add((BluetoothController.Callback) msg.obj); |
| break; |
| case MSG_REMOVE_CALLBACK: |
| mCallbacks.remove((BluetoothController.Callback) msg.obj); |
| break; |
| } |
| } |
| |
| private void firePairedDevicesChanged() { |
| for (BluetoothController.Callback cb : mCallbacks) { |
| cb.onBluetoothDevicesChanged(); |
| } |
| } |
| |
| private void fireStateChange() { |
| for (BluetoothController.Callback cb : mCallbacks) { |
| fireStateChange(cb); |
| } |
| } |
| |
| private void fireStateChange(BluetoothController.Callback cb) { |
| cb.onBluetoothStateChange(mEnabled); |
| } |
| } |
| } |