diff options
author | Kevin F. Haggerty <haggertk@lineageos.org> | 2019-08-05 17:25:43 -0600 |
---|---|---|
committer | Kevin F. Haggerty <haggertk@lineageos.org> | 2019-08-05 17:25:43 -0600 |
commit | f8ee395dc5ed28a9e865e805e8620302c57180cc (patch) | |
tree | eb2cc9de202321f07bb15f876161bb2e42e76ace /src | |
parent | cb87cd63aaecb6ccb4bcda28ac4dd82e1bd6301e (diff) | |
parent | 72232583d1e430bb95bb1ab42eade6bce25d3a7e (diff) | |
download | android_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')
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; } |