Do not change DevType of DUAL devices

If it is dual, even if we only have keys from one protocol, we shouldn't change the DevType as it is a dual device!

Change-Id: Ia3c8419c0d330de184417e7820fbf9b36cb8e004
Test: atest ConfigCacheTest
Bug: 225314856
Tag: #stability
(cherry picked from commit f3cb43835c2c7844972fad473f8f9be80fec20a1)
Merged-In: Ia3c8419c0d330de184417e7820fbf9b36cb8e004
diff --git a/system/gd/storage/config_cache.cc b/system/gd/storage/config_cache.cc
index b1dc1bd..bab8271 100644
--- a/system/gd/storage/config_cache.cc
+++ b/system/gd/storage/config_cache.cc
@@ -420,6 +420,16 @@
   if (!hci::Address::IsValidAddress(section_name)) {
     return false;
   }
+  auto device_type_iter = device_section_entries.find("DevType");
+  if (device_type_iter != device_section_entries.end() &&
+      device_type_iter->second == std::to_string(hci::DeviceType::DUAL)) {
+    // We might only have one of classic/LE keys for a dual device, but it is still a dual device,
+    // so we should not change the DevType.
+    return false;
+  }
+
+  // we will ignore the existing DevType, since it is not known to be a DUAL device so
+  // the keys we have should be sufficient to infer the correct DevType
   bool is_le = false;
   bool is_classic = false;
   // default
@@ -441,11 +451,10 @@
   }
   bool inconsistent = true;
   std::string device_type_str = std::to_string(device_type);
-  auto it = device_section_entries.find("DevType");
-  if (it != device_section_entries.end()) {
-    inconsistent = device_type_str != it->second;
+  if (device_type_iter != device_section_entries.end()) {
+    inconsistent = device_type_str != device_type_iter->second;
     if (inconsistent) {
-      it->second = std::move(device_type_str);
+      device_type_iter->second = std::move(device_type_str);
     }
   } else {
     device_section_entries.insert_or_assign("DevType", std::move(device_type_str));
diff --git a/system/gd/storage/config_cache_test.cc b/system/gd/storage/config_cache_test.cc
index bec056f..29773db 100644
--- a/system/gd/storage/config_cache_test.cc
+++ b/system/gd/storage/config_cache_test.cc
@@ -275,34 +275,110 @@
   ASSERT_EQ(num_change, 4);
 }
 
-TEST(ConfigCacheTest, fix_device_type_inconsistency_test) {
+TEST(ConfigCacheTest, fix_device_type_inconsistency_missing_devtype_no_keys_test) {
   ConfigCache config(100, Device::kLinkKeyProperties);
   config.SetProperty("A", "B", "C");
   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
-  ASSERT_TRUE(config.FixDeviceTypeInconsistencies());
+
+  auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
+
+  ASSERT_TRUE(hadInconsistencies);
   ASSERT_THAT(
       config.GetProperty("AA:BB:CC:DD:EE:FF", "DevType"),
       Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::BR_EDR))));
+}
+
+TEST(ConfigCacheTest, fix_device_type_inconsistency_consistent_devtype_test) {
+  // arrange
+  ConfigCache config(100, Device::kLinkKeyProperties);
+  config.SetProperty("A", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
+
   config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
   config.SetProperty("CC:DD:EE:FF:00:11", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
   config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
-  ASSERT_FALSE(config.FixDeviceTypeInconsistencies());
+
+  // act
+  auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
+
+  // assert
+  ASSERT_FALSE(hadInconsistencies);
   ASSERT_THAT(
       config.GetProperty("CC:DD:EE:FF:00:11", "DevType"),
       Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::BR_EDR))));
+}
+
+TEST(ConfigCacheTest, fix_device_type_inconsistency_devtype_should_be_dual_test) {
+  // arrange
+  ConfigCache config(100, Device::kLinkKeyProperties);
+  config.SetProperty("A", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
+
+  config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
+  config.SetProperty("CC:DD:EE:FF:00:11", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
+  config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
   config.SetProperty("CC:DD:EE:FF:00:11", "LE_KEY_PENC", "AABBAABBCCDDEE");
-  ASSERT_TRUE(config.FixDeviceTypeInconsistencies());
+
+  // act
+  auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
+
+  // assert
+  ASSERT_TRUE(hadInconsistencies);
   ASSERT_THAT(
       config.GetProperty("CC:DD:EE:FF:00:11", "DevType"),
       Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::DUAL))));
-  config.RemoveProperty("CC:DD:EE:FF:00:11", "LinkKey");
-  ASSERT_TRUE(config.FixDeviceTypeInconsistencies());
+}
+
+TEST(ConfigCacheTest, fix_device_type_inconsistency_devtype_should_be_le_not_classic_test) {
+  // arrange
+  ConfigCache config(100, Device::kLinkKeyProperties);
+  config.SetProperty("A", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
+
+  config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
+  config.SetProperty("CC:DD:EE:FF:00:11", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
+  config.SetProperty("CC:DD:EE:FF:00:11", "LE_KEY_PENC", "AABBAABBCCDDEE");
+
+  // act
+  auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
+
+  // assert
+  ASSERT_TRUE(hadInconsistencies);
   ASSERT_THAT(
       config.GetProperty("CC:DD:EE:FF:00:11", "DevType"),
       Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::LE))));
 }
 
+TEST(ConfigCacheTest, fix_device_type_inconsistency_devtype_dont_override_dual_test) {
+  // arrange
+  ConfigCache config(100, Device::kLinkKeyProperties);
+  config.SetProperty("A", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+  config.SetProperty("AA:BB:CC:DD:EE:FF", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
+
+  config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
+  config.SetProperty("CC:DD:EE:FF:00:11", "DevType", std::to_string(bluetooth::hci::DeviceType::DUAL));
+  config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+  config.SetProperty("CC:DD:EE:FF:00:11", "LE_KEY_PENC", "AABBAABBCCDDEE");
+
+  // act
+  auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
+
+  // assert
+  ASSERT_FALSE(hadInconsistencies);
+  ASSERT_THAT(
+      config.GetProperty("CC:DD:EE:FF:00:11", "DevType"),
+      Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::DUAL))));
+}
+
 TEST(ConfigCacheTest, test_get_section_with_property) {
   ConfigCache config(100, Device::kLinkKeyProperties);
   config.SetProperty("A", "B", "C");