Make QS use SettingsLib's BT code
A couple of changes needed to be made to SettingsLib to support this.
- SettingsLib needed to track ACTION_CONNECTION_STATE_CHANGED
- The summary code needed to move from Settings up into SettingsLib
- Added a getMaxConnectionState to CachedBluetoothDevice
- This simplifies the states of all of the profiles into
one.
Change-Id: I7f828f0038ad0cf39274986ece6d486d545f0286
This commit is contained in:
@@ -76,6 +76,17 @@
|
||||
<string name="bluetooth_connecting">Connecting\u2026</string>
|
||||
<!-- Bluetooth settings. Message when connected to a device. [CHAR LIMIT=40] -->
|
||||
<string name="bluetooth_connected">Connected</string>
|
||||
<!--Bluetooth settings screen, summary text under individual Bluetooth devices when pairing -->
|
||||
<string name="bluetooth_pairing">Pairing\u2026</string>
|
||||
|
||||
<!-- Bluetooth settings. Message when connected to a device, except for phone audio. [CHAR LIMIT=40] -->
|
||||
<string name="bluetooth_connected_no_headset">Connected (no phone)</string>
|
||||
<!-- Bluetooth settings. Message when connected to a device, except for media audio. [CHAR LIMIT=40] -->
|
||||
<string name="bluetooth_connected_no_a2dp">Connected (no media)</string>
|
||||
<!-- Bluetooth settings. Message when connected to a device, except for map. [CHAR LIMIT=40] -->
|
||||
<string name="bluetooth_connected_no_map">Connected (no message access)</string>
|
||||
<!-- Bluetooth settings. Message when connected to a device, except for phone/media audio. [CHAR LIMIT=40] -->
|
||||
<string name="bluetooth_connected_no_headset_no_a2dp">Connected (no phone or media)</string>
|
||||
|
||||
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the A2DP profile. -->
|
||||
<string name="bluetooth_profile_a2dp">Media audio</string>
|
||||
|
||||
@@ -27,4 +27,5 @@ public interface BluetoothCallback {
|
||||
void onDeviceAdded(CachedBluetoothDevice cachedDevice);
|
||||
void onDeviceDeleted(CachedBluetoothDevice cachedDevice);
|
||||
void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState);
|
||||
void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state);
|
||||
}
|
||||
|
||||
@@ -81,6 +81,9 @@ public final class BluetoothEventManager {
|
||||
|
||||
// Bluetooth on/off broadcasts
|
||||
addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());
|
||||
// Generic connected/not broadcast
|
||||
addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED,
|
||||
new ConnectionStateChangedHandler());
|
||||
|
||||
// Discovery broadcasts
|
||||
addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
|
||||
@@ -183,8 +186,6 @@ public final class BluetoothEventManager {
|
||||
cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
|
||||
Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
|
||||
+ cachedDevice);
|
||||
// callback to UI to create Preference for new device
|
||||
dispatchDeviceAdded(cachedDevice);
|
||||
}
|
||||
cachedDevice.setRssi(rssi);
|
||||
cachedDevice.setBtClass(btClass);
|
||||
@@ -193,7 +194,25 @@ public final class BluetoothEventManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
|
||||
private class ConnectionStateChangedHandler implements Handler {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent, BluetoothDevice device) {
|
||||
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
|
||||
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
|
||||
BluetoothAdapter.ERROR);
|
||||
dispatchConnectionStateChanged(cachedDevice, state);
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||
synchronized (mCallbacks) {
|
||||
for (BluetoothCallback callback : mCallbacks) {
|
||||
callback.onConnectionStateChanged(cachedDevice, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
|
||||
synchronized (mCallbacks) {
|
||||
for (BluetoothCallback callback : mCallbacks) {
|
||||
callback.onDeviceAdded(cachedDevice);
|
||||
|
||||
@@ -28,6 +28,8 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -784,4 +786,62 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
|
||||
setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_ALLOWED);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxConnectionState() {
|
||||
int maxState = BluetoothProfile.STATE_DISCONNECTED;
|
||||
for (LocalBluetoothProfile profile : getProfiles()) {
|
||||
int connectionStatus = getProfileConnectionState(profile);
|
||||
if (connectionStatus > maxState) {
|
||||
maxState = connectionStatus;
|
||||
}
|
||||
}
|
||||
return maxState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource for string that discribes the connection state of this device.
|
||||
*/
|
||||
public int getConnectionSummary() {
|
||||
boolean profileConnected = false; // at least one profile is connected
|
||||
boolean a2dpNotConnected = false; // A2DP is preferred but not connected
|
||||
boolean headsetNotConnected = false; // Headset is preferred but not connected
|
||||
|
||||
for (LocalBluetoothProfile profile : getProfiles()) {
|
||||
int connectionStatus = getProfileConnectionState(profile);
|
||||
|
||||
switch (connectionStatus) {
|
||||
case BluetoothProfile.STATE_CONNECTING:
|
||||
case BluetoothProfile.STATE_DISCONNECTING:
|
||||
return Utils.getConnectionStateSummary(connectionStatus);
|
||||
|
||||
case BluetoothProfile.STATE_CONNECTED:
|
||||
profileConnected = true;
|
||||
break;
|
||||
|
||||
case BluetoothProfile.STATE_DISCONNECTED:
|
||||
if (profile.isProfileReady()) {
|
||||
if (profile instanceof A2dpProfile) {
|
||||
a2dpNotConnected = true;
|
||||
} else if (profile instanceof HeadsetProfile) {
|
||||
headsetNotConnected = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (profileConnected) {
|
||||
if (a2dpNotConnected && headsetNotConnected) {
|
||||
return R.string.bluetooth_connected_no_headset_no_a2dp;
|
||||
} else if (a2dpNotConnected) {
|
||||
return R.string.bluetooth_connected_no_a2dp;
|
||||
} else if (headsetNotConnected) {
|
||||
return R.string.bluetooth_connected_no_headset;
|
||||
} else {
|
||||
return R.string.bluetooth_connected;
|
||||
}
|
||||
}
|
||||
|
||||
return getBondState() == BluetoothDevice.BOND_BONDING ? R.string.bluetooth_pairing : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,11 @@ public final class CachedBluetoothDeviceManager {
|
||||
private Context mContext;
|
||||
private final List<CachedBluetoothDevice> mCachedDevices =
|
||||
new ArrayList<CachedBluetoothDevice>();
|
||||
private final LocalBluetoothManager mBtManager;
|
||||
|
||||
CachedBluetoothDeviceManager(Context context) {
|
||||
CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
|
||||
mContext = context;
|
||||
mBtManager = localBtManager;
|
||||
}
|
||||
|
||||
public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
|
||||
@@ -88,6 +90,7 @@ public final class CachedBluetoothDeviceManager {
|
||||
profileManager, device);
|
||||
synchronized (mCachedDevices) {
|
||||
mCachedDevices.add(newDevice);
|
||||
mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
|
||||
}
|
||||
return newDevice;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,10 @@ public final class LocalBluetoothAdapter {
|
||||
return mAdapter.isEnabled();
|
||||
}
|
||||
|
||||
public int getConnectionState() {
|
||||
return mAdapter.getConnectionState();
|
||||
}
|
||||
|
||||
public void setDiscoverableTimeout(int timeout) {
|
||||
mAdapter.setDiscoverableTimeout(timeout);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public final class LocalBluetoothManager {
|
||||
mContext = context;
|
||||
mLocalAdapter = adapter;
|
||||
|
||||
mCachedDeviceManager = new CachedBluetoothDeviceManager(context);
|
||||
mCachedDeviceManager = new CachedBluetoothDeviceManager(context, this);
|
||||
mEventManager = new BluetoothEventManager(mLocalAdapter,
|
||||
mCachedDeviceManager, context);
|
||||
mProfileManager = new LocalBluetoothProfileManager(context,
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
<!-- Networking and telephony -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.qs.tiles;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
@@ -23,13 +25,14 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.qs.QSDetailItems;
|
||||
import com.android.systemui.qs.QSDetailItems.Item;
|
||||
import com.android.systemui.qs.QSTile;
|
||||
import com.android.systemui.statusbar.policy.BluetoothController;
|
||||
import com.android.systemui.statusbar.policy.BluetoothController.PairedDevice;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/** Quick settings tile: Bluetooth **/
|
||||
@@ -143,7 +146,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
|
||||
refreshState();
|
||||
}
|
||||
@Override
|
||||
public void onBluetoothPairedDevicesChanged() {
|
||||
public void onBluetoothDevicesChanged() {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -199,19 +202,21 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
|
||||
private void updateItems() {
|
||||
if (mItems == null) return;
|
||||
Item[] items = null;
|
||||
final Set<PairedDevice> devices = mController.getPairedDevices();
|
||||
final Collection<CachedBluetoothDevice> devices = mController.getDevices();
|
||||
if (devices != null) {
|
||||
items = new Item[devices.size()];
|
||||
items = new Item[getBondedCount(devices)];
|
||||
int i = 0;
|
||||
for (PairedDevice device : devices) {
|
||||
for (CachedBluetoothDevice device : devices) {
|
||||
if (device.getBondState() == BluetoothDevice.BOND_NONE) continue;
|
||||
final Item item = new Item();
|
||||
item.icon = R.drawable.ic_qs_bluetooth_on;
|
||||
item.line1 = device.name;
|
||||
if (device.state == PairedDevice.STATE_CONNECTED) {
|
||||
item.line1 = device.getName();
|
||||
int state = device.getMaxConnectionState();
|
||||
if (state == BluetoothProfile.STATE_CONNECTED) {
|
||||
item.icon = R.drawable.ic_qs_bluetooth_connected;
|
||||
item.line2 = mContext.getString(R.string.quick_settings_connected);
|
||||
item.canDisconnect = true;
|
||||
} else if (device.state == PairedDevice.STATE_CONNECTING) {
|
||||
} else if (state == BluetoothProfile.STATE_CONNECTING) {
|
||||
item.icon = R.drawable.ic_qs_bluetooth_connecting;
|
||||
item.line2 = mContext.getString(R.string.quick_settings_connecting);
|
||||
}
|
||||
@@ -222,11 +227,22 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
|
||||
mItems.setItems(items);
|
||||
}
|
||||
|
||||
private int getBondedCount(Collection<CachedBluetoothDevice> devices) {
|
||||
int ct = 0;
|
||||
for (CachedBluetoothDevice device : devices) {
|
||||
if (device.getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
ct++;
|
||||
}
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetailItemClick(Item item) {
|
||||
if (item == null || item.tag == null) return;
|
||||
final PairedDevice device = (PairedDevice) item.tag;
|
||||
if (device != null && device.state == PairedDevice.STATE_DISCONNECTED) {
|
||||
final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
|
||||
if (device != null && device.getMaxConnectionState()
|
||||
== BluetoothProfile.STATE_DISCONNECTED) {
|
||||
mController.connect(device);
|
||||
}
|
||||
}
|
||||
@@ -234,7 +250,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
|
||||
@Override
|
||||
public void onDetailItemDisconnect(Item item) {
|
||||
if (item == null || item.tag == null) return;
|
||||
final PairedDevice device = (PairedDevice) item.tag;
|
||||
final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
|
||||
if (device != null) {
|
||||
mController.disconnect(device);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import java.util.Set;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface BluetoothController {
|
||||
void addStateChangedCallback(Callback callback);
|
||||
@@ -28,32 +30,12 @@ public interface BluetoothController {
|
||||
boolean isBluetoothConnecting();
|
||||
String getLastDeviceName();
|
||||
void setBluetoothEnabled(boolean enabled);
|
||||
Set<PairedDevice> getPairedDevices();
|
||||
void connect(PairedDevice device);
|
||||
void disconnect(PairedDevice device);
|
||||
Collection<CachedBluetoothDevice> getDevices();
|
||||
void connect(CachedBluetoothDevice device);
|
||||
void disconnect(CachedBluetoothDevice device);
|
||||
|
||||
public interface Callback {
|
||||
void onBluetoothStateChange(boolean enabled, boolean connecting);
|
||||
void onBluetoothPairedDevicesChanged();
|
||||
}
|
||||
|
||||
public static final class PairedDevice {
|
||||
public static int STATE_DISCONNECTED = 0;
|
||||
public static int STATE_CONNECTING = 1;
|
||||
public static int STATE_CONNECTED = 2;
|
||||
public static int STATE_DISCONNECTING = 3;
|
||||
|
||||
public String id;
|
||||
public String name;
|
||||
public int state = STATE_DISCONNECTED;
|
||||
public Object tag;
|
||||
|
||||
public static String stateToString(int state) {
|
||||
if (state == STATE_DISCONNECTED) return "STATE_DISCONNECTED";
|
||||
if (state == STATE_CONNECTING) return "STATE_CONNECTING";
|
||||
if (state == STATE_CONNECTED) return "STATE_CONNECTED";
|
||||
if (state == STATE_DISCONNECTING) return "STATE_DISCONNECTING";
|
||||
return "UNKNOWN";
|
||||
}
|
||||
void onBluetoothDevicesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,138 +16,57 @@
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import static android.bluetooth.BluetoothAdapter.ERROR;
|
||||
import static com.android.systemui.statusbar.policy.BluetoothUtil.connectionStateToString;
|
||||
import static com.android.systemui.statusbar.policy.BluetoothUtil.deviceToString;
|
||||
import static com.android.systemui.statusbar.policy.BluetoothUtil.profileToString;
|
||||
import static com.android.systemui.statusbar.policy.BluetoothUtil.uuidToProfile;
|
||||
import static com.android.systemui.statusbar.policy.BluetoothUtil.uuidToString;
|
||||
import static com.android.systemui.statusbar.policy.BluetoothUtil.uuidsToString;
|
||||
|
||||
import android.bluetooth.BluetoothA2dp;
|
||||
import android.bluetooth.BluetoothA2dpSink;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
import android.bluetooth.BluetoothHeadsetClient;
|
||||
import android.bluetooth.BluetoothInputDevice;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.bluetooth.BluetoothMap;
|
||||
import android.bluetooth.BluetoothPan;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothProfile.ServiceListener;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelUuid;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.systemui.statusbar.policy.BluetoothUtil.Profile;
|
||||
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.Set;
|
||||
import java.util.Collection;
|
||||
|
||||
public class BluetoothControllerImpl implements BluetoothController {
|
||||
public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback,
|
||||
CachedBluetoothDevice.Callback {
|
||||
private static final String TAG = "BluetoothController";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
// This controls the order in which we check the states. Since a device can only have
|
||||
// one state on screen, but can have multiple profiles, the later states override the
|
||||
// value of earlier states. So if a device has a profile in CONNECTING and one in
|
||||
// CONNECTED, it will show as CONNECTED, theoretically this shouldn't really happen often,
|
||||
// but seemed worth noting.
|
||||
private static final int[] CONNECTION_STATES = {
|
||||
BluetoothProfile.STATE_DISCONNECTED,
|
||||
BluetoothProfile.STATE_DISCONNECTING,
|
||||
BluetoothProfile.STATE_CONNECTING,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
};
|
||||
// Update all the BT device states.
|
||||
private static final int MSG_UPDATE_CONNECTION_STATES = 1;
|
||||
// Update just one BT device.
|
||||
private static final int MSG_UPDATE_SINGLE_CONNECTION_STATE = 2;
|
||||
// Update whether devices are bonded or not.
|
||||
private static final int MSG_UPDATE_BONDED_DEVICES = 3;
|
||||
|
||||
private static final int MSG_ADD_PROFILE = 4;
|
||||
private static final int MSG_REM_PROFILE = 5;
|
||||
|
||||
private final Context mContext;
|
||||
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
|
||||
private final BluetoothAdapter mAdapter;
|
||||
private final Receiver mReceiver = new Receiver();
|
||||
private final ArrayMap<BluetoothDevice, DeviceInfo> mDeviceInfo = new ArrayMap<>();
|
||||
private final SparseArray<BluetoothProfile> mProfiles = new SparseArray<>();
|
||||
|
||||
private final H mHandler;
|
||||
private final LocalBluetoothManager mLocalBluetoothManager;
|
||||
|
||||
private boolean mEnabled;
|
||||
private boolean mConnecting;
|
||||
private BluetoothDevice mLastDevice;
|
||||
private CachedBluetoothDevice mLastDevice;
|
||||
|
||||
public BluetoothControllerImpl(Context context, Looper bgLooper) {
|
||||
mContext = context;
|
||||
mHandler = new H(bgLooper);
|
||||
|
||||
final BluetoothManager bluetoothManager =
|
||||
(BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
mAdapter = bluetoothManager.getAdapter();
|
||||
if (mAdapter == null) {
|
||||
Log.w(TAG, "Default BT adapter not found");
|
||||
return;
|
||||
mLocalBluetoothManager = LocalBluetoothManager.getInstance(context, null);
|
||||
if (mLocalBluetoothManager != null) {
|
||||
mLocalBluetoothManager.getEventManager().registerCallback(this);
|
||||
onBluetoothStateChanged(
|
||||
mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
|
||||
}
|
||||
|
||||
mReceiver.register();
|
||||
setAdapterState(mAdapter.getState());
|
||||
updateBondedDevices();
|
||||
bindAllProfiles();
|
||||
}
|
||||
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("BluetoothController state:");
|
||||
pw.print(" mAdapter="); pw.println(mAdapter);
|
||||
pw.print(" mLocalBluetoothManager="); pw.println(mLocalBluetoothManager);
|
||||
pw.print(" mEnabled="); pw.println(mEnabled);
|
||||
pw.print(" mConnecting="); pw.println(mConnecting);
|
||||
pw.print(" mLastDevice="); pw.println(mLastDevice);
|
||||
pw.print(" mCallbacks.size="); pw.println(mCallbacks.size());
|
||||
pw.print(" mProfiles="); pw.println(profilesToString(mProfiles));
|
||||
pw.print(" mDeviceInfo.size="); pw.println(mDeviceInfo.size());
|
||||
for (int i = 0; i < mDeviceInfo.size(); i++) {
|
||||
final BluetoothDevice device = mDeviceInfo.keyAt(i);
|
||||
final DeviceInfo info = mDeviceInfo.valueAt(i);
|
||||
pw.print(" "); pw.print(deviceToString(device));
|
||||
pw.print('('); pw.print(uuidsToString(device)); pw.print(')');
|
||||
pw.print(" "); pw.println(infoToString(info));
|
||||
pw.println(" Bluetooth Devices:");
|
||||
for (CachedBluetoothDevice device :
|
||||
mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) {
|
||||
pw.println(" " + getDeviceString(device));
|
||||
}
|
||||
}
|
||||
|
||||
private static String infoToString(DeviceInfo info) {
|
||||
return info == null ? null : ("connectionState=" +
|
||||
connectionStateToString(CONNECTION_STATES[info.connectionStateIndex])
|
||||
+ ",bonded=" + info.bonded + ",profiles="
|
||||
+ profilesToString(info.connectedProfiles));
|
||||
}
|
||||
|
||||
private static String profilesToString(SparseArray<?> profiles) {
|
||||
final int N = profiles.size();
|
||||
final StringBuffer buffer = new StringBuffer();
|
||||
buffer.append('[');
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (i != 0) {
|
||||
buffer.append(',');
|
||||
}
|
||||
buffer.append(BluetoothUtil.profileToString(profiles.keyAt(i)));
|
||||
}
|
||||
buffer.append(']');
|
||||
return buffer.toString();
|
||||
private String getDeviceString(CachedBluetoothDevice device) {
|
||||
return device.getName() + " " + device.getBondState() + " " + device.isConnected();
|
||||
}
|
||||
|
||||
public void addStateChangedCallback(Callback cb) {
|
||||
@@ -162,266 +81,63 @@ public class BluetoothControllerImpl implements BluetoothController {
|
||||
|
||||
@Override
|
||||
public boolean isBluetoothEnabled() {
|
||||
return mAdapter != null && mAdapter.isEnabled();
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBluetoothConnected() {
|
||||
return mAdapter != null
|
||||
&& mAdapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED;
|
||||
return mLocalBluetoothManager != null
|
||||
&& mLocalBluetoothManager.getBluetoothAdapter().getConnectionState()
|
||||
== BluetoothAdapter.STATE_CONNECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBluetoothConnecting() {
|
||||
return mAdapter != null
|
||||
&& mAdapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTING;
|
||||
return mConnecting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBluetoothEnabled(boolean enabled) {
|
||||
if (mAdapter != null) {
|
||||
if (enabled) {
|
||||
mAdapter.enable();
|
||||
} else {
|
||||
mAdapter.disable();
|
||||
}
|
||||
if (mLocalBluetoothManager != null) {
|
||||
mLocalBluetoothManager.getBluetoothAdapter().setBluetoothEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBluetoothSupported() {
|
||||
return mAdapter != null;
|
||||
return mLocalBluetoothManager != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySet<PairedDevice> getPairedDevices() {
|
||||
final ArraySet<PairedDevice> rt = new ArraySet<>();
|
||||
for (int i = 0; i < mDeviceInfo.size(); i++) {
|
||||
final BluetoothDevice device = mDeviceInfo.keyAt(i);
|
||||
final DeviceInfo info = mDeviceInfo.valueAt(i);
|
||||
if (!info.bonded) continue;
|
||||
final PairedDevice paired = new PairedDevice();
|
||||
paired.id = device.getAddress();
|
||||
paired.tag = device;
|
||||
paired.name = device.getAliasName();
|
||||
paired.state = connectionStateToPairedDeviceState(info.connectionStateIndex);
|
||||
rt.add(paired);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
private static int connectionStateToPairedDeviceState(int index) {
|
||||
int state = CONNECTION_STATES[index];
|
||||
if (state == BluetoothAdapter.STATE_CONNECTED) return PairedDevice.STATE_CONNECTED;
|
||||
if (state == BluetoothAdapter.STATE_CONNECTING) return PairedDevice.STATE_CONNECTING;
|
||||
if (state == BluetoothAdapter.STATE_DISCONNECTING) return PairedDevice.STATE_DISCONNECTING;
|
||||
return PairedDevice.STATE_DISCONNECTED;
|
||||
public void connect(final CachedBluetoothDevice device) {
|
||||
if (mLocalBluetoothManager == null || device == null) return;
|
||||
device.connect(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(final PairedDevice pd) {
|
||||
connect(pd, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(PairedDevice pd) {
|
||||
connect(pd, false);
|
||||
}
|
||||
|
||||
private void connect(PairedDevice pd, final boolean connect) {
|
||||
if (mAdapter == null || pd == null || pd.tag == null) return;
|
||||
final BluetoothDevice device = (BluetoothDevice) pd.tag;
|
||||
final DeviceInfo info = mDeviceInfo.get(device);
|
||||
final String action = connect ? "connect" : "disconnect";
|
||||
if (DEBUG) Log.d(TAG, action + " " + deviceToString(device));
|
||||
final ParcelUuid[] uuids = device.getUuids();
|
||||
if (uuids == null) {
|
||||
Log.w(TAG, "No uuids returned, aborting " + action + " for " + deviceToString(device));
|
||||
return;
|
||||
}
|
||||
SparseArray<Boolean> profiles = new SparseArray<>();
|
||||
if (connect) {
|
||||
// When connecting add every profile we can recognize by uuid.
|
||||
for (ParcelUuid uuid : uuids) {
|
||||
final int profile = uuidToProfile(uuid);
|
||||
if (profile == 0) {
|
||||
Log.w(TAG, "Device " + deviceToString(device) + " has an unsupported uuid: "
|
||||
+ uuidToString(uuid));
|
||||
continue;
|
||||
}
|
||||
final boolean connected = info.connectedProfiles.get(profile, false);
|
||||
if (!connected) {
|
||||
profiles.put(profile, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// When disconnecting, just add every profile we know they are connected to.
|
||||
profiles = info.connectedProfiles;
|
||||
}
|
||||
for (int i = 0; i < profiles.size(); i++) {
|
||||
final int profile = profiles.keyAt(i);
|
||||
if (mProfiles.indexOfKey(profile) >= 0) {
|
||||
final Profile p = BluetoothUtil.getProfile(mProfiles.get(profile));
|
||||
final boolean ok = connect ? p.connect(device) : p.disconnect(device);
|
||||
if (DEBUG) Log.d(TAG, action + " " + profileToString(profile) + " "
|
||||
+ (ok ? "succeeded" : "failed"));
|
||||
} else {
|
||||
Log.w(TAG, "Unable get get Profile for " + profileToString(profile));
|
||||
}
|
||||
}
|
||||
public void disconnect(CachedBluetoothDevice device) {
|
||||
if (mLocalBluetoothManager == null || device == null) return;
|
||||
device.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastDeviceName() {
|
||||
return mLastDevice != null ? mLastDevice.getAliasName() : null;
|
||||
return mLastDevice != null ? mLastDevice.getName() : null;
|
||||
}
|
||||
|
||||
private void updateBondedDevices() {
|
||||
mHandler.removeMessages(MSG_UPDATE_BONDED_DEVICES);
|
||||
mHandler.sendEmptyMessage(MSG_UPDATE_BONDED_DEVICES);
|
||||
}
|
||||
|
||||
private void updateConnectionStates() {
|
||||
mHandler.removeMessages(MSG_UPDATE_CONNECTION_STATES);
|
||||
mHandler.removeMessages(MSG_UPDATE_SINGLE_CONNECTION_STATE);
|
||||
mHandler.sendEmptyMessage(MSG_UPDATE_CONNECTION_STATES);
|
||||
}
|
||||
|
||||
private void updateConnectionState(BluetoothDevice device, int profile, int state) {
|
||||
if (mHandler.hasMessages(MSG_UPDATE_CONNECTION_STATES)) {
|
||||
// If we are about to update all the devices, then we don't need to update this one.
|
||||
return;
|
||||
}
|
||||
mHandler.obtainMessage(MSG_UPDATE_SINGLE_CONNECTION_STATE, profile, state, device)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
private void handleUpdateBondedDevices() {
|
||||
if (mAdapter == null) return;
|
||||
final Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
|
||||
for (DeviceInfo info : mDeviceInfo.values()) {
|
||||
info.bonded = false;
|
||||
}
|
||||
int bondedCount = 0;
|
||||
BluetoothDevice lastBonded = null;
|
||||
if (bondedDevices != null) {
|
||||
for (BluetoothDevice bondedDevice : bondedDevices) {
|
||||
final boolean bonded = bondedDevice.getBondState() != BluetoothDevice.BOND_NONE;
|
||||
updateInfo(bondedDevice).bonded = bonded;
|
||||
if (bonded) {
|
||||
bondedCount++;
|
||||
lastBonded = bondedDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mLastDevice == null && bondedCount == 1) {
|
||||
mLastDevice = lastBonded;
|
||||
}
|
||||
updateConnectionStates();
|
||||
firePairedDevicesChanged();
|
||||
}
|
||||
|
||||
private void handleUpdateConnectionStates() {
|
||||
final int N = mDeviceInfo.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
BluetoothDevice device = mDeviceInfo.keyAt(i);
|
||||
DeviceInfo info = updateInfo(device);
|
||||
info.connectionStateIndex = 0;
|
||||
info.connectedProfiles.clear();
|
||||
for (int j = 0; j < mProfiles.size(); j++) {
|
||||
int state = mProfiles.valueAt(j).getConnectionState(device);
|
||||
handleUpdateConnectionState(device, mProfiles.keyAt(j), state);
|
||||
}
|
||||
}
|
||||
handleConnectionChange();
|
||||
firePairedDevicesChanged();
|
||||
}
|
||||
|
||||
private void handleUpdateConnectionState(BluetoothDevice device, int profile, int state) {
|
||||
if (DEBUG) Log.d(TAG, "updateConnectionState " + BluetoothUtil.deviceToString(device)
|
||||
+ " " + BluetoothUtil.profileToString(profile)
|
||||
+ " " + BluetoothUtil.connectionStateToString(state));
|
||||
DeviceInfo info = updateInfo(device);
|
||||
int stateIndex = 0;
|
||||
for (int i = 0; i < CONNECTION_STATES.length; i++) {
|
||||
if (CONNECTION_STATES[i] == state) {
|
||||
stateIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
info.profileStates.put(profile, stateIndex);
|
||||
|
||||
info.connectionStateIndex = 0;
|
||||
final int N = info.profileStates.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (info.profileStates.valueAt(i) > info.connectionStateIndex) {
|
||||
info.connectionStateIndex = info.profileStates.valueAt(i);
|
||||
}
|
||||
}
|
||||
if (state == BluetoothProfile.STATE_CONNECTED) {
|
||||
info.connectedProfiles.put(profile, true);
|
||||
} else {
|
||||
info.connectedProfiles.remove(profile);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleConnectionChange() {
|
||||
// If we are no longer connected to the current device, see if we are connected to
|
||||
// something else, so we don't display a name we aren't connected to.
|
||||
if (mLastDevice != null &&
|
||||
CONNECTION_STATES[mDeviceInfo.get(mLastDevice).connectionStateIndex]
|
||||
!= BluetoothProfile.STATE_CONNECTED) {
|
||||
// Make sure we don't keep this device while it isn't connected.
|
||||
mLastDevice = null;
|
||||
// Look for anything else connected.
|
||||
final int size = mDeviceInfo.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
BluetoothDevice device = mDeviceInfo.keyAt(i);
|
||||
DeviceInfo info = mDeviceInfo.valueAt(i);
|
||||
if (CONNECTION_STATES[info.connectionStateIndex]
|
||||
== BluetoothProfile.STATE_CONNECTED) {
|
||||
mLastDevice = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindAllProfiles() {
|
||||
// Note: This needs to contain all of the types that can be returned by BluetoothUtil
|
||||
// otherwise we can't find the profiles we need when we connect/disconnect.
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP_SINK);
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.AVRCP_CONTROLLER);
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET);
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET_CLIENT);
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.INPUT_DEVICE);
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.MAP);
|
||||
mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.PAN);
|
||||
// Note Health is not in this list because health devices aren't 'connected'.
|
||||
// If profiles are expanded to use more than just connection state and connect/disconnect
|
||||
// then it should be added.
|
||||
@Override
|
||||
public Collection<CachedBluetoothDevice> getDevices() {
|
||||
return mLocalBluetoothManager != null
|
||||
? mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
|
||||
: null;
|
||||
}
|
||||
|
||||
private void firePairedDevicesChanged() {
|
||||
for (Callback cb : mCallbacks) {
|
||||
cb.onBluetoothPairedDevicesChanged();
|
||||
cb.onBluetoothDevicesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void setAdapterState(int adapterState) {
|
||||
final boolean enabled = adapterState == BluetoothAdapter.STATE_ON;
|
||||
if (mEnabled == enabled) return;
|
||||
mEnabled = enabled;
|
||||
fireStateChange();
|
||||
}
|
||||
|
||||
private void setConnecting(boolean connecting) {
|
||||
if (mConnecting == connecting) return;
|
||||
mConnecting = connecting;
|
||||
fireStateChange();
|
||||
}
|
||||
|
||||
private void fireStateChange() {
|
||||
for (Callback cb : mCallbacks) {
|
||||
fireStateChange(cb);
|
||||
@@ -432,141 +148,59 @@ public class BluetoothControllerImpl implements BluetoothController {
|
||||
cb.onBluetoothStateChange(mEnabled, mConnecting);
|
||||
}
|
||||
|
||||
private static int getProfileFromAction(String action) {
|
||||
if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
return BluetoothProfile.A2DP;
|
||||
} else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
return BluetoothProfile.HEADSET;
|
||||
} else if (BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
return BluetoothProfile.A2DP_SINK;
|
||||
} else if (BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
return BluetoothProfile.HEADSET_CLIENT;
|
||||
} else if (BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
return BluetoothProfile.INPUT_DEVICE;
|
||||
} else if (BluetoothMap.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
return BluetoothProfile.MAP;
|
||||
} else if (BluetoothPan.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
|
||||
return BluetoothProfile.PAN;
|
||||
private void updateConnected() {
|
||||
if (mLastDevice != null && mLastDevice.isConnected()) {
|
||||
// Our current device is still valid.
|
||||
return;
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "Unknown action " + action);
|
||||
return -1;
|
||||
}
|
||||
|
||||
private final ServiceListener mProfileListener = new ServiceListener() {
|
||||
@Override
|
||||
public void onServiceDisconnected(int profile) {
|
||||
if (DEBUG) Log.d(TAG, "Disconnected from " + BluetoothUtil.profileToString(profile));
|
||||
// We lost a profile, don't do any updates until it gets removed.
|
||||
mHandler.removeMessages(MSG_UPDATE_CONNECTION_STATES);
|
||||
mHandler.removeMessages(MSG_UPDATE_SINGLE_CONNECTION_STATE);
|
||||
mHandler.obtainMessage(MSG_REM_PROFILE, profile, 0).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||
if (DEBUG) Log.d(TAG, "Connected to " + BluetoothUtil.profileToString(profile));
|
||||
mHandler.obtainMessage(MSG_ADD_PROFILE, profile, 0, proxy).sendToTarget();
|
||||
}
|
||||
};
|
||||
|
||||
private final class Receiver extends BroadcastReceiver {
|
||||
public void register() {
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
|
||||
filter.addAction(BluetoothDevice.ACTION_ALIAS_CHANGED);
|
||||
filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
|
||||
mContext.registerReceiver(this, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
|
||||
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
|
||||
setAdapterState(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, ERROR));
|
||||
updateBondedDevices();
|
||||
if (DEBUG) Log.d(TAG, "ACTION_STATE_CHANGED " + mEnabled);
|
||||
} else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
|
||||
updateInfo(device);
|
||||
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
|
||||
ERROR);
|
||||
for (CachedBluetoothDevice device : getDevices()) {
|
||||
if (device.isConnected()) {
|
||||
mLastDevice = device;
|
||||
if (DEBUG) Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGED "
|
||||
+ connectionStateToString(state) + " " + deviceToString(device));
|
||||
setConnecting(state == BluetoothAdapter.STATE_CONNECTING);
|
||||
} else if (action.equals(BluetoothDevice.ACTION_ALIAS_CHANGED)) {
|
||||
updateInfo(device);
|
||||
mLastDevice = device;
|
||||
} else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
|
||||
if (DEBUG) Log.d(TAG, "ACTION_BOND_STATE_CHANGED " + device);
|
||||
updateBondedDevices();
|
||||
} else {
|
||||
int profile = getProfileFromAction(intent.getAction());
|
||||
int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
|
||||
if (DEBUG) Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGE "
|
||||
+ BluetoothUtil.profileToString(profile)
|
||||
+ " " + BluetoothUtil.connectionStateToString(state));
|
||||
if ((profile != -1) && (state != -1)) {
|
||||
updateConnectionState(device, profile, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DeviceInfo updateInfo(BluetoothDevice device) {
|
||||
DeviceInfo info = mDeviceInfo.get(device);
|
||||
info = info != null ? info : new DeviceInfo();
|
||||
mDeviceInfo.put(device, info);
|
||||
return info;
|
||||
@Override
|
||||
public void onBluetoothStateChanged(int bluetoothState) {
|
||||
mEnabled = bluetoothState == BluetoothAdapter.STATE_ON;
|
||||
fireStateChange();
|
||||
}
|
||||
|
||||
private class H extends Handler {
|
||||
public H(Looper l) {
|
||||
super(l);
|
||||
}
|
||||
@Override
|
||||
public void onScanningStateChanged(boolean started) {
|
||||
// Don't care.
|
||||
}
|
||||
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_UPDATE_CONNECTION_STATES:
|
||||
handleUpdateConnectionStates();
|
||||
firePairedDevicesChanged();
|
||||
break;
|
||||
case MSG_UPDATE_SINGLE_CONNECTION_STATE:
|
||||
handleUpdateConnectionState((BluetoothDevice) msg.obj, msg.arg1, msg.arg2);
|
||||
handleConnectionChange();
|
||||
firePairedDevicesChanged();
|
||||
break;
|
||||
case MSG_UPDATE_BONDED_DEVICES:
|
||||
handleUpdateBondedDevices();
|
||||
firePairedDevicesChanged();
|
||||
break;
|
||||
case MSG_ADD_PROFILE:
|
||||
mProfiles.put(msg.arg1, (BluetoothProfile) msg.obj);
|
||||
handleUpdateConnectionStates();
|
||||
firePairedDevicesChanged();
|
||||
break;
|
||||
case MSG_REM_PROFILE:
|
||||
mProfiles.remove(msg.arg1);
|
||||
handleUpdateConnectionStates();
|
||||
firePairedDevicesChanged();
|
||||
break;
|
||||
}
|
||||
};
|
||||
};
|
||||
@Override
|
||||
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
|
||||
cachedDevice.registerCallback(this);
|
||||
updateConnected();
|
||||
firePairedDevicesChanged();
|
||||
}
|
||||
|
||||
private static class DeviceInfo {
|
||||
int connectionStateIndex = 0;
|
||||
boolean bonded; // per getBondedDevices
|
||||
SparseArray<Boolean> connectedProfiles = new SparseArray<>();
|
||||
SparseArray<Integer> profileStates = new SparseArray<>();
|
||||
@Override
|
||||
public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
|
||||
updateConnected();
|
||||
firePairedDevicesChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
|
||||
updateConnected();
|
||||
firePairedDevicesChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceAttributesChanged() {
|
||||
updateConnected();
|
||||
firePairedDevicesChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||
mConnecting = state == BluetoothAdapter.STATE_CONNECTING;
|
||||
mLastDevice = cachedDevice;
|
||||
updateConnected();
|
||||
fireStateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.bluetooth.BluetoothA2dp;
|
||||
import android.bluetooth.BluetoothA2dpSink;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
import android.bluetooth.BluetoothHeadsetClient;
|
||||
import android.bluetooth.BluetoothInputDevice;
|
||||
import android.bluetooth.BluetoothMap;
|
||||
import android.bluetooth.BluetoothPan;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothUuid;
|
||||
import android.os.ParcelUuid;
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class BluetoothUtil {
|
||||
|
||||
public static String profileToString(int profile) {
|
||||
if (profile == BluetoothProfile.HEADSET) return "HEADSET";
|
||||
if (profile == BluetoothProfile.A2DP) return "A2DP";
|
||||
if (profile == BluetoothProfile.AVRCP_CONTROLLER) return "AVRCP_CONTROLLER";
|
||||
if (profile == BluetoothProfile.PAN) return "PAN";
|
||||
if (profile == BluetoothProfile.INPUT_DEVICE) return "INPUT_DEVICE";
|
||||
if (profile == BluetoothProfile.MAP) return "MAP";
|
||||
return "UNKNOWN(" + profile + ")";
|
||||
}
|
||||
|
||||
public static String profileStateToString(int state) {
|
||||
if (state == BluetoothProfile.STATE_CONNECTED) return "STATE_CONNECTED";
|
||||
if (state == BluetoothProfile.STATE_CONNECTING) return "STATE_CONNECTING";
|
||||
if (state == BluetoothProfile.STATE_DISCONNECTED) return "STATE_DISCONNECTED";
|
||||
if (state == BluetoothProfile.STATE_DISCONNECTING) return "STATE_DISCONNECTING";
|
||||
return "STATE_UNKNOWN";
|
||||
}
|
||||
|
||||
public static String uuidToString(ParcelUuid uuid) {
|
||||
if (BluetoothUuid.AudioSink.equals(uuid)) return "AudioSink";
|
||||
if (BluetoothUuid.AudioSource.equals(uuid)) return "AudioSource";
|
||||
if (BluetoothUuid.AdvAudioDist.equals(uuid)) return "AdvAudioDist";
|
||||
if (BluetoothUuid.HSP.equals(uuid)) return "HSP";
|
||||
if (BluetoothUuid.HSP_AG.equals(uuid)) return "HSP_AG";
|
||||
if (BluetoothUuid.Handsfree.equals(uuid)) return "Handsfree";
|
||||
if (BluetoothUuid.Handsfree_AG.equals(uuid)) return "Handsfree_AG";
|
||||
if (BluetoothUuid.AvrcpController.equals(uuid)) return "AvrcpController";
|
||||
if (BluetoothUuid.AvrcpTarget.equals(uuid)) return "AvrcpTarget";
|
||||
if (BluetoothUuid.ObexObjectPush.equals(uuid)) return "ObexObjectPush";
|
||||
if (BluetoothUuid.Hid.equals(uuid)) return "Hid";
|
||||
if (BluetoothUuid.Hogp.equals(uuid)) return "Hogp";
|
||||
if (BluetoothUuid.PANU.equals(uuid)) return "PANU";
|
||||
if (BluetoothUuid.NAP.equals(uuid)) return "NAP";
|
||||
if (BluetoothUuid.BNEP.equals(uuid)) return "BNEP";
|
||||
if (BluetoothUuid.PBAP_PSE.equals(uuid)) return "PBAP_PSE";
|
||||
if (BluetoothUuid.MAP.equals(uuid)) return "MAP";
|
||||
if (BluetoothUuid.MNS.equals(uuid)) return "MNS";
|
||||
if (BluetoothUuid.MAS.equals(uuid)) return "MAS";
|
||||
return uuid != null ? uuid.toString() : null;
|
||||
}
|
||||
|
||||
public static String connectionStateToString(int connectionState) {
|
||||
if (connectionState == BluetoothAdapter.STATE_DISCONNECTED) return "STATE_DISCONNECTED";
|
||||
if (connectionState == BluetoothAdapter.STATE_CONNECTED) return "STATE_CONNECTED";
|
||||
if (connectionState == BluetoothAdapter.STATE_DISCONNECTING) return "STATE_DISCONNECTING";
|
||||
if (connectionState == BluetoothAdapter.STATE_CONNECTING) return "STATE_CONNECTING";
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
public static String deviceToString(BluetoothDevice device) {
|
||||
return device == null ? null : (device.getAddress() + '[' + device.getAliasName() + ']');
|
||||
}
|
||||
|
||||
public static String uuidsToString(BluetoothDevice device) {
|
||||
if (device == null) return null;
|
||||
final ParcelUuid[] ids = device.getUuids();
|
||||
if (ids == null) return null;
|
||||
final String[] tokens = new String[ids.length];
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
tokens[i] = uuidToString(ids[i]);
|
||||
}
|
||||
return TextUtils.join(",", tokens);
|
||||
}
|
||||
|
||||
public static int uuidToProfile(ParcelUuid uuid) {
|
||||
if (BluetoothUuid.AudioSink.equals(uuid)) return BluetoothProfile.A2DP;
|
||||
if (BluetoothUuid.AdvAudioDist.equals(uuid)) return BluetoothProfile.A2DP;
|
||||
|
||||
if (BluetoothUuid.HSP.equals(uuid)) return BluetoothProfile.HEADSET;
|
||||
if (BluetoothUuid.Handsfree.equals(uuid)) return BluetoothProfile.HEADSET;
|
||||
|
||||
if (BluetoothUuid.MAP.equals(uuid)) return BluetoothProfile.MAP;
|
||||
if (BluetoothUuid.MNS.equals(uuid)) return BluetoothProfile.MAP;
|
||||
if (BluetoothUuid.MAS.equals(uuid)) return BluetoothProfile.MAP;
|
||||
|
||||
if (BluetoothUuid.AvrcpController.equals(uuid)) return BluetoothProfile.AVRCP_CONTROLLER;
|
||||
|
||||
if (BluetoothUuid.Hid.equals(uuid)) return BluetoothProfile.INPUT_DEVICE;
|
||||
if (BluetoothUuid.Hogp.equals(uuid)) return BluetoothProfile.INPUT_DEVICE;
|
||||
|
||||
if (BluetoothUuid.NAP.equals(uuid)) return BluetoothProfile.PAN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Profile getProfile(BluetoothProfile p) {
|
||||
if (p instanceof BluetoothA2dp) return newProfile((BluetoothA2dp) p);
|
||||
if (p instanceof BluetoothHeadset) return newProfile((BluetoothHeadset) p);
|
||||
if (p instanceof BluetoothA2dpSink) return newProfile((BluetoothA2dpSink) p);
|
||||
if (p instanceof BluetoothHeadsetClient) return newProfile((BluetoothHeadsetClient) p);
|
||||
if (p instanceof BluetoothInputDevice) return newProfile((BluetoothInputDevice) p);
|
||||
if (p instanceof BluetoothMap) return newProfile((BluetoothMap) p);
|
||||
if (p instanceof BluetoothPan) return newProfile((BluetoothPan) p);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Profile newProfile(final BluetoothA2dp a2dp) {
|
||||
return new Profile() {
|
||||
@Override
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
return a2dp.connect(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
return a2dp.disconnect(device);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Profile newProfile(final BluetoothHeadset headset) {
|
||||
return new Profile() {
|
||||
@Override
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
return headset.connect(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
return headset.disconnect(device);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Profile newProfile(final BluetoothA2dpSink sink) {
|
||||
return new Profile() {
|
||||
@Override
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
return sink.connect(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
return sink.disconnect(device);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Profile newProfile(final BluetoothHeadsetClient client) {
|
||||
return new Profile() {
|
||||
@Override
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
return client.connect(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
return client.disconnect(device);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Profile newProfile(final BluetoothInputDevice input) {
|
||||
return new Profile() {
|
||||
@Override
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
return input.connect(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
return input.disconnect(device);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Profile newProfile(final BluetoothMap map) {
|
||||
return new Profile() {
|
||||
@Override
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
return map.connect(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
return map.disconnect(device);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Profile newProfile(final BluetoothPan pan) {
|
||||
return new Profile() {
|
||||
@Override
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
return pan.connect(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
return pan.disconnect(device);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// common abstraction for supported profiles
|
||||
public interface Profile {
|
||||
boolean connect(BluetoothDevice device);
|
||||
boolean disconnect(BluetoothDevice device);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user