ASHA: always discover service to avoid GATT handles mismatch

If device receives Service Changed message before profile was
connected, characteristic handles values can be out of date. There
is no way they will ever update, because message notifying us about
it already came and won't be sent again. Old values read from storage
would be used. Instead, on encryption complete, discover service
again, and use those values. This patch removes characteristic handles
from storage, as we don't need them anymore. This patch adds minimal
time overhead, because discovery of ASHA service is quick -
service is small.
This in particular solves the issue in scenario after DFU of HA,
where Service Changed is sent very quickly after connection.

Bug: 388446070
Test: m .
Flag: EXEMPT, low potential for significant Droidfood feedback
Change-Id: I543d6362ba34432700cc5dcec7483717b441620d
diff --git a/system/bta/hearing_aid/hearing_aid.cc b/system/bta/hearing_aid/hearing_aid.cc
index d19ac80..5f1ee00 100644
--- a/system/bta/hearing_aid/hearing_aid.cc
+++ b/system/bta/hearing_aid/hearing_aid.cc
@@ -460,13 +460,14 @@
 
   void Connect(const RawAddress& address) {
     log::info("bd_addr={}", address);
-    hearingDevices.Add(HearingDevice(address, true));
+    hearingDevices.Add(HearingDevice(address));
+
     BTA_GATTC_Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, false);
   }
 
   void AddToAcceptlist(const RawAddress& address) {
     log::info("bd_addr={}", address);
-    hearingDevices.Add(HearingDevice(address, true));
+    hearingDevices.Add(HearingDevice(address));
     BTA_GATTC_Open(gatt_if, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
   }
 
@@ -698,24 +699,14 @@
     if (!success) {
       log::error("encryption failed: bd_addr={}", address);
       BTA_GATTC_Close(hearingDevice->conn_id);
-      if (hearingDevice->first_connection) {
-        callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
-      }
+      callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
       return;
     }
 
     log::info("encryption successful: bd_addr={}", address);
 
-    if (hearingDevice->audio_control_point_handle && hearingDevice->audio_status_handle &&
-        hearingDevice->audio_status_ccc_handle && hearingDevice->volume_handle &&
-        hearingDevice->read_psm_handle) {
-      // Use cached data, jump to read PSM
-      ReadPSM(hearingDevice);
-    } else {
-      log::info("starting service search request for ASHA: bd_addr={}", address);
-      hearingDevice->first_connection = true;
-      BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, HEARING_AID_UUID);
-    }
+    log::info("starting service search request for ASHA: bd_addr={}", address);
+    BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, HEARING_AID_UUID);
   }
 
   // Just take care phy update successful case to avoid loop executing.
@@ -761,7 +752,7 @@
 
     log::info("bd_addr={}", address);
 
-    hearingDevice->first_connection = true;
+    hearingDevice->stale_storage = true;
     hearingDevice->service_changed_rcvd = true;
     BtaGattQueue::Clean(hearingDevice->conn_id);
 
@@ -796,19 +787,10 @@
       return;
     }
 
-    // Known device, nothing to do.
-    if (!hearingDevice->first_connection) {
-      log::info("service discovery result ignored: bd_addr={}", hearingDevice->address);
-      return;
-    }
-
     if (status != GATT_SUCCESS) {
       /* close connection and report service discovery complete with error */
       log::error("service discovery failed: bd_addr={} status={}", hearingDevice->address, status);
-
-      if (hearingDevice->first_connection) {
-        callbacks->OnConnectionState(ConnectionState::DISCONNECTED, hearingDevice->address);
-      }
+      callbacks->OnConnectionState(ConnectionState::DISCONNECTED, hearingDevice->address);
       return;
     }
 
@@ -935,6 +917,8 @@
       return;
     }
 
+    hearingDevice->stale_storage = true;
+
     uint8_t capabilities;
     STREAM_TO_UINT8(capabilities, p);
     STREAM_TO_UINT64(hearingDevice->hi_sync_id, p);
@@ -1112,10 +1096,10 @@
 
     log::info("bd_addr={}", address);
 
-    if (hearingDevice->first_connection) {
+    if (hearingDevice->stale_storage) {
       btif_storage_add_hearing_aid(*hearingDevice);
 
-      hearingDevice->first_connection = false;
+      hearingDevice->stale_storage = false;
     }
 
     /* Register and enable the Audio Status Notification */
diff --git a/system/bta/hearing_aid/hearing_aid_test.cc b/system/bta/hearing_aid/hearing_aid_test.cc
index 2090df9..3325279 100644
--- a/system/bta/hearing_aid/hearing_aid_test.cc
+++ b/system/bta/hearing_aid/hearing_aid_test.cc
@@ -468,6 +468,51 @@
   HearingAid::Disconnect(test_address);
 }
 
+/* Test that bonded device that was loaded from storage refreshes GATT handles */
+TEST_F(HearingAidTest, load_from_storage) {
+  set_sample_database(1);
+  SetEncryptionResult(test_address, true);
+  HearingDevice saved_dev;
+
+  EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(1);
+  HearingAid::Connect(test_address);
+  ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(Return(true));
+
+  EXPECT_CALL(gatt_interface, Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, _));
+  HearingAid::Connect(test_address);
+
+  Mock::VerifyAndClearExpectations(&*callbacks);
+  Mock::VerifyAndClearExpectations(&gatt_interface);
+  Mock::VerifyAndClearExpectations(&btm_interface);
+
+
+  EXPECT_CALL(gatt_interface, CancelOpen(_, test_address, _)).Times(AnyNumber());
+  HearingAid::Disconnect(test_address);
+
+  ON_CALL(btif_storage_interface_, AddHearingAid(_))
+          .WillByDefault(Invoke([&](const HearingDevice* dev_info) { saved_dev = *dev_info; }));
+
+  ON_CALL(btif_storage_interface_, GetHearingAidProp(_, _, _, _, _, _))
+          .WillByDefault(Invoke([&](const RawAddress& /*address*/, uint8_t* capabilities,
+                                    uint64_t* hi_sync_id, uint16_t* render_delay,
+                                    uint16_t* preparation_delay, uint16_t* codecs) {
+            *capabilities = saved_dev.capabilities;
+            *hi_sync_id = saved_dev.hi_sync_id;
+            *render_delay = saved_dev.render_delay;
+            *preparation_delay = saved_dev.preparation_delay;
+            *codecs = saved_dev.codecs;
+            return true;
+          }));
+
+  Mock::VerifyAndClearExpectations(&gatt_interface);
+  EXPECT_CALL(gatt_interface, ServiceSearchRequest).Times(1);
+
+  HearingAid::AddFromStorage(saved_dev, true);
+
+  EXPECT_CALL(gatt_interface, Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, _));
+  HearingAid::Connect(test_address);
+}
+
 }  // namespace
 }  // namespace internal
 }  // namespace hearing_aid
diff --git a/system/bta/include/bta_hearing_aid_api.h b/system/bta/include/bta_hearing_aid_api.h
index 7314d2e..20e4d4d 100644
--- a/system/bta/include/bta_hearing_aid_api.h
+++ b/system/bta/include/bta_hearing_aid_api.h
@@ -106,14 +106,13 @@
 
 struct HearingDevice {
   RawAddress address;
-  /* This is true only during first connection to profile, until we store the
-   * device */
-  bool first_connection;
+  /* Indicates that storage is stale and needs to be updated */
+  bool stale_storage = false;
   bool service_changed_rcvd;
 
   /* we are making active attempt to connect to this device, 'direct connect'.
    */
-  bool connecting_actively;
+  bool connecting_actively = false;
 
   bool switch_to_background_connection_after_failure;
 
@@ -134,12 +133,12 @@
 
   tCONN_ID conn_id;
   uint16_t gap_handle;
-  uint16_t audio_control_point_handle;
-  uint16_t audio_status_handle;
-  uint16_t audio_status_ccc_handle;
-  uint16_t service_changed_ccc_handle;
-  uint16_t volume_handle;
-  uint16_t read_psm_handle;
+  uint16_t audio_control_point_handle = 0;
+  uint16_t audio_status_handle = 0;
+  uint16_t audio_status_ccc_handle = 0;
+  uint16_t service_changed_ccc_handle = 0;
+  uint16_t volume_handle = 0;
+  uint16_t read_psm_handle = 0;
 
   uint8_t capabilities;
   uint64_t hi_sync_id;
@@ -166,26 +165,15 @@
 
   int phy_update_retry_remain;
 
-  HearingDevice(const RawAddress& address, uint8_t capabilities, uint16_t codecs,
-                uint16_t audio_control_point_handle, uint16_t audio_status_handle,
-                uint16_t audio_status_ccc_handle, uint16_t service_changed_ccc_handle,
-                uint16_t volume_handle, uint16_t read_psm_handle, uint64_t hiSyncId,
+  HearingDevice(const RawAddress& address, uint8_t capabilities, uint16_t codecs, uint64_t hiSyncId,
                 uint16_t render_delay, uint16_t preparation_delay)
       : address(address),
-        first_connection(false),
         service_changed_rcvd(false),
-        connecting_actively(false),
         switch_to_background_connection_after_failure(false),
         connection_update_status(NONE),
         accepting_audio(false),
         conn_id(0),
         gap_handle(GAP_INVALID_HANDLE),
-        audio_control_point_handle(audio_control_point_handle),
-        audio_status_handle(audio_status_handle),
-        audio_status_ccc_handle(audio_status_ccc_handle),
-        service_changed_ccc_handle(service_changed_ccc_handle),
-        volume_handle(volume_handle),
-        read_psm_handle(read_psm_handle),
         capabilities(capabilities),
         hi_sync_id(hiSyncId),
         render_delay(render_delay),
@@ -197,20 +185,15 @@
         gap_opened(false),
         phy_update_retry_remain(kPhyUpdateRetryLimit) {}
 
-  HearingDevice(const RawAddress& address, bool first_connection)
+  HearingDevice(const RawAddress& address)
       : address(address),
-        first_connection(first_connection),
         service_changed_rcvd(false),
-        connecting_actively(first_connection),
+        connecting_actively(true),
         switch_to_background_connection_after_failure(false),
         connection_update_status(NONE),
         accepting_audio(false),
         conn_id(0),
         gap_handle(GAP_INVALID_HANDLE),
-        audio_status_handle(0),
-        audio_status_ccc_handle(0),
-        service_changed_ccc_handle(0),
-        read_psm_handle(0),
         capabilities(0),
         hi_sync_id(0),
         render_delay(0),
@@ -222,7 +205,7 @@
         gap_opened(false),
         phy_update_retry_remain(kPhyUpdateRetryLimit) {}
 
-  HearingDevice() : HearingDevice(RawAddress::kEmpty, false) {}
+  HearingDevice() : HearingDevice(RawAddress::kEmpty) {}
 
   /* return true if this device represents left Hearing Aid. Returned value is
    * valid only after capabilities are discovered */
diff --git a/system/btif/src/btif_profile_storage.cc b/system/btif/src/btif_profile_storage.cc
index 6051de1..8142068 100644
--- a/system/btif/src/btif_profile_storage.cc
+++ b/system/btif/src/btif_profile_storage.cc
@@ -421,21 +421,9 @@
           [](const HearingDevice& dev_info) {
             std::string bdstr = dev_info.address.ToString();
             log::verbose("saving hearing aid device: {}", dev_info.address);
-            btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_SERVICE_CHANGED_CCC_HANDLE,
-                                dev_info.service_changed_ccc_handle);
-            btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_READ_PSM_HANDLE,
-                                dev_info.read_psm_handle);
             btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_CAPABILITIES,
                                 dev_info.capabilities);
             btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_CODECS, dev_info.codecs);
-            btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_CONTROL_POINT,
-                                dev_info.audio_control_point_handle);
-            btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_VOLUME_HANDLE,
-                                dev_info.volume_handle);
-            btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_HANDLE,
-                                dev_info.audio_status_handle);
-            btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_CCC_HANDLE,
-                                dev_info.audio_status_ccc_handle);
             btif_config_set_uint64(bdstr, BTIF_STORAGE_KEY_HEARING_AID_SYNC_ID,
                                    dev_info.hi_sync_id);
             btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HEARING_AID_RENDER_DELAY,
@@ -473,37 +461,6 @@
       codecs = value;
     }
 
-    uint16_t audio_control_point_handle = 0;
-    if (btif_config_get_int(name, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_CONTROL_POINT, &value)) {
-      audio_control_point_handle = value;
-    }
-
-    uint16_t audio_status_handle = 0;
-    if (btif_config_get_int(name, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_HANDLE, &value)) {
-      audio_status_handle = value;
-    }
-
-    uint16_t audio_status_ccc_handle = 0;
-    if (btif_config_get_int(name, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_CCC_HANDLE, &value)) {
-      audio_status_ccc_handle = value;
-    }
-
-    uint16_t service_changed_ccc_handle = 0;
-    if (btif_config_get_int(name, BTIF_STORAGE_KEY_HEARING_AID_SERVICE_CHANGED_CCC_HANDLE,
-                            &value)) {
-      service_changed_ccc_handle = value;
-    }
-
-    uint16_t volume_handle = 0;
-    if (btif_config_get_int(name, BTIF_STORAGE_KEY_HEARING_AID_VOLUME_HANDLE, &value)) {
-      volume_handle = value;
-    }
-
-    uint16_t read_psm_handle = 0;
-    if (btif_config_get_int(name, BTIF_STORAGE_KEY_HEARING_AID_READ_PSM_HANDLE, &value)) {
-      read_psm_handle = value;
-    }
-
     uint64_t lvalue;
     uint64_t hi_sync_id = 0;
     if (btif_config_get_uint64(name, BTIF_STORAGE_KEY_HEARING_AID_SYNC_ID, &lvalue)) {
@@ -527,10 +484,8 @@
 
     // add extracted information to BTA Hearing Aid
     do_in_main_thread(Bind(&HearingAid::AddFromStorage,
-                           HearingDevice(bd_addr, capabilities, codecs, audio_control_point_handle,
-                                         audio_status_handle, audio_status_ccc_handle,
-                                         service_changed_ccc_handle, volume_handle, read_psm_handle,
-                                         hi_sync_id, render_delay, preparation_delay),
+                           HearingDevice(bd_addr, capabilities, codecs, hi_sync_id, render_delay,
+                                         preparation_delay),
                            is_acceptlisted));
   }
 }
@@ -538,14 +493,8 @@
 /** Deletes the bonded hearing aid device info from NVRAM */
 void btif_storage_remove_hearing_aid(const RawAddress& address) {
   std::string addrstr = address.ToString();
-  btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_READ_PSM_HANDLE);
   btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_CAPABILITIES);
   btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_CODECS);
-  btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_CONTROL_POINT);
-  btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_VOLUME_HANDLE);
-  btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_HANDLE);
-  btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_CCC_HANDLE);
-  btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_SERVICE_CHANGED_CCC_HANDLE);
   btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_SYNC_ID);
   btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_RENDER_DELAY);
   btif_config_remove(addrstr, BTIF_STORAGE_KEY_HEARING_AID_PREPARATION_DELAY);
diff --git a/system/gd/storage/config_keys.h b/system/gd/storage/config_keys.h
index d3659b6..d6b51c9 100644
--- a/system/gd/storage/config_keys.h
+++ b/system/gd/storage/config_keys.h
@@ -38,18 +38,12 @@
 #define BTIF_STORAGE_KEY_GATT_CLIENT_DB_HASH "GattClientDatabaseHash"
 #define BTIF_STORAGE_KEY_GATT_CLIENT_SUPPORTED "GattClientSupportedFeatures"
 #define BTIF_STORAGE_KEY_GATT_SERVER_SUPPORTED "GattServerSupportedFeatures"
-#define BTIF_STORAGE_KEY_HEARING_AID_AUDIO_CONTROL_POINT "HearingAidAudioControlPoint"
-#define BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_CCC_HANDLE "HearingAidAudioStatusCccHandle"
-#define BTIF_STORAGE_KEY_HEARING_AID_AUDIO_STATUS_HANDLE "HearingAidAudioStatusHandle"
 #define BTIF_STORAGE_KEY_HEARING_AID_CAPABILITIES "HearingAidCapabilities"
 #define BTIF_STORAGE_KEY_HEARING_AID_CODECS "HearingAidCodecs"
 #define BTIF_STORAGE_KEY_HEARING_AID_IS_ACCEPTLISTED "HearingAidIsAcceptlisted"
 #define BTIF_STORAGE_KEY_HEARING_AID_PREPARATION_DELAY "HearingAidPreparationDelay"
-#define BTIF_STORAGE_KEY_HEARING_AID_READ_PSM_HANDLE "HearingAidReadPsmHandle"
 #define BTIF_STORAGE_KEY_HEARING_AID_RENDER_DELAY "HearingAidRenderDelay"
-#define BTIF_STORAGE_KEY_HEARING_AID_SERVICE_CHANGED_CCC_HANDLE "HearingAidServiceChangedCccHandle"
 #define BTIF_STORAGE_KEY_HEARING_AID_SYNC_ID "HearingAidSyncId"
-#define BTIF_STORAGE_KEY_HEARING_AID_VOLUME_HANDLE "HearingAidVolumeHandle"
 #define BTIF_STORAGE_KEY_HFP_SDP_FEATURES "HfpSdpFeatures"
 #define BTIF_STORAGE_KEY_HFP_VERSION "HfpVersion"
 #define BTIF_STORAGE_KEY_HID_APP_ID "HidAppId"