bt: Add late bonding confirmation mechanism

If a coordinated set member is bonding late the user will be notified and
asked for confirmation on pairing with this device. The dialog box will
display specific message for this case.

Bug: 282193044
Test: manual
Tag: #feature
Change-Id: Ie9d79282dd432a542ea02ef477019be6dfbce997
diff --git a/res/values/strings.xml b/res/values/strings.xml
index df82b29..7676d86 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1444,6 +1444,9 @@
     <!-- Title for the dialog to enter PIN. [CHAR LIMIT=40] -->
     <string name="bluetooth_pairing_request">Pair with <xliff:g id="device_name">%1$s</xliff:g>?</string>
 
+    <!-- Message when a bluetooth device from a coordinated set is bonding late. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_pairing_group_late_bonding">Add new member to the existing coordinated set</string>
+
     <!-- Message when bluetooth is informing the user of the pairing key. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_pairing_key_msg">Bluetooth pairing code</string>
 
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingController.java b/src/com/android/settings/bluetooth/BluetoothPairingController.java
index 535e040..f75d301 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingController.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingController.java
@@ -72,6 +72,7 @@
     private boolean mIsCoordinatedSetMember;
     private boolean mIsLeAudio;
     private boolean mIsLeContactSharingEnabled;
+    private boolean mIsLateBonding;
 
     /**
      * Creates an instance of a BluetoothPairingController.
@@ -98,6 +99,7 @@
         mDeviceName = mBluetoothManager.getCachedDeviceManager().getName(mDevice);
         mPbapClientProfile = mBluetoothManager.getProfileManager().getPbapClientProfile();
         mPasskeyFormatted = formatKey(mPasskey);
+        mIsLateBonding = mBluetoothManager.getCachedDeviceManager().isLateBonding(mDevice);
 
         final CachedBluetoothDevice cachedDevice =
                 mBluetoothManager.getCachedDeviceManager().findDevice(mDevice);
@@ -116,7 +118,10 @@
 
             mIsLeContactSharingEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
                     SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, true);
-            Log.d(TAG, "BT_LE_AUDIO_CONTACT_SHARING_ENABLED is " + mIsLeContactSharingEnabled);
+            Log.d(TAG,
+                "BT_LE_AUDIO_CONTACT_SHARING_ENABLED is "
+                    + mIsLeContactSharingEnabled + " isCooridnatedSetMember "
+                    + mIsCoordinatedSetMember);
         }
     }
 
@@ -193,6 +198,15 @@
     }
 
     /**
+     * A method for querying if the bluetooth device from a coordinated set is bonding late.
+     *
+     * @return - A boolean indicating if the device is bonding late.
+     */
+    public boolean isLateBonding() {
+        return mIsLateBonding;
+    }
+
+    /**
      * A method for querying if the bluetooth device has a profile already set up on this device.
      *
      * @return - A boolean indicating if the device has previous knowledge of a profile for this
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
index ad38fa1..3d6a44f 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
@@ -357,6 +357,10 @@
             pairingViewContent.setText(mPairingController.getPairingContent());
         }
         final TextView messagePairingSet = (TextView) view.findViewById(R.id.pairing_group_message);
+        if (mPairingController.isLateBonding()) {
+            messagePairingSet.setText(getString(R.string.bluetooth_pairing_group_late_bonding));
+        }
+
         messagePairingSet.setVisibility(mPairingController.isCoordinatedSetMemberDevice()
                 ? View.VISIBLE : View.GONE);
         return view;
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
index ed477c8..ace0643 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
@@ -26,6 +26,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 
 /**
@@ -53,17 +54,28 @@
             boolean shouldShowDialog = LocalBluetoothPreferences.shouldShowDialogInForeground(
                     context, device);
 
-            // Skips consent pairing dialog if the device was recently associated with CDM
+            Log.d(TAG,
+                "Receive ACTION_PAIRING_REQUEST pairingVariant=" + pairingVariant
+                    + " canBondWithoutDialog=" + device.canBondWithoutDialog()
+                    + " isOngoingPairByCsip="
+                    + mBluetoothManager.getCachedDeviceManager().isOngoingPairByCsip(device)
+                    + " isLateBonding="
+                    + mBluetoothManager.getCachedDeviceManager().isLateBonding(device));
+
+            /* Skips consent pairing dialog if the device was recently associated with CDM
+             * or if the device is a member of the coordinated set and is not bonding late.
+             */
             if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_CONSENT
-                    && (device.canBondWithoutDialog()
-                    || mBluetoothManager.getCachedDeviceManager().isOngoingPairByCsip(device))) {
+                && (device.canBondWithoutDialog()
+                    || (mBluetoothManager.getCachedDeviceManager().isOngoingPairByCsip(device)
+                        && !mBluetoothManager.getCachedDeviceManager().isLateBonding(device)))) {
                 device.setPairingConfirmation(true);
             } else if (powerManager.isInteractive() && shouldShowDialog) {
                 // Since the screen is on and the BT-related activity is in the foreground,
                 // just open the dialog
                 // convert broadcast intent into activity intent (same action string)
-                Intent pairingIntent = BluetoothPairingService.getPairingDialogIntent(context,
-                        intent, BluetoothDevice.EXTRA_PAIRING_INITIATOR_FOREGROUND);
+                Intent pairingIntent = BluetoothPairingService.getPairingDialogIntent(
+                    context, intent, BluetoothDevice.EXTRA_PAIRING_INITIATOR_FOREGROUND);
 
                 context.startActivityAsUser(pairingIntent, UserHandle.CURRENT);
             } else {