Add additional check on float precision after parsing, only compile the
value when precision is not lost.

Bug: b/69347762
Test: Verified affected atests pass
Change-Id: I8e4fcd420a924f0e949bfd3a8aae23d1e7d582b1
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 5a118a9..e670f38 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -670,8 +670,19 @@
     // Try parsing this as a float.
     auto floating_point = TryParseFloat(value);
     if (floating_point) {
+      // Only check if the parsed result lost precision when the parsed item is
+      // android::Res_value::TYPE_FLOAT and there is other possible types saved in type_mask, like
+      // ResTable_map::TYPE_INTEGER.
       if (type_mask & AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
-        return std::move(floating_point);
+        const bool mayOnlyBeFloat = (type_mask & ~float_mask) == 0;
+        const bool parsedAsFloat = floating_point->value.dataType == android::Res_value::TYPE_FLOAT;
+        if (!mayOnlyBeFloat && parsedAsFloat) {
+          if (floating_point->toPrettyString() == value.data()) {
+            return std::move(floating_point);
+          }
+        } else {
+          return std::move(floating_point);
+        }
       }
     }
   }
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index 568871a..ffc6795 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -228,6 +228,21 @@
               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened))));
 }
 
+TEST(ResourceUtilsTest, FloatAndBigIntegerParsedCorrectly) {
+  const float expected_float = 0.125f;
+  const uint32_t expected_float_flattened = *(uint32_t*)&expected_float;
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute("0.125", ResTable_map::TYPE_FLOAT),
+              Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened))));
+
+  EXPECT_EQ(ResourceUtils::TryParseItemForAttribute("1099511627776", ResTable_map::TYPE_INTEGER),
+            std::unique_ptr<Item>(nullptr));
+
+  const float big_float = 1099511627776.0f;
+  const uint32_t big_flattened = *(uint32_t*)&big_float;
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute("1099511627776", ResTable_map::TYPE_FLOAT),
+              Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, big_flattened))));
+}
+
 TEST(ResourceUtilsTest, ParseSdkVersionWithCodename) {
   EXPECT_THAT(ResourceUtils::ParseSdkVersion("Q"), Eq(std::optional<int>(10000)));
   EXPECT_THAT(ResourceUtils::ParseSdkVersion("Q.fingerprint"), Eq(std::optional<int>(10000)));
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index a5754e0..728e35a 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -22,12 +22,12 @@
 #include <set>
 #include <sstream>
 
-#include "android-base/stringprintf.h"
-#include "androidfw/ResourceTypes.h"
-
 #include "Resource.h"
 #include "ResourceUtils.h"
 #include "ValueVisitor.h"
+#include "android-base/stringprintf.h"
+#include "androidfw/ResourceTypes.h"
+#include "io/StringStream.h"
 #include "util/Util.h"
 
 using ::aapt::text::Printer;
@@ -487,6 +487,15 @@
   }
 }
 
+std::string BinaryPrimitive::toPrettyString() const {
+  std::string str;
+  io::StringOutputStream out(&str);
+  text::Printer printer(&out);
+  this->PrettyPrint(&printer);
+  out.Flush();
+  return str;
+}
+
 Attribute::Attribute(uint32_t t)
     : type_mask(t),
       min_int(std::numeric_limits<int32_t>::min()),
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 6f9dccb..daf8814 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -285,6 +285,7 @@
   bool Flatten(android::Res_value* out_value) const override;
   void Print(std::ostream* out) const override;
   void PrettyPrint(text::Printer* printer) const override;
+  std::string toPrettyString() const;
 };
 
 struct Attribute : public TransformableValue<Attribute, BaseValue<Attribute>> {