summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKevin F. Haggerty <haggertk@lineageos.org>2019-08-05 17:25:43 -0600
committerKevin F. Haggerty <haggertk@lineageos.org>2019-08-05 17:25:43 -0600
commitf8ee395dc5ed28a9e865e805e8620302c57180cc (patch)
treeeb2cc9de202321f07bb15f876161bb2e42e76ace /src
parentcb87cd63aaecb6ccb4bcda28ac4dd82e1bd6301e (diff)
parent72232583d1e430bb95bb1ab42eade6bce25d3a7e (diff)
downloadandroid_packages_apps_Bluetooth-f8ee395dc5ed28a9e865e805e8620302c57180cc.tar.gz
android_packages_apps_Bluetooth-f8ee395dc5ed28a9e865e805e8620302c57180cc.tar.bz2
android_packages_apps_Bluetooth-f8ee395dc5ed28a9e865e805e8620302c57180cc.zip
Merge tag 'android-9.0.0_r46' into staging/lineage-16.0_merge-android-9.0.0_r46
Android 9.0.0 Release 46 (PQ3A.190801.002) * tag 'android-9.0.0_r46': DO NOT MERGE Separate SDP procedure from bonding state (2/2) Change-Id: I23862a3c7c9cbab787b4eebed8ab86371c91aa9b
Diffstat (limited to 'src')
-rw-r--r--src/com/android/bluetooth/a2dp/A2dpService.java26
-rw-r--r--src/com/android/bluetooth/btservice/AdapterProperties.java2
-rw-r--r--src/com/android/bluetooth/btservice/AdapterService.java12
-rw-r--r--src/com/android/bluetooth/btservice/BondStateMachine.java49
-rw-r--r--src/com/android/bluetooth/btservice/RemoteDevices.java8
-rw-r--r--src/com/android/bluetooth/hearingaid/HearingAidService.java26
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetService.java26
-rw-r--r--src/com/android/bluetooth/hid/HidHostService.java40
8 files changed, 129 insertions, 60 deletions
diff --git a/src/com/android/bluetooth/a2dp/A2dpService.java b/src/com/android/bluetooth/a2dp/A2dpService.java
index 361ac6735..01ecd9434 100644
--- a/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -355,24 +355,18 @@ public class A2dpService extends ProfileService {
return false;
}
// Check priority and accept or reject the connection.
- // Note: Logic can be simplified, but keeping it this way for readability
int priority = getPriority(device);
int bondState = mAdapterService.getBondState(device);
- // If priority is undefined, it is likely that service discovery has not completed and peer
- // initiated the connection. Allow this connection only if the device is bonded or bonding
- boolean serviceDiscoveryPending = (priority == BluetoothProfile.PRIORITY_UNDEFINED)
- && (bondState == BluetoothDevice.BOND_BONDING
- || bondState == BluetoothDevice.BOND_BONDED);
- // Also allow connection when device is bonded/bonding and priority is ON/AUTO_CONNECT.
- boolean isEnabled = (priority == BluetoothProfile.PRIORITY_ON
- || priority == BluetoothProfile.PRIORITY_AUTO_CONNECT)
- && (bondState == BluetoothDevice.BOND_BONDED
- || bondState == BluetoothDevice.BOND_BONDING);
- if (!serviceDiscoveryPending && !isEnabled) {
- // Otherwise, reject the connection if no service discovery is pending and priority is
- // neither PRIORITY_ON nor PRIORITY_AUTO_CONNECT
- Log.w(TAG, "okToConnect: return false, priority=" + priority + ", bondState="
- + bondState);
+ // Allow this connection only if the device is bonded. Any attempt to connect while
+ // bonding would potentially lead to an unauthorized connection.
+ if (bondState != BluetoothDevice.BOND_BONDED) {
+ Log.w(TAG, "okToConnect: return false, bondState=" + bondState);
+ return false;
+ } else if (priority != BluetoothProfile.PRIORITY_UNDEFINED
+ && priority != BluetoothProfile.PRIORITY_ON
+ && priority != BluetoothProfile.PRIORITY_AUTO_CONNECT) {
+ // Otherwise, reject the connection if priority is not valid.
+ Log.w(TAG, "okToConnect: return false, priority=" + priority);
return false;
}
return true;
diff --git a/src/com/android/bluetooth/btservice/AdapterProperties.java b/src/com/android/bluetooth/btservice/AdapterProperties.java
index d594850c2..981a45acb 100644
--- a/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -41,6 +41,7 @@ import android.os.ParcelUuid;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings.Secure;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.util.Pair;
import android.util.StatsLog;
@@ -462,6 +463,7 @@ class AdapterProperties {
// This function shall be invoked from BondStateMachine whenever the bond
// state changes.
+ @VisibleForTesting
void onBondStateChanged(BluetoothDevice device, int state) {
if (device == null) {
Log.w(TAG, "onBondStateChanged, device is null");
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index ad7895519..9d8cde986 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -1817,6 +1817,18 @@ public class AdapterService extends Service {
}
}
+ /**
+ * Update device UUID changed to {@link BondStateMachine}
+ *
+ * @param device remote device of interest
+ */
+ public void deviceUuidUpdated(BluetoothDevice device) {
+ // Notify BondStateMachine for SDP complete / UUID changed.
+ Message msg = mBondStateMachine.obtainMessage(BondStateMachine.UUID_UPDATE);
+ msg.obj = device;
+ mBondStateMachine.sendMessage(msg);
+ }
+
boolean cancelBondProcess(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
byte[] addr = Utils.getBytesFromAddress(device.getAddress());
diff --git a/src/com/android/bluetooth/btservice/BondStateMachine.java b/src/com/android/bluetooth/btservice/BondStateMachine.java
index 13ef2ad4b..81e5aae5a 100644
--- a/src/com/android/bluetooth/btservice/BondStateMachine.java
+++ b/src/com/android/bluetooth/btservice/BondStateMachine.java
@@ -34,10 +34,13 @@ import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.hfpclient.HeadsetClientService;
import com.android.bluetooth.hid.HidHostService;
import com.android.bluetooth.pbapclient.PbapClientService;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
/**
* This state machine handles Bluetooth Adapter State.
@@ -57,6 +60,7 @@ final class BondStateMachine extends StateMachine {
static final int BONDING_STATE_CHANGE = 4;
static final int SSP_REQUEST = 5;
static final int PIN_REQUEST = 6;
+ static final int UUID_UPDATE = 10;
static final int BOND_STATE_NONE = 0;
static final int BOND_STATE_BONDING = 1;
static final int BOND_STATE_BONDED = 2;
@@ -71,6 +75,8 @@ final class BondStateMachine extends StateMachine {
public static final String OOBDATA = "oobdata";
+ @VisibleForTesting Set<BluetoothDevice> mPendingBondedDevices = new HashSet<>();
+
private BondStateMachine(AdapterService service, AdapterProperties prop,
RemoteDevices remoteDevices) {
super("BondStateMachine:");
@@ -144,7 +150,11 @@ final class BondStateMachine extends StateMachine {
+ state2str(newState));
}
break;
-
+ case UUID_UPDATE:
+ if (mPendingBondedDevices.contains(dev)) {
+ sendIntent(dev, BluetoothDevice.BOND_BONDED, 0);
+ }
+ break;
case CANCEL_BOND:
default:
Log.e(TAG, "Received unhandled state: " + msg.what);
@@ -330,17 +340,52 @@ final class BondStateMachine extends StateMachine {
mAdapterService.sendOrderedBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
}
- private void sendIntent(BluetoothDevice device, int newState, int reason) {
+ @VisibleForTesting
+ void sendIntent(BluetoothDevice device, int newState, int reason) {
DeviceProperties devProp = mRemoteDevices.getDeviceProperties(device);
int oldState = BluetoothDevice.BOND_NONE;
+ if (newState != BluetoothDevice.BOND_NONE
+ && newState != BluetoothDevice.BOND_BONDING
+ && newState != BluetoothDevice.BOND_BONDED) {
+ infoLog("Invalid bond state " + newState);
+ return;
+ }
if (devProp != null) {
oldState = devProp.getBondState();
}
+ if (mPendingBondedDevices.contains(device)) {
+ mPendingBondedDevices.remove(device);
+ if (oldState == BluetoothDevice.BOND_BONDED) {
+ if (newState == BluetoothDevice.BOND_BONDING) {
+ mAdapterProperties.onBondStateChanged(device, newState);
+ }
+ oldState = BluetoothDevice.BOND_BONDING;
+ } else {
+ // Should not enter here.
+ throw new IllegalArgumentException("Invalid old state " + oldState);
+ }
+ }
if (oldState == newState) {
return;
}
+
mAdapterProperties.onBondStateChanged(device, newState);
+ if (devProp != null && ((devProp.getDeviceType() == BluetoothDevice.DEVICE_TYPE_CLASSIC
+ || devProp.getDeviceType() == BluetoothDevice.DEVICE_TYPE_DUAL)
+ && newState == BluetoothDevice.BOND_BONDED && devProp.getUuids() == null)) {
+ infoLog(device + " is bonded, wait for SDP complete to broadcast bonded intent");
+ if (!mPendingBondedDevices.contains(device)) {
+ mPendingBondedDevices.add(device);
+ }
+ if (oldState == BluetoothDevice.BOND_NONE) {
+ // Broadcast NONE->BONDING for NONE->BONDED case.
+ newState = BluetoothDevice.BOND_BONDING;
+ } else {
+ return;
+ }
+ }
+
Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, newState);
diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java
index 12897fea5..011177e51 100644
--- a/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -177,6 +177,7 @@ final class RemoteDevices {
return prop.getDevice();
}
+ @VisibleForTesting
DeviceProperties addDeviceProperties(byte[] address) {
synchronized (mDevices) {
DeviceProperties prop = new DeviceProperties();
@@ -207,13 +208,13 @@ final class RemoteDevices {
private byte[] mAddress;
private int mBluetoothClass = BluetoothClass.Device.Major.UNCATEGORIZED;
private short mRssi;
- private ParcelUuid[] mUuids;
- private int mDeviceType;
private String mAlias;
- private int mBondState;
private BluetoothDevice mDevice;
private boolean mIsBondingInitiatedLocally;
private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ @VisibleForTesting int mBondState;
+ @VisibleForTesting int mDeviceType;
+ @VisibleForTesting ParcelUuid[] mUuids;
DeviceProperties() {
mBondState = BluetoothDevice.BOND_NONE;
@@ -545,6 +546,7 @@ final class RemoteDevices {
}
device.mUuids = newUuids;
if (sAdapterService.getState() == BluetoothAdapter.STATE_ON) {
+ sAdapterService.deviceUuidUpdated(bdDevice);
sendUuidIntent(bdDevice);
}
break;
diff --git a/src/com/android/bluetooth/hearingaid/HearingAidService.java b/src/com/android/bluetooth/hearingaid/HearingAidService.java
index b30eb62a0..704a3d593 100644
--- a/src/com/android/bluetooth/hearingaid/HearingAidService.java
+++ b/src/com/android/bluetooth/hearingaid/HearingAidService.java
@@ -343,24 +343,18 @@ public class HearingAidService extends ProfileService {
return false;
}
// Check priority and accept or reject the connection.
- // Note: Logic can be simplified, but keeping it this way for readability
int priority = getPriority(device);
int bondState = mAdapterService.getBondState(device);
- // If priority is undefined, it is likely that service discovery has not completed and peer
- // initiated the connection. Allow this connection only if the device is bonded or bonding
- boolean serviceDiscoveryPending = (priority == BluetoothProfile.PRIORITY_UNDEFINED)
- && (bondState == BluetoothDevice.BOND_BONDING
- || bondState == BluetoothDevice.BOND_BONDED);
- // Also allow connection when device is bonded/bonding and priority is ON/AUTO_CONNECT.
- boolean isEnabled = (priority == BluetoothProfile.PRIORITY_ON
- || priority == BluetoothProfile.PRIORITY_AUTO_CONNECT)
- && (bondState == BluetoothDevice.BOND_BONDED
- || bondState == BluetoothDevice.BOND_BONDING);
- if (!serviceDiscoveryPending && !isEnabled) {
- // Otherwise, reject the connection if no service discovery is pending and priority is
- // neither PRIORITY_ON nor PRIORITY_AUTO_CONNECT
- Log.w(TAG, "okToConnect: return false, priority=" + priority + ", bondState="
- + bondState);
+ // Allow this connection only if the device is bonded. Any attempt to connect while
+ // bonding would potentially lead to an unauthorized connection.
+ if (bondState != BluetoothDevice.BOND_BONDED) {
+ Log.w(TAG, "okToConnect: return false, bondState=" + bondState);
+ return false;
+ } else if (priority != BluetoothProfile.PRIORITY_UNDEFINED
+ && priority != BluetoothProfile.PRIORITY_ON
+ && priority != BluetoothProfile.PRIORITY_AUTO_CONNECT) {
+ // Otherwise, reject the connection if priority is not valid.
+ Log.w(TAG, "okToConnect: return false, priority=" + priority);
return false;
}
return true;
diff --git a/src/com/android/bluetooth/hfp/HeadsetService.java b/src/com/android/bluetooth/hfp/HeadsetService.java
index 2ccc1e486..6d16a6a26 100644
--- a/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -1688,24 +1688,18 @@ public class HeadsetService extends ProfileService {
return false;
}
// Check priority and accept or reject the connection.
- // Note: Logic can be simplified, but keeping it this way for readability
int priority = getPriority(device);
int bondState = mAdapterService.getBondState(device);
- // If priority is undefined, it is likely that service discovery has not completed and peer
- // initiated the connection. Allow this connection only if the device is bonded or bonding
- boolean serviceDiscoveryPending = (priority == BluetoothProfile.PRIORITY_UNDEFINED) && (
- bondState == BluetoothDevice.BOND_BONDING
- || bondState == BluetoothDevice.BOND_BONDED);
- // Also allow connection when device is bonded/bonding and priority is ON/AUTO_CONNECT.
- boolean isEnabled = (priority == BluetoothProfile.PRIORITY_ON
- || priority == BluetoothProfile.PRIORITY_AUTO_CONNECT) && (
- bondState == BluetoothDevice.BOND_BONDED
- || bondState == BluetoothDevice.BOND_BONDING);
- if (!serviceDiscoveryPending && !isEnabled) {
- // Otherwise, reject the connection if no service discovery is pending and priority is
- // neither PRIORITY_ON nor PRIORITY_AUTO_CONNECT
- Log.w(TAG,
- "okToConnect: return false, priority=" + priority + ", bondState=" + bondState);
+ // Allow this connection only if the device is bonded. Any attempt to connect while
+ // bonding would potentially lead to an unauthorized connection.
+ if (bondState != BluetoothDevice.BOND_BONDED) {
+ Log.w(TAG, "okToAcceptConnection: return false, bondState=" + bondState);
+ return false;
+ } else if (priority != BluetoothProfile.PRIORITY_UNDEFINED
+ && priority != BluetoothProfile.PRIORITY_ON
+ && priority != BluetoothProfile.PRIORITY_AUTO_CONNECT) {
+ // Otherwise, reject the connection if priority is not valid.
+ Log.w(TAG, "okToAcceptConnection: return false, priority=" + priority);
return false;
}
List<BluetoothDevice> connectingConnectedDevices =
diff --git a/src/com/android/bluetooth/hid/HidHostService.java b/src/com/android/bluetooth/hid/HidHostService.java
index ff1a608da..63f52060b 100644
--- a/src/com/android/bluetooth/hid/HidHostService.java
+++ b/src/com/android/bluetooth/hid/HidHostService.java
@@ -26,6 +26,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.bluetooth.BluetoothMetricsProto;
@@ -793,16 +794,41 @@ public class HidHostService extends ProfileService {
}
}
- private boolean okToConnect(BluetoothDevice device) {
+ /**
+ * Check whether can connect to a peer device.
+ * The check considers a number of factors during the evaluation.
+ *
+ * @param device the peer device to connect to
+ * @return true if connection is allowed, otherwise false
+ */
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ public boolean okToConnect(BluetoothDevice device) {
AdapterService adapterService = AdapterService.getAdapterService();
- //check if it is inbound connection in Quiet mode, priority and Bond status
- //to decide if its ok to allow this connection
- if ((adapterService == null) || ((adapterService.isQuietModeEnabled()) && (mTargetDevice
- == null)) || (BluetoothProfile.PRIORITY_OFF == getPriority(device)) || (
- device.getBondState() == BluetoothDevice.BOND_NONE)) {
+ // Check if adapter service is null.
+ if (adapterService == null) {
+ Log.w(TAG, "okToConnect: adapter service is null");
+ return false;
+ }
+ // Check if this is an incoming connection in Quiet mode.
+ if (adapterService.isQuietModeEnabled() && mTargetDevice == null) {
+ Log.w(TAG, "okToConnect: return false as quiet mode enabled");
+ return false;
+ }
+ // Check priority and accept or reject the connection.
+ int priority = getPriority(device);
+ int bondState = adapterService.getBondState(device);
+ // Allow this connection only if the device is bonded. Any attempt to connect while
+ // bonding would potentially lead to an unauthorized connection.
+ if (bondState != BluetoothDevice.BOND_BONDED) {
+ Log.w(TAG, "okToConnect: return false, bondState=" + bondState);
+ return false;
+ } else if (priority != BluetoothProfile.PRIORITY_UNDEFINED
+ && priority != BluetoothProfile.PRIORITY_ON
+ && priority != BluetoothProfile.PRIORITY_AUTO_CONNECT) {
+ // Otherwise, reject the connection if priority is not valid.
+ Log.w(TAG, "okToConnect: return false, priority=" + priority);
return false;
}
-
return true;
}