SMP: Delay authorization complete.

Delay authorization complete during Bond Pending state in SMP.
Instead of automatically advancing the Bond Pending state, create
a 500ms window to allow the slave to stop pairing by sending over
the Pairing Failed command during the Bond Pending state.

BUG: 28475887
Change-Id: Id6c30247d15258cd18eb34827694b6cd79ca753a
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index 1e3effe..7422898 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -24,6 +24,8 @@
 #include "stack/smp/smp_int.h"
 #include "utils/include/bt_utils.h"
 
+extern fixed_queue_t *btu_general_alarm_queue;
+
 #if SMP_INCLUDED == TRUE
 const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
 {
@@ -553,6 +555,9 @@
 {
     SMP_TRACE_DEBUG("%s", __func__);
     p_cb->status = *(UINT8 *)p_data;
+
+    /* Cancel pending auth complete timer if set */
+    alarm_cancel(p_cb->delayed_auth_timer_ent);
 }
 
 /*******************************************************************************
@@ -1287,7 +1292,6 @@
 *******************************************************************************/
 void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   reason = SMP_SUCCESS;
     SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
                       __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
 
@@ -1309,9 +1313,22 @@
             }
 
             if (p_cb->total_tx_unacked == 0)
-                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
-            else
+            {
+                /*
+                 * Instead of declaring authorization complete immediately,
+                 * delay the event from being sent by SMP_DELAYED_AUTH_TIMEOUT_MS.
+                 * This allows the slave to send over Pairing Failed if the
+                 * last key is rejected.  During this waiting window, the
+                 * state should remain in SMP_STATE_BOND_PENDING.
+                 */
+                if (!alarm_is_scheduled(p_cb->delayed_auth_timer_ent)) {
+                    SMP_TRACE_DEBUG("%s delaying auth complete.", __func__);
+                    alarm_set_on_queue(p_cb->delayed_auth_timer_ent, SMP_DELAYED_AUTH_TIMEOUT_MS,
+                                       smp_delayed_auth_complete_timeout, NULL, btu_general_alarm_queue);
+                }
+            } else {
                 p_cb->wait_for_authorization_complete = TRUE;
+            }
         }
     }
 }
diff --git a/stack/smp/smp_api.c b/stack/smp/smp_api.c
index b3373b5..ddf9ba4 100644
--- a/stack/smp/smp_api.c
+++ b/stack/smp/smp_api.c
@@ -52,6 +52,7 @@
 {
     memset(&smp_cb, 0, sizeof(tSMP_CB));
     smp_cb.smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
+    smp_cb.delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
 
 #if defined(SMP_INITIAL_TRACE_LEVEL)
     smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index fbb4289..aea8538 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -51,6 +51,7 @@
 #endif
 
 #define SMP_WAIT_FOR_RSP_TIMEOUT_MS      (30 * 1000)
+#define SMP_DELAYED_AUTH_TIMEOUT_MS      500
 
 #define SMP_OPCODE_INIT                   0x04
 
@@ -340,7 +341,8 @@
     UINT16          total_tx_unacked;
     BOOLEAN         wait_for_authorization_complete;
     UINT8           cert_failure; /*failure case for certification */
-} tSMP_CB;
+    alarm_t         *delayed_auth_timer_ent;
+}tSMP_CB;
 
 /* Server Action functions are of this type */
 typedef void (*tSMP_ACT)(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
@@ -481,6 +483,7 @@
 extern void smp_convert_string_to_tk(BT_OCTET16 tk, UINT32 passkey);
 extern void smp_mask_enc_key(UINT8 loc_enc_size, UINT8 * p_data);
 extern void smp_rsp_timeout(void *data);
+extern void smp_delayed_auth_complete_timeout(void *data);
 extern void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b);
 extern BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
                                  UINT8 *plain_text, UINT8 pt_len,
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index 2d80343..c3709f8 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -240,7 +240,7 @@
 /* PAIR_RSP             */{ 0,    0,     0,      1,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
 /* CONFIRM              */{ 0,    0,     0,      0,     0,   1,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
 /* RAND                 */{ 0,    0,     0,      0,     0,   0,    1,   0,      0,      0,    1,    0,      0,     0,     0,    0,     0   },
-/* PAIR_FAIL            */{ 0,    0x81,  0,      0x81,  0x81,0x81, 0x81,0x81,   0x81,   0x81, 0x81, 0x81,   0x81,  0x81,  0,    0,     0   },
+/* PAIR_FAIL            */{ 0,    0x81,  0,      0x81,  0x81,0x81, 0x81,0x81,   0x81,   0x81, 0x81, 0x81,   0x81,  0x81,  0,    0x81,  0   },
 /* ENC_INFO             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    1,     0   },
 /* MASTER_ID            */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    4,     0   },
 /* ID_INFO              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    2,     0   },
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 0be94c4..a7357db 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -375,6 +375,30 @@
 
 /*******************************************************************************
 **
+** Function         smp_delayed_auth_complete_timeout
+**
+** Description      Called when no pairing failed command received within timeout
+**                  period.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_delayed_auth_complete_timeout(UNUSED_ATTR void *data)
+{
+    /*
+     * Waited for potential pair failure. Send SMP_AUTH_CMPL_EVT if
+     * the state is still in bond pending.
+     */
+    if (smp_get_state() == SMP_STATE_BOND_PENDING)
+    {
+        UINT8 reason = SMP_SUCCESS;
+        SMP_TRACE_EVENT("%s sending delayed auth complete.", __func__);
+        smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &reason);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         smp_build_pairing_req_cmd
 **
 ** Description      Build pairing request command.
@@ -842,10 +866,12 @@
     SMP_TRACE_EVENT("smp_cb_cleanup");
 
     alarm_free(p_cb->smp_rsp_timer_ent);
+    alarm_free(p_cb->delayed_auth_timer_ent);
     memset(p_cb, 0, sizeof(tSMP_CB));
     p_cb->p_callback = p_callback;
     p_cb->trace_level = trace_level;
     p_cb->smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
+    p_cb->delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
 }
 
 /*******************************************************************************