diff options
Diffstat (limited to 'tools')
190 files changed, 23761 insertions, 1139 deletions
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index 40cba3ed316f..412aa9bf88ab 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -47,6 +47,7 @@ cc_defaults { "-Wno-missing-field-initializers", "-fno-exceptions", "-fno-rtti", + "-Wno-deprecated-declarations", ], target: { windows: { @@ -220,6 +221,7 @@ genrule { name: "aapt2-protos", tools: [":soong_zip"], srcs: [ + "ApkInfo.proto", "Configuration.proto", "ResourcesInternal.proto", "ResourceMetadata.proto", diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index 9cfb85d7cd73..6a17ef85a755 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -265,6 +265,16 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& ValueHeadlinePrinter headline_printer(package.name, printer); ValueBodyPrinter body_printer(package.name, printer); + auto& dynamicRefTable = table.GetReferencedPackages(); + if (!dynamicRefTable.empty()) { + printer->Println(StringPrintf("DynamicRefTable entryCount=%d", int(dynamicRefTable.size()))); + printer->Indent(); + for (auto&& [id, name] : dynamicRefTable) { + printer->Println(StringPrintf("0x%02x -> %s", id, name.c_str())); + } + printer->Undent(); + } + printer->Print("Package name="); printer->Print(package.name); if (package.id) { diff --git a/tools/aapt2/LoadedApk.h b/tools/aapt2/LoadedApk.h index 4cd7eae0a5e2..27c354a7b08e 100644 --- a/tools/aapt2/LoadedApk.h +++ b/tools/aapt2/LoadedApk.h @@ -40,10 +40,8 @@ enum ApkFormat { }; // Info about an APK loaded in memory. -class LoadedApk { +class LoadedApk final { public: - virtual ~LoadedApk() = default; - // Loads both binary and proto APKs from disk. static std::unique_ptr<LoadedApk> LoadApkFromPath(android::StringPiece path, android::IDiagnostics* diag); @@ -96,8 +94,8 @@ class LoadedApk { * Writes the APK on disk at the given path, while also removing the resource * files that are not referenced in the resource table. */ - virtual bool WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options, - IArchiveWriter* writer); + bool WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options, + IArchiveWriter* writer); /** * Writes the APK on disk at the given path, while also removing the resource files that are not @@ -108,9 +106,9 @@ class LoadedApk { * original manifest will be written. The manifest is only required if the contents of the new APK * have been modified in a way that require the AndroidManifest.xml to also be modified. */ - virtual bool WriteToArchive(IAaptContext* context, ResourceTable* split_table, - const TableFlattenerOptions& options, FilterChain* filters, - IArchiveWriter* writer, xml::XmlResource* manifest = nullptr); + bool WriteToArchive(IAaptContext* context, ResourceTable* split_table, + const TableFlattenerOptions& options, FilterChain* filters, + IArchiveWriter* writer, xml::XmlResource* manifest = nullptr); /** Loads the file as an xml document. */ std::unique_ptr<xml::XmlResource> LoadXml(const std::string& file_path, diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index fa9a98f136cb..6af39b739e9b 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -800,7 +800,7 @@ std::unique_ptr<Item> ResourceParser::ParseXml(const FlattenedXmlSubTree& xmlsub // Process the raw value. std::unique_ptr<Item> processed_item = ResourceUtils::TryParseItemForAttribute( - xmlsub_tree.raw_value, type_mask, on_create_reference); + &diag, xmlsub_tree.raw_value, type_mask, on_create_reference); if (processed_item) { // Fix up the reference. if (auto ref = ValueCast<Reference>(processed_item.get())) { diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index bb286a8abdaa..61e399c7ab68 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -307,6 +307,11 @@ class ResourceTable { // order. ResourceTableView GetPartitionedView(const ResourceTableViewOptions& options = {}) const; + using ReferencedPackages = std::map<uint8_t, std::string>; + const ReferencedPackages& GetReferencedPackages() const { + return included_packages_; + } + struct SearchResult { ResourceTablePackage* package; ResourceTableType* type; @@ -342,7 +347,7 @@ class ResourceTable { // Set of dynamic packages that this table may reference. Their package names get encoded // into the resources.arsc along with their compile-time assigned IDs. - std::map<size_t, std::string> included_packages_; + ReferencedPackages included_packages_; private: DISALLOW_COPY_AND_ASSIGN(ResourceTable); diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index 5a118a902963..d358df98ada6 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -619,7 +619,7 @@ uint32_t AndroidTypeToAttributeTypeMask(uint16_t type) { } std::unique_ptr<Item> TryParseItemForAttribute( - StringPiece value, uint32_t type_mask, + android::IDiagnostics* diag, StringPiece value, uint32_t type_mask, const std::function<bool(const ResourceName&)>& on_create_reference) { using android::ResTable_map; @@ -670,8 +670,32 @@ std::unique_ptr<Item> TryParseItemForAttribute( // 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) { + float f = reinterpret_cast<float&>(floating_point->value.data); + std::u16string str16 = android::util::Utf8ToUtf16(util::TrimWhitespace(value)); + double d; + if (android::ResTable::stringToDouble(str16.data(), str16.size(), d)) { + // Parse as a float only if the difference between float and double parsed from the + // same string is smaller than 1, otherwise return as raw string. + if (fabs(f - d) < 1) { + return std::move(floating_point); + } else { + if (diag->IsVerbose()) { + diag->Note(android::DiagMessage() + << "precision lost greater than 1 while parsing float " << value + << ", return a raw string"); + } + } + } + } else { + return std::move(floating_point); + } } } } @@ -683,12 +707,12 @@ std::unique_ptr<Item> TryParseItemForAttribute( * allows. */ std::unique_ptr<Item> TryParseItemForAttribute( - StringPiece str, const Attribute* attr, + android::IDiagnostics* diag, StringPiece str, const Attribute* attr, const std::function<bool(const ResourceName&)>& on_create_reference) { using android::ResTable_map; const uint32_t type_mask = attr->type_mask; - auto value = TryParseItemForAttribute(str, type_mask, on_create_reference); + auto value = TryParseItemForAttribute(diag, str, type_mask, on_create_reference); if (value) { return value; } diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h index f30f4acfec7a..50fc87900162 100644 --- a/tools/aapt2/ResourceUtils.h +++ b/tools/aapt2/ResourceUtils.h @@ -200,11 +200,11 @@ std::unique_ptr<BinaryPrimitive> TryParseFlagSymbol(const Attribute* enum_attr, * reference to an ID that must be created (@+id/foo). */ std::unique_ptr<Item> TryParseItemForAttribute( - android::StringPiece value, const Attribute* attr, + android::IDiagnostics* diag, android::StringPiece value, const Attribute* attr, const std::function<bool(const ResourceName&)>& on_create_reference = {}); std::unique_ptr<Item> TryParseItemForAttribute( - android::StringPiece value, uint32_t type_mask, + android::IDiagnostics* diag, android::StringPiece value, uint32_t type_mask, const std::function<bool(const ResourceName&)>& on_create_reference = {}); uint32_t AndroidTypeToAttributeTypeMask(uint16_t type); diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp index 568871a4d66e..4cba04de72ee 100644 --- a/tools/aapt2/ResourceUtils_test.cpp +++ b/tools/aapt2/ResourceUtils_test.cpp @@ -217,17 +217,46 @@ TEST(ResourceUtilsTest, EmptyIsBinaryPrimitive) { } TEST(ResourceUtilsTest, ItemsWithWhitespaceAreParsedCorrectly) { - EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" 12\n ", ResTable_map::TYPE_INTEGER), + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), " 12\n ", + ResTable_map::TYPE_INTEGER), Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_INT_DEC, 12u)))); - EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" true\n ", ResTable_map::TYPE_BOOLEAN), + EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), " true\n ", + ResTable_map::TYPE_BOOLEAN), Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_INT_BOOLEAN, 0xffffffffu)))); const float expected_float = 12.0f; const uint32_t expected_float_flattened = *(uint32_t*)&expected_float; - EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" 12.0\n ", ResTable_map::TYPE_FLOAT), + EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), " 12.0\n ", + ResTable_map::TYPE_FLOAT), Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened)))); } +TEST(ResourceUtilsTest, FloatAndBigIntegerParsedCorrectly) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + const float expected_float = 0.125f; + const uint32_t expected_float_flattened = *(uint32_t*)&expected_float; + EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), "0.125", + ResTable_map::TYPE_FLOAT), + Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened)))); + + const float special_float = 1.0f; + const uint32_t special_float_flattened = *(uint32_t*)&special_float; + EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), "1.0", + ResTable_map::TYPE_FLOAT), + Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, special_float_flattened)))); + + EXPECT_EQ(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), "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(context->GetDiagnostics(), "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 a5754e0d168f..166b01bd9154 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -439,6 +439,21 @@ static std::string ComplexToString(uint32_t complex_value, bool fraction) { return str; } +// This function is designed to using different specifier to print different floats, +// which can print more accurate format rather than using %g only. +const char* BinaryPrimitive::DecideFormat(float f) { + // if the float is either too big or too tiny, print it in scientific notation. + // eg: "10995116277760000000000" to 1.099512e+22, "0.00000000001" to 1.000000e-11 + if (fabs(f) > std::numeric_limits<int64_t>::max() || fabs(f) < 1e-10) { + return "%e"; + // Else if the number is an integer exactly, print it without trailing zeros. + // eg: "1099511627776" to 1099511627776 + } else if (int64_t(f) == f) { + return "%.0f"; + } + return "%g"; +} + void BinaryPrimitive::PrettyPrint(Printer* printer) const { using ::android::Res_value; switch (value.dataType) { @@ -470,7 +485,9 @@ void BinaryPrimitive::PrettyPrint(Printer* printer) const { break; case Res_value::TYPE_FLOAT: - printer->Print(StringPrintf("%g", *reinterpret_cast<const float*>(&value.data))); + float f; + f = *reinterpret_cast<const float*>(&value.data); + printer->Print(StringPrintf(DecideFormat(f), f)); break; case Res_value::TYPE_DIMENSION: diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h index 6f9dccbd3bcc..5192c2be1f98 100644 --- a/tools/aapt2/ResourceValues.h +++ b/tools/aapt2/ResourceValues.h @@ -284,6 +284,7 @@ struct BinaryPrimitive : public TransformableItem<BinaryPrimitive, BaseItem<Bina bool Equals(const Value* value) const override; bool Flatten(android::Res_value* out_value) const override; void Print(std::ostream* out) const override; + static const char* DecideFormat(float f); void PrettyPrint(text::Printer* printer) const override; }; diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index a766bd437120..83f2eb31aa57 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -16,20 +16,24 @@ #include "SdkConstants.h" +#include <stdint.h> + #include <algorithm> #include <string> -#include <unordered_set> -#include <vector> +#include <string_view> using android::StringPiece; +using namespace std::literals; namespace aapt { -static ApiVersion sDevelopmentSdkLevel = 10000; -static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>( - {"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake", "VanillaIceCream"}); +static constexpr ApiVersion sDevelopmentSdkLevel = 10000; +static constexpr StringPiece sDevelopmentSdkCodeNames[] = { + "Q"sv, "R"sv, "S"sv, "Sv2"sv, "Tiramisu"sv, "UpsideDownCake"sv, "VanillaIceCream"sv}; + +static constexpr auto sPrivacySandboxSuffix = "PrivacySandbox"sv; -static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = { +static constexpr std::pair<uint16_t, ApiVersion> sAttrIdMap[] = { {0x021c, 1}, {0x021d, 2}, {0x0269, SDK_CUPCAKE}, @@ -62,25 +66,37 @@ static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = { {0x064c, SDK_S_V2}, }; -static bool less_entry_id(const std::pair<uint16_t, ApiVersion>& p, uint16_t entryId) { - return p.first < entryId; -} +static_assert(std::is_sorted(std::begin(sAttrIdMap), std::end(sAttrIdMap), + [](auto&& l, auto&& r) { return l.first < r.first; })); ApiVersion FindAttributeSdkLevel(const ResourceId& id) { if (id.package_id() != 0x01 || id.type_id() != 0x01) { return 0; } - auto iter = std::lower_bound(sAttrIdMap.begin(), sAttrIdMap.end(), id.entry_id(), less_entry_id); - if (iter == sAttrIdMap.end()) { + const auto it = + std::lower_bound(std::begin(sAttrIdMap), std::end(sAttrIdMap), id.entry_id(), + [](const auto& pair, uint16_t entryId) { return pair.first < entryId; }); + if (it == std::end(sAttrIdMap)) { return SDK_LOLLIPOP_MR1; } - return iter->second; + return it->second; } std::optional<ApiVersion> GetDevelopmentSdkCodeNameVersion(StringPiece code_name) { - return (sDevelopmentSdkCodeNames.find(code_name) == sDevelopmentSdkCodeNames.end()) - ? std::optional<ApiVersion>() - : sDevelopmentSdkLevel; + const auto it = + std::find_if(std::begin(sDevelopmentSdkCodeNames), std::end(sDevelopmentSdkCodeNames), + [code_name](const auto& item) { return code_name.starts_with(item); }); + if (it == std::end(sDevelopmentSdkCodeNames)) { + return {}; + } + if (code_name.size() == it->size()) { + return sDevelopmentSdkLevel; + } + if (code_name.size() == it->size() + sPrivacySandboxSuffix.size() && + code_name.ends_with(sPrivacySandboxSuffix)) { + return sDevelopmentSdkLevel; + } + return {}; } } // namespace aapt diff --git a/tools/aapt2/SdkConstants_test.cpp b/tools/aapt2/SdkConstants_test.cpp index 61f4d71b7fb2..0f645ffc1e8b 100644 --- a/tools/aapt2/SdkConstants_test.cpp +++ b/tools/aapt2/SdkConstants_test.cpp @@ -28,4 +28,24 @@ TEST(SdkConstantsTest, NonFrameworkAttributeIsSdk0) { EXPECT_EQ(0, FindAttributeSdkLevel(ResourceId(0x7f010345))); } +TEST(SdkConstantsTest, GetDevelopmentSdkCodeNameVersionValid) { + EXPECT_EQ(std::optional<ApiVersion>(10000), GetDevelopmentSdkCodeNameVersion("Q")); + EXPECT_EQ(std::optional<ApiVersion>(10000), GetDevelopmentSdkCodeNameVersion("VanillaIceCream")); +} + +TEST(SdkConstantsTest, GetDevelopmentSdkCodeNameVersionPrivacySandbox) { + EXPECT_EQ(std::optional<ApiVersion>(10000), GetDevelopmentSdkCodeNameVersion("QPrivacySandbox")); + EXPECT_EQ(std::optional<ApiVersion>(10000), + GetDevelopmentSdkCodeNameVersion("VanillaIceCreamPrivacySandbox")); +} + +TEST(SdkConstantsTest, GetDevelopmentSdkCodeNameVersionInvalid) { + EXPECT_EQ(std::optional<ApiVersion>(), GetDevelopmentSdkCodeNameVersion("A")); + EXPECT_EQ(std::optional<ApiVersion>(), GetDevelopmentSdkCodeNameVersion("Sv3")); + EXPECT_EQ(std::optional<ApiVersion>(), + GetDevelopmentSdkCodeNameVersion("VanillaIceCream_PrivacySandbox")); + EXPECT_EQ(std::optional<ApiVersion>(), GetDevelopmentSdkCodeNameVersion("PrivacySandbox")); + EXPECT_EQ(std::optional<ApiVersion>(), GetDevelopmentSdkCodeNameVersion("QQQQQQQQQQQQQQQ")); +} + } // namespace aapt diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index bb7b13a71412..728ba8aa4fdd 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -196,7 +196,20 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, // These are created as weak symbols, and are only generated from default // configuration // strings and plurals. - PseudolocaleGenerator pseudolocale_generator; + std::string grammatical_gender_values; + std::string grammatical_gender_ratio; + if (options.pseudo_localize_gender_values) { + grammatical_gender_values = options.pseudo_localize_gender_values.value(); + } else { + grammatical_gender_values = "f,m,n"; + } + if (options.pseudo_localize_gender_ratio) { + grammatical_gender_ratio = options.pseudo_localize_gender_ratio.value(); + } else { + grammatical_gender_ratio = "1.0"; + } + PseudolocaleGenerator pseudolocale_generator(grammatical_gender_values, + grammatical_gender_ratio); if (!pseudolocale_generator.Consume(context, &table)) { return false; } @@ -607,6 +620,7 @@ class CompileContext : public IAaptContext { void SetVerbose(bool val) { verbose_ = val; + diagnostics_->SetVerbose(val); } bool IsVerbose() override { diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h index 984d8901ac56..61c5b60adb76 100644 --- a/tools/aapt2/cmd/Compile.h +++ b/tools/aapt2/cmd/Compile.h @@ -35,6 +35,8 @@ struct CompileOptions { std::optional<std::string> res_dir; std::optional<std::string> res_zip; std::optional<std::string> generate_text_symbols_path; + std::optional<std::string> pseudo_localize_gender_values; + std::optional<std::string> pseudo_localize_gender_ratio; std::optional<Visibility::Level> visibility; bool pseudolocalize = false; bool no_png_crunch = false; @@ -77,6 +79,15 @@ class CompileCommand : public Command { AddOptionalFlag("--source-path", "Sets the compiled resource file source file path to the given string.", &options_.source_path); + AddOptionalFlag("--pseudo-localize-gender-values", + "Sets the gender values to pick up for generating grammatical gender strings, " + "gender values should be f, m, or n, which are shortcuts for feminine, " + "masculine and neuter, and split with comma.", + &options_.pseudo_localize_gender_values); + AddOptionalFlag("--pseudo-localize-gender-ratio", + "Sets the ratio of resources to generate grammatical gender strings for. The " + "ratio has to be a float number between 0 and 1.", + &options_.pseudo_localize_gender_ratio); AddOptionalFlag("--filter-product", "Leave only resources specific to the given product. All " "other resources (including defaults) are removed.", diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp index 3464a7662c60..8880089d0e20 100644 --- a/tools/aapt2/cmd/Compile_test.cpp +++ b/tools/aapt2/cmd/Compile_test.cpp @@ -236,9 +236,24 @@ TEST_F(CompilerTest, DoNotTranslateTest) { // The first string (000) is translatable, the second is not // ar-XB uses "\u200F\u202E...\u202C\u200F" std::vector<std::string> expected_translatable = { - "000", "111", // default locale - "[000 one]", // en-XA - "\xE2\x80\x8F\xE2\x80\xAE" "000" "\xE2\x80\xAC\xE2\x80\x8F", // ar-XB + "(F)[000 one]", // en-XA-feminine + "(F)\xE2\x80\x8F\xE2\x80\xAE" + "000" + "\xE2\x80\xAC\xE2\x80\x8F", // ar-XB-feminine + "(M)[000 one]", // en-XA-masculine + "(M)\xE2\x80\x8F\xE2\x80\xAE" + "000" + "\xE2\x80\xAC\xE2\x80\x8F", // ar-XB-masculine + "(N)[000 one]", // en-XA-neuter + "(N)\xE2\x80\x8F\xE2\x80\xAE" + "000" + "\xE2\x80\xAC\xE2\x80\x8F", // ar-XB-neuter + "000", // default locale + "111", // default locale + "[000 one]", // en-XA + "\xE2\x80\x8F\xE2\x80\xAE" + "000" + "\xE2\x80\xAC\xE2\x80\x8F", // ar-XB }; AssertTranslations(this, "foo", expected_translatable); AssertTranslations(this, "foo_donottranslate", expected_translatable); diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp index 7381a85f4339..387dcfe2ddf3 100644 --- a/tools/aapt2/cmd/Convert.cpp +++ b/tools/aapt2/cmd/Convert.cpp @@ -425,6 +425,7 @@ int ConvertCommand::Action(const std::vector<std::string>& args) { if (force_sparse_encoding_) { table_flattener_options_.sparse_entries = SparseEntriesMode::Forced; } + table_flattener_options_.use_compact_entries = enable_compact_entries_; if (resources_config_path_) { if (!ExtractResourceConfig(*resources_config_path_, &context, table_flattener_options_)) { return 1; diff --git a/tools/aapt2/cmd/Convert.h b/tools/aapt2/cmd/Convert.h index 15fe11fd91cc..9452e588953e 100644 --- a/tools/aapt2/cmd/Convert.h +++ b/tools/aapt2/cmd/Convert.h @@ -46,6 +46,10 @@ class ConvertCommand : public Command { "This decreases APK size at the cost of resource retrieval performance.\n" "Applies sparse encoding to all resources regardless of minSdk.", &force_sparse_encoding_); + AddOptionalSwitch( + "--enable-compact-entries", + "This decreases APK size by using compact resource entries for simple data types.", + &enable_compact_entries_); AddOptionalSwitch("--keep-raw-values", android::base::StringPrintf("Preserve raw attribute values in xml files when using the" " '%s' output format", kOutputFormatBinary), @@ -85,6 +89,7 @@ class ConvertCommand : public Command { bool verbose_ = false; bool enable_sparse_encoding_ = false; bool force_sparse_encoding_ = false; + bool enable_compact_entries_ = false; std::optional<std::string> resources_config_path_; }; diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp index 71b08022f688..864af06f187e 100644 --- a/tools/aapt2/cmd/Dump.cpp +++ b/tools/aapt2/cmd/Dump.cpp @@ -112,6 +112,7 @@ class DumpContext : public IAaptContext { void SetVerbose(bool val) { verbose_ = val; + diagnostics_.SetVerbose(val); } int GetMinSdkVersion() override { diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 1fb5cc0919a3..c638873873dc 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -149,6 +149,7 @@ class LinkContext : public IAaptContext { void SetVerbose(bool val) { verbose_ = val; + diagnostics_->SetVerbose(val); } int GetMinSdkVersion() override { diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp index 725a1b86f616..7096f5cc54e3 100644 --- a/tools/aapt2/cmd/Link_test.cpp +++ b/tools/aapt2/cmd/Link_test.cpp @@ -441,8 +441,8 @@ static void BuildNonFinalizedSDK(const std::string& apk_path, const std::string& R"(<resources> <public type="attr" name="finalized_res" id="0x01010001"/> - <!-- S staged attributes (support staged resources in the same type id) --> - <staging-public-group type="attr" first-id="0x01010050"> + <!-- S staged attributes (Not support staged resources in the same type id) --> + <staging-public-group type="attr" first-id="0x01fc0050"> <public name="staged_s_res" /> </staging-public-group> @@ -480,8 +480,8 @@ static void BuildFinalizedSDK(const std::string& apk_path, const std::string& ja <public type="attr" name="staged_s2_res" id="0x01010003"/> <public type="string" name="staged_s_string" id="0x01020000"/> - <!-- S staged attributes (support staged resources in the same type id) --> - <staging-public-group-final type="attr" first-id="0x01010050"> + <!-- S staged attributes (Not support staged resources in the same type id) --> + <staging-public-group-final type="attr" first-id="0x01fc0050"> <public name="staged_s_res" /> </staging-public-group-final> @@ -551,7 +551,7 @@ TEST_F(LinkTest, StagedAndroidApi) { EXPECT_THAT(android_r_contents, HasSubstr("public static final int finalized_res=0x01010001;")); EXPECT_THAT( android_r_contents, - HasSubstr("public static final int staged_s_res; static { staged_s_res=0x01010050; }")); + HasSubstr("public static final int staged_s_res; static { staged_s_res=0x01fc0050; }")); EXPECT_THAT( android_r_contents, HasSubstr("public static final int staged_s_string; static { staged_s_string=0x01fd0080; }")); @@ -583,7 +583,7 @@ TEST_F(LinkTest, StagedAndroidApi) { result = am.GetResourceId("android:attr/staged_s_res"); ASSERT_TRUE(result.has_value()); - EXPECT_THAT(*result, Eq(0x01010050)); + EXPECT_THAT(*result, Eq(0x01fc0050)); result = am.GetResourceId("android:string/staged_s_string"); ASSERT_TRUE(result.has_value()); diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index dbe79701bf5c..f045dad6d11a 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -101,6 +101,7 @@ class OptimizeContext : public IAaptContext { void SetVerbose(bool val) { verbose_ = val; + diagnostics_.SetVerbose(val); } void SetMinSdkVersion(int sdk_version) { diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp index b3f98a9d3e30..5421abde3689 100644 --- a/tools/aapt2/compile/IdAssigner.cpp +++ b/tools/aapt2/compile/IdAssigner.cpp @@ -37,6 +37,7 @@ using Result = expected<T, std::string>; template <typename Id, typename Key> struct NextIdFinder { + std::map<Id, Key> pre_assigned_ids_; explicit NextIdFinder(Id start_id = 0u) : next_id_(start_id){}; // Attempts to reserve an identifier for the specified key. @@ -55,7 +56,6 @@ struct NextIdFinder { Id next_id_; bool next_id_called_ = false; bool exhausted_ = false; - std::map<Id, Key> pre_assigned_ids_; typename std::map<Id, Key>::iterator next_preassigned_id_; }; @@ -158,7 +158,7 @@ bool IdAssigner::Consume(IAaptContext* context, ResourceTable* table) { } if (assigned_id_map_) { - // Reserve all the IDs mentioned in the stable ID map. That way we won't assig IDs that were + // Reserve all the IDs mentioned in the stable ID map. That way we won't assign IDs that were // listed in the map if they don't exist in the table. for (const auto& stable_id_entry : *assigned_id_map_) { const ResourceName& pre_assigned_name = stable_id_entry.first; @@ -191,6 +191,11 @@ bool IdAssigner::Consume(IAaptContext* context, ResourceTable* table) { } namespace { +static const std::string_view staged_type_overlap_error = + "Staged public resource type IDs have conflict with non staged public resources type " + "IDs, please restart staged resource type ID assignment at 0xff in public-staging.xml " + "and also delete all the overlapping groups in public-final.xml"; + template <typename Id, typename Key> Result<Id> NextIdFinder<Id, Key>::ReserveId(Key key, Id id) { CHECK(!next_id_called_) << "ReserveId cannot be called after NextId"; @@ -282,8 +287,20 @@ bool IdAssignerContext::ReserveId(const ResourceName& name, ResourceId id, // another type. auto assign_result = type_id_finder_.ReserveId(key, id.type_id()); if (!assign_result.has_value()) { - diag->Error(android::DiagMessage() << "can't assign ID " << id << " to resource " << name - << " because type " << assign_result.error()); + auto pre_assigned_type = type_id_finder_.pre_assigned_ids_[id.type_id()].type; + bool pre_assigned_type_staged = + non_staged_type_ids_.find(pre_assigned_type) == non_staged_type_ids_.end(); + auto hex_type_id = fmt::format("{:#04x}", (int)id.type_id()); + bool current_type_staged = visibility.staged_api; + diag->Error(android::DiagMessage() + << "can't assign type ID " << hex_type_id << " to " + << (current_type_staged ? "staged type " : "non staged type ") << name.type.type + << " because this type ID have been assigned to " + << (pre_assigned_type_staged ? "staged type " : "non staged type ") + << pre_assigned_type); + if (pre_assigned_type_staged || current_type_staged) { + diag->Error(android::DiagMessage() << staged_type_overlap_error); + } return false; } type = types_.emplace(key, TypeGroup(package_id_, id.type_id())).first; @@ -298,6 +315,20 @@ bool IdAssignerContext::ReserveId(const ResourceName& name, ResourceId id, << " because type already has ID " << std::hex << (int)id.type_id()); return false; } + } else { + // Ensure that staged public resources cannot have the same type name and type id with + // non staged public resources. + auto non_staged_type = non_staged_type_ids_.find(name.type.type); + if (non_staged_type != non_staged_type_ids_.end() && non_staged_type->second == id.type_id()) { + diag->Error( + android::DiagMessage() + << "can`t assign type ID " << fmt::format("{:#04x}", (int)id.type_id()) + << " to staged type " << name.type.type << " because type ID " + << fmt::format("{:#04x}", (int)id.type_id()) + << " already has been assigned to a non staged resource type with the same type name"); + diag->Error(android::DiagMessage() << staged_type_overlap_error); + return false; + } } auto assign_result = type->second.ReserveId(name, id); diff --git a/tools/aapt2/compile/IdAssigner_test.cpp b/tools/aapt2/compile/IdAssigner_test.cpp index 8911dad39470..ce45b7c1df04 100644 --- a/tools/aapt2/compile/IdAssigner_test.cpp +++ b/tools/aapt2/compile/IdAssigner_test.cpp @@ -117,14 +117,28 @@ TEST_F(IdAssignerTests, FailWhenTypeHasTwoNonStagedIds) { } TEST_F(IdAssignerTests, FailWhenTypeHasTwoNonStagedIdsRegardlessOfStagedId) { - auto table = test::ResourceTableBuilder() - .AddSimple("android:attr/foo", ResourceId(0x01050000)) - .AddSimple("android:attr/bar", ResourceId(0x01ff0006)) - .Add(NewResourceBuilder("android:attr/staged_baz") - .SetId(0x01ff0000) - .SetVisibility({.staged_api = true}) - .Build()) - .Build(); + auto table = + test::ResourceTableBuilder() + .AddSimple("android:attr/foo", ResourceId(0x01050000)) + .AddSimple("android:attr/bar", ResourceId(0x01ff0006)) + .Add(NewResourceBuilder("android:attr/staged_baz") + .SetId(0x01ff0000) + .SetVisibility({.staged_api = true, .level = Visibility::Level::kPublic}) + .Build()) + .Build(); + IdAssigner assigner; + ASSERT_FALSE(assigner.Consume(context.get(), table.get())); +} + +TEST_F(IdAssignerTests, FailWhenTypeHaveBothStagedAndNonStagedIds) { + auto table = + test::ResourceTableBuilder() + .AddSimple("android:attr/foo", ResourceId(0x01010000)) + .Add(NewResourceBuilder("android:bool/staged_baz") + .SetId(0x01010001) + .SetVisibility({.staged_api = true, .level = Visibility::Level::kPublic}) + .Build()) + .Build(); IdAssigner assigner; ASSERT_FALSE(assigner.Consume(context.get(), table.get())); } diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp index 09a8560f984a..8143052f4376 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp @@ -16,11 +16,15 @@ #include "compile/PseudolocaleGenerator.h" +#include <stdint.h> + #include <algorithm> +#include <random> #include "ResourceTable.h" #include "ResourceValues.h" #include "ValueVisitor.h" +#include "androidfw/ResourceTypes.h" #include "androidfw/Util.h" #include "compile/Pseudolocalizer.h" #include "util/Util.h" @@ -293,8 +297,85 @@ class Visitor : public ValueVisitor { Pseudolocalizer localizer_; }; +class GrammaticalGenderVisitor : public ValueVisitor { + public: + std::unique_ptr<Value> value; + std::unique_ptr<Item> item; + + GrammaticalGenderVisitor(android::StringPool* pool, uint8_t grammaticalInflection) + : pool_(pool), grammaticalInflection_(grammaticalInflection) { + } + + void Visit(Plural* plural) override { + CloningValueTransformer cloner(pool_); + std::unique_ptr<Plural> grammatical_gendered = util::make_unique<Plural>(); + for (size_t i = 0; i < plural->values.size(); i++) { + if (plural->values[i]) { + GrammaticalGenderVisitor sub_visitor(pool_, grammaticalInflection_); + plural->values[i]->Accept(&sub_visitor); + if (sub_visitor.item) { + grammatical_gendered->values[i] = std::move(sub_visitor.item); + } else { + grammatical_gendered->values[i] = plural->values[i]->Transform(cloner); + } + } + } + grammatical_gendered->SetSource(plural->GetSource()); + grammatical_gendered->SetWeak(true); + value = std::move(grammatical_gendered); + } + + std::string AddGrammaticalGenderPrefix(const std::string_view& original_string) { + std::string result; + switch (grammaticalInflection_) { + case android::ResTable_config::GRAMMATICAL_GENDER_MASCULINE: + result = std::string("(M)") + std::string(original_string); + break; + case android::ResTable_config::GRAMMATICAL_GENDER_FEMININE: + result = std::string("(F)") + std::string(original_string); + break; + case android::ResTable_config::GRAMMATICAL_GENDER_NEUTER: + result = std::string("(N)") + std::string(original_string); + break; + default: + result = std::string(original_string); + break; + } + return result; + } + + void Visit(String* string) override { + std::string prefixed_string = AddGrammaticalGenderPrefix(std::string(*string->value)); + std::unique_ptr<String> grammatical_gendered = + util::make_unique<String>(pool_->MakeRef(prefixed_string)); + grammatical_gendered->SetSource(string->GetSource()); + grammatical_gendered->SetWeak(true); + item = std::move(grammatical_gendered); + } + + void Visit(StyledString* string) override { + std::string prefixed_string = AddGrammaticalGenderPrefix(std::string(string->value->value)); + android::StyleString new_string; + new_string.str = std::move(prefixed_string); + for (const android::StringPool::Span& span : string->value->spans) { + new_string.spans.emplace_back(android::Span{*span.name, span.first_char, span.last_char}); + } + std::unique_ptr<StyledString> grammatical_gendered = + util::make_unique<StyledString>(pool_->MakeRef(new_string)); + grammatical_gendered->SetSource(string->GetSource()); + grammatical_gendered->SetWeak(true); + item = std::move(grammatical_gendered); + } + + private: + DISALLOW_COPY_AND_ASSIGN(GrammaticalGenderVisitor); + android::StringPool* pool_; + uint8_t grammaticalInflection_; +}; + ConfigDescription ModifyConfigForPseudoLocale(const ConfigDescription& base, - Pseudolocalizer::Method m) { + Pseudolocalizer::Method m, + uint8_t grammaticalInflection) { ConfigDescription modified = base; switch (m) { case Pseudolocalizer::Method::kAccent: @@ -313,12 +394,64 @@ ConfigDescription ModifyConfigForPseudoLocale(const ConfigDescription& base, default: break; } + modified.grammaticalInflection = grammaticalInflection; return modified; } +void GrammaticalGender(ResourceConfigValue* original_value, + ResourceConfigValue* localized_config_value, android::StringPool* pool, + ResourceEntry* entry, const Pseudolocalizer::Method method, + uint8_t grammaticalInflection) { + GrammaticalGenderVisitor visitor(pool, grammaticalInflection); + localized_config_value->value->Accept(&visitor); + + std::unique_ptr<Value> grammatical_gendered_value; + if (visitor.value) { + grammatical_gendered_value = std::move(visitor.value); + } else if (visitor.item) { + grammatical_gendered_value = std::move(visitor.item); + } + if (!grammatical_gendered_value) { + return; + } + + ConfigDescription config = + ModifyConfigForPseudoLocale(original_value->config, method, grammaticalInflection); + + ResourceConfigValue* grammatical_gendered_config_value = + entry->FindOrCreateValue(config, original_value->product); + if (!grammatical_gendered_config_value->value) { + // Only use auto-generated pseudo-localization if none is defined. + grammatical_gendered_config_value->value = std::move(grammatical_gendered_value); + } +} + +const uint32_t MASK_MASCULINE = 1; // Bit mask for masculine +const uint32_t MASK_FEMININE = 2; // Bit mask for feminine +const uint32_t MASK_NEUTER = 4; // Bit mask for neuter + +void GrammaticalGenderIfNeeded(ResourceConfigValue* original_value, ResourceConfigValue* new_value, + android::StringPool* pool, ResourceEntry* entry, + const Pseudolocalizer::Method method, uint32_t gender_state) { + if (gender_state & MASK_FEMININE) { + GrammaticalGender(original_value, new_value, pool, entry, method, + android::ResTable_config::GRAMMATICAL_GENDER_FEMININE); + } + + if (gender_state & MASK_MASCULINE) { + GrammaticalGender(original_value, new_value, pool, entry, method, + android::ResTable_config::GRAMMATICAL_GENDER_MASCULINE); + } + + if (gender_state & MASK_NEUTER) { + GrammaticalGender(original_value, new_value, pool, entry, method, + android::ResTable_config::GRAMMATICAL_GENDER_NEUTER); + } +} + void PseudolocalizeIfNeeded(const Pseudolocalizer::Method method, ResourceConfigValue* original_value, android::StringPool* pool, - ResourceEntry* entry) { + ResourceEntry* entry, uint32_t gender_state, bool gender_flag) { Visitor visitor(pool, method); original_value->value->Accept(&visitor); @@ -333,8 +466,8 @@ void PseudolocalizeIfNeeded(const Pseudolocalizer::Method method, return; } - ConfigDescription config_with_accent = - ModifyConfigForPseudoLocale(original_value->config, method); + ConfigDescription config_with_accent = ModifyConfigForPseudoLocale( + original_value->config, method, android::ResTable_config::GRAMMATICAL_GENDER_ANY); ResourceConfigValue* new_config_value = entry->FindOrCreateValue(config_with_accent, original_value->product); @@ -342,6 +475,9 @@ void PseudolocalizeIfNeeded(const Pseudolocalizer::Method method, // Only use auto-generated pseudo-localization if none is defined. new_config_value->value = std::move(localized_value); } + if (gender_flag) { + GrammaticalGenderIfNeeded(original_value, new_config_value, pool, entry, method, gender_state); + } } // A value is pseudolocalizable if it does not define a locale (or is the default locale) and is @@ -356,16 +492,71 @@ static bool IsPseudolocalizable(ResourceConfigValue* config_value) { } // namespace +bool ParseGenderValuesAndSaveState(const std::string& grammatical_gender_values, + uint32_t* gender_state, android::IDiagnostics* diag) { + std::vector<std::string> values = util::SplitAndLowercase(grammatical_gender_values, ','); + for (size_t i = 0; i < values.size(); i++) { + if (values[i].length() != 0) { + if (values[i] == "f") { + *gender_state |= MASK_FEMININE; + } else if (values[i] == "m") { + *gender_state |= MASK_MASCULINE; + } else if (values[i] == "n") { + *gender_state |= MASK_NEUTER; + } else { + diag->Error(android::DiagMessage() << "Invalid grammatical gender value: " << values[i]); + return false; + } + } + } + return true; +} + +bool ParseGenderRatio(const std::string& grammatical_gender_ratio, float* gender_ratio, + android::IDiagnostics* diag) { + const char* input = grammatical_gender_ratio.c_str(); + char* endPtr; + errno = 0; + *gender_ratio = strtof(input, &endPtr); + if (endPtr == input || *endPtr != '\0' || errno == ERANGE || *gender_ratio < 0 || + *gender_ratio > 1) { + diag->Error(android::DiagMessage() + << "Invalid grammatical gender ratio: " << grammatical_gender_ratio + << ", must be a real number between 0 and 1"); + return false; + } + return true; +} + bool PseudolocaleGenerator::Consume(IAaptContext* context, ResourceTable* table) { + uint32_t gender_state = 0; + if (!ParseGenderValuesAndSaveState(grammatical_gender_values_, &gender_state, + context->GetDiagnostics())) { + return false; + } + + float gender_ratio = 0; + if (!ParseGenderRatio(grammatical_gender_ratio_, &gender_ratio, context->GetDiagnostics())) { + return false; + } + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> distrib(0.0, 1.0); + for (auto& package : table->packages) { for (auto& type : package->types) { for (auto& entry : type->entries) { + bool gender_flag = false; + if (distrib(gen) < gender_ratio) { + gender_flag = true; + } std::vector<ResourceConfigValue*> values = entry->FindValuesIf(IsPseudolocalizable); for (ResourceConfigValue* value : values) { PseudolocalizeIfNeeded(Pseudolocalizer::Method::kAccent, value, &table->string_pool, - entry.get()); + entry.get(), gender_state, gender_flag); PseudolocalizeIfNeeded(Pseudolocalizer::Method::kBidi, value, &table->string_pool, - entry.get()); + entry.get(), gender_state, gender_flag); } } } diff --git a/tools/aapt2/compile/PseudolocaleGenerator.h b/tools/aapt2/compile/PseudolocaleGenerator.h index 44e6e3e86f92..ce92008cdba1 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator.h +++ b/tools/aapt2/compile/PseudolocaleGenerator.h @@ -27,8 +27,19 @@ std::unique_ptr<StyledString> PseudolocalizeStyledString(StyledString* string, Pseudolocalizer::Method method, android::StringPool* pool); -struct PseudolocaleGenerator : public IResourceTableConsumer { - bool Consume(IAaptContext* context, ResourceTable* table) override; +class PseudolocaleGenerator : public IResourceTableConsumer { + public: + explicit PseudolocaleGenerator(std::string grammatical_gender_values, + std::string grammatical_gender_ratio) + : grammatical_gender_values_(std::move(grammatical_gender_values)), + grammatical_gender_ratio_(std::move(grammatical_gender_ratio)) { + } + + bool Consume(IAaptContext* context, ResourceTable* table); + + private: + std::string grammatical_gender_values_; + std::string grammatical_gender_ratio_; }; } // namespace aapt diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp index 2f90cbf722c2..1477ebf8473d 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp @@ -197,7 +197,7 @@ TEST(PseudolocaleGeneratorTest, PseudolocalizeOnlyDefaultConfigs) { val->SetTranslatable(false); std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); - PseudolocaleGenerator generator; + PseudolocaleGenerator generator(std::string("f,m,n"), std::string("1.0")); ASSERT_TRUE(generator.Consume(context.get(), table.get())); // Normal pseudolocalization should take place. @@ -249,7 +249,7 @@ TEST(PseudolocaleGeneratorTest, PluralsArePseudolocalized) { expected->values = {util::make_unique<String>(table->string_pool.MakeRef("[žéŕö one]")), util::make_unique<String>(table->string_pool.MakeRef("[öñé one]"))}; - PseudolocaleGenerator generator; + PseudolocaleGenerator generator(std::string("f,m,n"), std::string("1.0")); ASSERT_TRUE(generator.Consume(context.get(), table.get())); const auto* actual = test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo", @@ -287,7 +287,7 @@ TEST(PseudolocaleGeneratorTest, RespectUntranslateableSections) { context->GetDiagnostics())); } - PseudolocaleGenerator generator; + PseudolocaleGenerator generator(std::string("f,m,n"), std::string("1.0")); ASSERT_TRUE(generator.Consume(context.get(), table.get())); StyledString* new_styled_string = test::GetValueForConfig<StyledString>( @@ -305,4 +305,213 @@ TEST(PseudolocaleGeneratorTest, RespectUntranslateableSections) { EXPECT_NE(std::string::npos, new_string->value->find("world")); } +TEST(PseudolocaleGeneratorTest, PseudolocalizeGrammaticalGenderForString) { + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder().AddString("android:string/foo", "foo").Build(); + + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + PseudolocaleGenerator generator(std::string("f,m,n"), std::string("1.0")); + ASSERT_TRUE(generator.Consume(context.get(), table.get())); + + String* locale = test::GetValueForConfig<String>(table.get(), "android:string/foo", + test::ParseConfigOrDie("en-rXA")); + ASSERT_NE(nullptr, locale); + + // Grammatical gendered string + auto config_feminine = test::ParseConfigOrDie("en-rXA-feminine"); + config_feminine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + String* feminine = + test::GetValueForConfig<String>(table.get(), "android:string/foo", config_feminine); + ASSERT_NE(nullptr, feminine); + EXPECT_EQ(std::string("(F)") + *locale->value, *feminine->value); + + auto config_masculine = test::ParseConfigOrDie("en-rXA-masculine"); + config_masculine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + String* masculine = + test::GetValueForConfig<String>(table.get(), "android:string/foo", config_masculine); + ASSERT_NE(nullptr, masculine); + EXPECT_EQ(std::string("(M)") + *locale->value, *masculine->value); + + auto config_neuter = test::ParseConfigOrDie("en-rXA-neuter"); + config_neuter.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + String* neuter = + test::GetValueForConfig<String>(table.get(), "android:string/foo", config_neuter); + ASSERT_NE(nullptr, neuter); + EXPECT_EQ(std::string("(N)") + *locale->value, *neuter->value); +} + +TEST(PseudolocaleGeneratorTest, PseudolocalizeGrammaticalGenderForPlural) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder().Build(); + std::unique_ptr<Plural> plural = util::make_unique<Plural>(); + plural->values = {util::make_unique<String>(table->string_pool.MakeRef("zero")), + util::make_unique<String>(table->string_pool.MakeRef("one"))}; + ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("com.pkg:plurals/foo")) + .SetValue(std::move(plural)) + .Build(), + context->GetDiagnostics())); + PseudolocaleGenerator generator(std::string("f,m,n"), std::string("1.0")); + ASSERT_TRUE(generator.Consume(context.get(), table.get())); + + Plural* actual = test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo", + test::ParseConfigOrDie("en-rXA")); + ASSERT_NE(nullptr, actual); + + // Grammatical gendered Plural + auto config_feminine = test::ParseConfigOrDie("en-rXA-feminine"); + config_feminine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + Plural* actual_feminine = + test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo", config_feminine); + for (size_t i = 0; i < actual->values.size(); i++) { + if (actual->values[i]) { + String* locale = ValueCast<String>(actual->values[i].get()); + String* feminine = ValueCast<String>(actual_feminine->values[i].get()); + EXPECT_EQ(std::string("(F)") + *locale->value, *feminine->value); + } + } + + auto config_masculine = test::ParseConfigOrDie("en-rXA-masculine"); + config_masculine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + Plural* actual_masculine = + test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo", config_masculine); + ASSERT_NE(nullptr, actual_masculine); + for (size_t i = 0; i < actual->values.size(); i++) { + if (actual->values[i]) { + String* locale = ValueCast<String>(actual->values[i].get()); + String* masculine = ValueCast<String>(actual_masculine->values[i].get()); + EXPECT_EQ(std::string("(M)") + *locale->value, *masculine->value); + } + } + + auto config_neuter = test::ParseConfigOrDie("en-rXA-neuter"); + config_neuter.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + Plural* actual_neuter = + test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo", config_neuter); + for (size_t i = 0; i < actual->values.size(); i++) { + if (actual->values[i]) { + String* locale = ValueCast<String>(actual->values[i].get()); + String* neuter = ValueCast<String>(actual_neuter->values[i].get()); + EXPECT_EQ(std::string("(N)") + *locale->value, *neuter->value); + } + } +} + +TEST(PseudolocaleGeneratorTest, PseudolocalizeGrammaticalGenderForStyledString) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder().Build(); + android::StyleString original_style; + original_style.str = "Hello world!"; + original_style.spans = {android::Span{"i", 1, 10}}; + + std::unique_ptr<StyledString> original = + util::make_unique<StyledString>(table->string_pool.MakeRef(original_style)); + ASSERT_TRUE(table->AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/foo")) + .SetValue(std::move(original)) + .Build(), + context->GetDiagnostics())); + PseudolocaleGenerator generator(std::string("f,m,n"), std::string("1.0")); + ASSERT_TRUE(generator.Consume(context.get(), table.get())); + + StyledString* locale = test::GetValueForConfig<StyledString>(table.get(), "android:string/foo", + test::ParseConfigOrDie("en-rXA")); + ASSERT_NE(nullptr, locale); + EXPECT_EQ(1, locale->value->spans.size()); + EXPECT_EQ(std::string("i"), *locale->value->spans[0].name); + + // Grammatical gendered StyledString + auto config_feminine = test::ParseConfigOrDie("en-rXA-feminine"); + config_feminine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + StyledString* feminine = + test::GetValueForConfig<StyledString>(table.get(), "android:string/foo", config_feminine); + ASSERT_NE(nullptr, feminine); + EXPECT_EQ(1, feminine->value->spans.size()); + EXPECT_EQ(std::string("i"), *feminine->value->spans[0].name); + EXPECT_EQ(std::string("(F)") + locale->value->value, feminine->value->value); + + auto config_masculine = test::ParseConfigOrDie("en-rXA-masculine"); + config_masculine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + StyledString* masculine = + test::GetValueForConfig<StyledString>(table.get(), "android:string/foo", config_masculine); + ASSERT_NE(nullptr, masculine); + EXPECT_EQ(1, masculine->value->spans.size()); + EXPECT_EQ(std::string("i"), *masculine->value->spans[0].name); + EXPECT_EQ(std::string("(M)") + locale->value->value, masculine->value->value); + + auto config_neuter = test::ParseConfigOrDie("en-rXA-neuter"); + config_neuter.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + StyledString* neuter = + test::GetValueForConfig<StyledString>(table.get(), "android:string/foo", config_neuter); + ASSERT_NE(nullptr, neuter); + EXPECT_EQ(1, neuter->value->spans.size()); + EXPECT_EQ(std::string("i"), *neuter->value->spans[0].name); + EXPECT_EQ(std::string("(N)") + locale->value->value, neuter->value->value); +} + +TEST(PseudolocaleGeneratorTest, GrammaticalGenderForCertainValues) { + // single gender value + std::unique_ptr<ResourceTable> table_0 = + test::ResourceTableBuilder().AddString("android:string/foo", "foo").Build(); + + std::unique_ptr<IAaptContext> context_0 = test::ContextBuilder().Build(); + PseudolocaleGenerator generator_0(std::string("f"), std::string("1.0")); + ASSERT_TRUE(generator_0.Consume(context_0.get(), table_0.get())); + + String* locale_0 = test::GetValueForConfig<String>(table_0.get(), "android:string/foo", + test::ParseConfigOrDie("en-rXA")); + ASSERT_NE(nullptr, locale_0); + + auto config_feminine = test::ParseConfigOrDie("en-rXA-feminine"); + config_feminine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + String* feminine_0 = + test::GetValueForConfig<String>(table_0.get(), "android:string/foo", config_feminine); + ASSERT_NE(nullptr, feminine_0); + EXPECT_EQ(std::string("(F)") + *locale_0->value, *feminine_0->value); + + auto config_masculine = test::ParseConfigOrDie("en-rXA-masculine"); + config_masculine.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + String* masculine_0 = + test::GetValueForConfig<String>(table_0.get(), "android:string/foo", config_masculine); + EXPECT_EQ(nullptr, masculine_0); + + auto config_neuter = test::ParseConfigOrDie("en-rXA-neuter"); + config_neuter.sdkVersion = android::ResTable_config::SDKVERSION_ANY; + String* neuter_0 = + test::GetValueForConfig<String>(table_0.get(), "android:string/foo", config_neuter); + EXPECT_EQ(nullptr, neuter_0); + + // multiple gender values + std::unique_ptr<ResourceTable> table_1 = + test::ResourceTableBuilder().AddString("android:string/foo", "foo").Build(); + + std::unique_ptr<IAaptContext> context_1 = test::ContextBuilder().Build(); + PseudolocaleGenerator generator_1(std::string("f,n"), std::string("1.0")); + ASSERT_TRUE(generator_1.Consume(context_1.get(), table_1.get())); + + String* locale_1 = test::GetValueForConfig<String>(table_1.get(), "android:string/foo", + test::ParseConfigOrDie("en-rXA")); + ASSERT_NE(nullptr, locale_1); + + String* feminine_1 = + test::GetValueForConfig<String>(table_1.get(), "android:string/foo", config_feminine); + ASSERT_NE(nullptr, feminine_1); + EXPECT_EQ(std::string("(F)") + *locale_1->value, *feminine_1->value); + + String* masculine_1 = + test::GetValueForConfig<String>(table_1.get(), "android:string/foo", config_masculine); + EXPECT_EQ(nullptr, masculine_1); + + String* neuter_1 = + test::GetValueForConfig<String>(table_1.get(), "android:string/foo", config_neuter); + ASSERT_NE(nullptr, neuter_1); + EXPECT_EQ(std::string("(N)") + *locale_1->value, *neuter_1->value); + + // invalid gender value + std::unique_ptr<ResourceTable> table_2 = + test::ResourceTableBuilder().AddString("android:string/foo", "foo").Build(); + + std::unique_ptr<IAaptContext> context_2 = test::ContextBuilder().Build(); + PseudolocaleGenerator generator_2(std::string("invald,"), std::string("1.0")); + ASSERT_FALSE(generator_2.Consume(context_2.get(), table_2.get())); +} + } // namespace aapt diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp index adb682730f5a..a2b48187c24f 100644 --- a/tools/aapt2/dump/DumpManifest.cpp +++ b/tools/aapt2/dump/DumpManifest.cpp @@ -835,9 +835,9 @@ class UsesSdkBadging : public ManifestExtractor::Element { void Print(text::Printer* printer) override { if (min_sdk) { - printer->Print(StringPrintf("sdkVersion:'%d'\n", *min_sdk)); + printer->Print(StringPrintf("minSdkVersion:'%d'\n", *min_sdk)); } else if (min_sdk_name) { - printer->Print(StringPrintf("sdkVersion:'%s'\n", min_sdk_name->data())); + printer->Print(StringPrintf("minSdkVersion:'%s'\n", min_sdk_name->data())); } if (max_sdk) { printer->Print(StringPrintf("maxSdkVersion:'%d'\n", *max_sdk)); diff --git a/tools/aapt2/format/Archive_test.cpp b/tools/aapt2/format/Archive_test.cpp index 3c44da710d94..fd50af92ceee 100644 --- a/tools/aapt2/format/Archive_test.cpp +++ b/tools/aapt2/format/Archive_test.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <stdlib.h> + #include "test/Test.h" namespace aapt { @@ -34,6 +36,29 @@ class TestData : public io::MallocData { std::string error_; }; +class TzSetter { + public: + explicit TzSetter(const std::string& new_tz) { + old_tz_ = getenv("TZ"); + new_tz_ = "TZ=" + new_tz; + putenv(const_cast<char*>(new_tz_.c_str())); + tzset(); + } + + ~TzSetter() { + if (old_tz_) { + putenv(old_tz_); + } else { + putenv(const_cast<char*>("TZ")); + } + tzset(); + } + + private: + char* old_tz_; + std::string new_tz_; +}; + std::unique_ptr<uint8_t[]> MakeTestArray() { auto array = std::make_unique<uint8_t[]>(kTestDataLength); for (int index = 0; index < kTestDataLength; ++index) { @@ -86,6 +111,22 @@ void VerifyZipFile(const std::string& output_path, const std::string& file, cons } } +void VerifyZipFileTimestamps(const std::string& output_path) { + std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(output_path, nullptr); + auto it = zip->Iterator(); + while (it->HasNext()) { + auto file = it->Next(); + struct tm modification_time; + ASSERT_TRUE(file->GetModificationTime(&modification_time)); + EXPECT_EQ(modification_time.tm_year, 80); + EXPECT_EQ(modification_time.tm_mon, 0); + EXPECT_EQ(modification_time.tm_mday, 1); + EXPECT_EQ(modification_time.tm_hour, 0); + EXPECT_EQ(modification_time.tm_min, 0); + EXPECT_EQ(modification_time.tm_sec, 0); + } +} + TEST_F(ArchiveTest, DirectoryWriteEntrySuccess) { std::string output_path = GetTestPath("output"); std::unique_ptr<IArchiveWriter> writer = MakeDirectoryWriter(output_path); @@ -206,4 +247,73 @@ TEST_F(ArchiveTest, ZipFileWriteFileError) { ASSERT_EQ("ZipFileWriteFileError", writer->GetError()); } +TEST_F(ArchiveTest, ZipFileTimeZoneUTC) { + TzSetter tz("UTC0"); + std::string output_path = GetTestPath("output.apk"); + std::unique_ptr<IArchiveWriter> writer = MakeZipFileWriter(output_path); + std::unique_ptr<uint8_t[]> data1 = MakeTestArray(); + std::unique_ptr<uint8_t[]> data2 = MakeTestArray(); + + ASSERT_TRUE(writer->StartEntry("test1", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data1.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + ASSERT_TRUE(writer->StartEntry("test2", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data2.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + writer.reset(); + + // All zip file entries must have the same timestamp, regardless of time zone. See: b/277978832 + VerifyZipFileTimestamps(output_path); +} + +TEST_F(ArchiveTest, ZipFileTimeZoneWestOfUTC) { + TzSetter tz("PST8"); + std::string output_path = GetTestPath("output.apk"); + std::unique_ptr<IArchiveWriter> writer = MakeZipFileWriter(output_path); + std::unique_ptr<uint8_t[]> data1 = MakeTestArray(); + std::unique_ptr<uint8_t[]> data2 = MakeTestArray(); + + ASSERT_TRUE(writer->StartEntry("test1", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data1.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + ASSERT_TRUE(writer->StartEntry("test2", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data2.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + writer.reset(); + + // All zip file entries must have the same timestamp, regardless of time zone. See: b/277978832 + VerifyZipFileTimestamps(output_path); +} + +TEST_F(ArchiveTest, ZipFileTimeZoneEastOfUTC) { + TzSetter tz("EET-2"); + std::string output_path = GetTestPath("output.apk"); + std::unique_ptr<IArchiveWriter> writer = MakeZipFileWriter(output_path); + std::unique_ptr<uint8_t[]> data1 = MakeTestArray(); + std::unique_ptr<uint8_t[]> data2 = MakeTestArray(); + + ASSERT_TRUE(writer->StartEntry("test1", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data1.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + ASSERT_TRUE(writer->StartEntry("test2", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data2.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + writer.reset(); + + // All zip file entries must have the same timestamp, regardless of time zone. See: b/277978832 + VerifyZipFileTimestamps(output_path); +} + } // namespace aapt diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index 8c594ba553a0..f05611048caa 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -68,9 +68,8 @@ struct OverlayableChunk { class PackageFlattener { public: PackageFlattener(IAaptContext* context, const ResourceTablePackageView& package, - const std::map<size_t, std::string>* shared_libs, - SparseEntriesMode sparse_entries, - bool compact_entries, + const ResourceTable::ReferencedPackages* shared_libs, + SparseEntriesMode sparse_entries, bool compact_entries, bool collapse_key_stringpool, const std::set<ResourceName>& name_collapse_exemptions, bool deduplicate_entry_values) @@ -145,10 +144,9 @@ class PackageFlattener { // 2) the entries will be accessed on platforms U+, and // 3) all entry keys can be encoded in 16 bits bool UseCompactEntries(const ConfigDescription& config, std::vector<FlatEntry>* entries) const { - return compact_entries_ && - (context_->GetMinSdkVersion() > SDK_TIRAMISU || config.sdkVersion > SDK_TIRAMISU) && - std::none_of(entries->cbegin(), entries->cend(), - [](const auto& e) { return e.entry_key >= std::numeric_limits<uint16_t>::max(); }); + return compact_entries_ && context_->GetMinSdkVersion() > SDK_TIRAMISU && + std::none_of(entries->cbegin(), entries->cend(), + [](const auto& e) { return e.entry_key >= std::numeric_limits<uint16_t>::max(); }); } std::unique_ptr<ResEntryWriter> GetResEntryWriter(bool dedup, bool compact, BigBuffer* buffer) { @@ -548,7 +546,7 @@ class PackageFlattener { IAaptContext* context_; android::IDiagnostics* diag_; const ResourceTablePackageView package_; - const std::map<size_t, std::string>* shared_libs_; + const ResourceTable::ReferencedPackages* shared_libs_; SparseEntriesMode sparse_entries_; bool compact_entries_; android::StringPool type_pool_; diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index 09ef9bddd3bd..e1a3013c07bb 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -916,7 +916,7 @@ std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, } break; case pb::Primitive::kIntDecimalValue: { val.dataType = android::Res_value::TYPE_INT_DEC; - val.data = static_cast<uint32_t>(pb_prim.int_decimal_value()); + val.data = static_cast<int32_t>(pb_prim.int_decimal_value()); } break; case pb::Primitive::kIntHexadecimalValue: { val.dataType = android::Res_value::TYPE_INT_HEX; diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index afb83562b129..fa8860ff69eb 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -250,6 +250,7 @@ TEST(ProtoSerializeTest, SerializeSinglePackage) { } TEST(ProtoSerializeTest, SerializeAndDeserializeXml) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); xml::Element element; element.line_number = 22; element.column_number = 23; @@ -269,8 +270,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeXml) { attr.namespace_uri = xml::kSchemaAndroid; attr.value = "23dp"; attr.compiled_attribute = xml::AaptAttribute(Attribute{}, ResourceId(0x01010000)); - attr.compiled_value = - ResourceUtils::TryParseItemForAttribute(attr.value, android::ResTable_map::TYPE_DIMENSION); + attr.compiled_value = ResourceUtils::TryParseItemForAttribute( + context->GetDiagnostics(), attr.value, android::ResTable_map::TYPE_DIMENSION); attr.compiled_value->SetSource(android::Source().WithLine(25)); element.attributes.push_back(std::move(attr)); diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp index bfd35083366e..c901efa707f4 100644 --- a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp +++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp @@ -26,4 +26,5 @@ package { android_test { name: "AaptAutoVersionTest", sdk_version: "current", + use_resource_processor: false, } diff --git a/tools/aapt2/integration-tests/BasicTest/Android.bp b/tools/aapt2/integration-tests/BasicTest/Android.bp index 7db9d2698cc7..d0649ea4ef9c 100644 --- a/tools/aapt2/integration-tests/BasicTest/Android.bp +++ b/tools/aapt2/integration-tests/BasicTest/Android.bp @@ -26,4 +26,5 @@ package { android_test { name: "AaptBasicTest", sdk_version: "current", + use_resource_processor: false, } diff --git a/tools/aapt2/integration-tests/DumpTest/built_with_aapt_expected.txt b/tools/aapt2/integration-tests/DumpTest/built_with_aapt_expected.txt index cc0b3bf5d2fb..d14e5fb5c477 100644 --- a/tools/aapt2/integration-tests/DumpTest/built_with_aapt_expected.txt +++ b/tools/aapt2/integration-tests/DumpTest/built_with_aapt_expected.txt @@ -1,5 +1,5 @@ package: name='com.aapt.app' versionCode='222' versionName='222' platformBuildVersionName='12' platformBuildVersionCode='32' compileSdkVersion='32' compileSdkVersionCodename='12' -sdkVersion:'22' +minSdkVersion:'22' targetSdkVersion:'32' application: label='App' icon='' feature-group: label='' diff --git a/tools/aapt2/integration-tests/DumpTest/components_expected.txt b/tools/aapt2/integration-tests/DumpTest/components_expected.txt index 9c81fb83ca15..93cce0a29024 100644 --- a/tools/aapt2/integration-tests/DumpTest/components_expected.txt +++ b/tools/aapt2/integration-tests/DumpTest/components_expected.txt @@ -1,5 +1,5 @@ package: name='com.example.bundletool.minimal' versionCode='1' versionName='1.0' platformBuildVersionName='12' platformBuildVersionCode='31' compileSdkVersion='31' compileSdkVersionCodename='12' -sdkVersion:'21' +minSdkVersion:'21' targetSdkVersion:'31' uses-configuration: reqTouchScreen='3' reqKeyboardType='2' reqHardKeyboard='-1' reqNavigation='3' reqFiveWayNav='-1' supports-gl-texture:'GL_OES_compressed_paletted_texture' diff --git a/tools/aapt2/integration-tests/DumpTest/minimal_expected.txt b/tools/aapt2/integration-tests/DumpTest/minimal_expected.txt index 85ab5d80cd39..aafca68443a9 100644 --- a/tools/aapt2/integration-tests/DumpTest/minimal_expected.txt +++ b/tools/aapt2/integration-tests/DumpTest/minimal_expected.txt @@ -1,5 +1,5 @@ package: name='com.lato.bubblegirl' versionCode='33' versionName='1.0.0' platformBuildVersionName='8.1.0' platformBuildVersionCode='27' -sdkVersion:'19' +minSdkVersion:'19' targetSdkVersion:'26' application-label:'Bubble Girl' application-label-ar:'Bubble Girl' diff --git a/tools/aapt2/integration-tests/DumpTest/multiple_uses_sdk_expected.txt b/tools/aapt2/integration-tests/DumpTest/multiple_uses_sdk_expected.txt index 85e8d0a3cbba..f48f381e3012 100644 --- a/tools/aapt2/integration-tests/DumpTest/multiple_uses_sdk_expected.txt +++ b/tools/aapt2/integration-tests/DumpTest/multiple_uses_sdk_expected.txt @@ -1,5 +1,5 @@ package: name='com.test.e17wmultiapknexus' versionCode='107' versionName='14' platformBuildVersionName='2.3.3' platformBuildVersionCode='10' -sdkVersion:'1' +minSdkVersion:'1' application-label:'w45wmultiapknexus_10' application-icon-120:'res/drawable-ldpi-v4/icon.png' application-icon-160:'res/drawable-mdpi-v4/icon.png' diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp index 80404eeb8d8e..ebb4e9f479d6 100644 --- a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp +++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp @@ -24,9 +24,9 @@ package { } android_test { - name: "AaptTestStaticLib_App", sdk_version: "current", + use_resource_processor: false, srcs: ["src/**/*.java"], asset_dirs: [ "assets", diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp index a84da43c70c8..ee12a92906a8 100644 --- a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp @@ -26,6 +26,7 @@ package { android_library { name: "AaptTestStaticLib_LibOne", sdk_version: "current", + use_resource_processor: false, srcs: ["src/**/*.java"], resource_dirs: ["res"], } diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp index d386c3a35d20..83b2362496fc 100644 --- a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp @@ -26,6 +26,7 @@ package { android_library { name: "AaptTestStaticLib_LibTwo", sdk_version: "current", + use_resource_processor: false, srcs: ["src/**/*.java"], resource_dirs: ["res"], libs: ["AaptTestStaticLib_LibOne"], diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp index 1e8cf86ed811..15a6a207d6d1 100644 --- a/tools/aapt2/integration-tests/SymlinkTest/Android.bp +++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp @@ -26,4 +26,5 @@ package { android_test { name: "AaptSymlinkTest", sdk_version: "current", + use_resource_processor: false, } diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h index 08d497def8a4..673d1b75e660 100644 --- a/tools/aapt2/io/File.h +++ b/tools/aapt2/io/File.h @@ -57,6 +57,11 @@ class IFile { return false; } + // Fills in buf with the last modification time of the file. Returns true if successful, + // otherwise false (i.e., the operation is not supported or the file system is unable to provide + // a last modification time). + virtual bool GetModificationTime(struct tm* buf) const = 0; + private: // Any segments created from this IFile need to be owned by this IFile, so // keep them @@ -79,6 +84,10 @@ class FileSegment : public IFile { return file_->GetSource(); } + bool GetModificationTime(struct tm* buf) const override { + return file_->GetModificationTime(buf); + }; + private: DISALLOW_COPY_AND_ASSIGN(FileSegment); diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp index a64982a7fa5c..6a692e497816 100644 --- a/tools/aapt2/io/FileSystem.cpp +++ b/tools/aapt2/io/FileSystem.cpp @@ -14,9 +14,12 @@ * limitations under the License. */ +#define _POSIX_THREAD_SAFE_FUNCTIONS // For mingw localtime_r(). + #include "io/FileSystem.h" #include <dirent.h> +#include <sys/stat.h> #include "android-base/errors.h" #include "androidfw/Source.h" @@ -54,6 +57,23 @@ const android::Source& RegularFile::GetSource() const { return source_; } +bool RegularFile::GetModificationTime(struct tm* buf) const { + if (buf == nullptr) { + return false; + } + struct stat stat_buf; + if (stat(source_.path.c_str(), &stat_buf) != 0) { + return false; + } + + struct tm* ptm; + struct tm tm_result; + ptm = localtime_r(&stat_buf.st_mtime, &tm_result); + + *buf = *ptm; + return true; +} + FileCollectionIterator::FileCollectionIterator(FileCollection* collection) : current_(collection->files_.begin()), end_(collection->files_.end()) {} diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h index 0e798fc1b975..f975196b9cfa 100644 --- a/tools/aapt2/io/FileSystem.h +++ b/tools/aapt2/io/FileSystem.h @@ -32,6 +32,7 @@ class RegularFile : public IFile { std::unique_ptr<IData> OpenAsData() override; std::unique_ptr<io::InputStream> OpenInputStream() override; const android::Source& GetSource() const override; + bool GetModificationTime(struct tm* buf) const override; private: DISALLOW_COPY_AND_ASSIGN(RegularFile); diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp index 4a5385d90d3b..cb5bbe96b8b7 100644 --- a/tools/aapt2/io/ZipArchive.cpp +++ b/tools/aapt2/io/ZipArchive.cpp @@ -75,6 +75,14 @@ bool ZipFile::WasCompressed() { return zip_entry_.method != kCompressStored; } +bool ZipFile::GetModificationTime(struct tm* buf) const { + if (buf == nullptr) { + return false; + } + *buf = zip_entry_.GetModificationTime(); + return true; +} + ZipFileCollectionIterator::ZipFileCollectionIterator( ZipFileCollection* collection) : current_(collection->files_.begin()), end_(collection->files_.end()) {} diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h index c263aa490d22..ac125d097983 100644 --- a/tools/aapt2/io/ZipArchive.h +++ b/tools/aapt2/io/ZipArchive.h @@ -38,6 +38,7 @@ class ZipFile : public IFile { std::unique_ptr<io::InputStream> OpenInputStream() override; const android::Source& GetSource() const override; bool WasCompressed() override; + bool GetModificationTime(struct tm* buf) const override; private: ::ZipArchiveHandle zip_handle_; diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index 9dadfb26a3f8..c69b32513167 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -164,8 +164,8 @@ std::unique_ptr<Item> ReferenceLinkerTransformer::TransformItem(const Reference* std::unique_ptr<Item> ReferenceLinkerTransformer::ParseValueWithAttribute( std::unique_ptr<Item> value, const Attribute* attr) { if (RawString* raw_string = ValueCast<RawString>(value.get())) { - std::unique_ptr<Item> transformed = - ResourceUtils::TryParseItemForAttribute(*raw_string->value, attr); + std::unique_ptr<Item> transformed = ResourceUtils::TryParseItemForAttribute( + context_->GetDiagnostics(), *raw_string->value, attr); // If we could not parse as any specific type, try a basic STRING. if (!transformed && (attr->type_mask & android::ResTable_map::TYPE_STRING)) { diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp index d2e9bd770a31..aec7ceb82c0f 100644 --- a/tools/aapt2/link/XmlReferenceLinker.cpp +++ b/tools/aapt2/link/XmlReferenceLinker.cpp @@ -90,7 +90,8 @@ class XmlVisitor : public xml::PackageAwareVisitor { attribute = &attr.compiled_attribute.value().attribute; } - attr.compiled_value = ResourceUtils::TryParseItemForAttribute(attr.value, attribute); + attr.compiled_value = ResourceUtils::TryParseItemForAttribute(context_->GetDiagnostics(), + attr.value, attribute); if (attr.compiled_value) { // With a compiledValue, we must resolve the reference and assign it an ID. attr.compiled_value->SetSource(source); diff --git a/tools/aapt2/optimize/Obfuscator.cpp b/tools/aapt2/optimize/Obfuscator.cpp index 8f12f735736e..903cdf852566 100644 --- a/tools/aapt2/optimize/Obfuscator.cpp +++ b/tools/aapt2/optimize/Obfuscator.cpp @@ -40,9 +40,9 @@ Obfuscator::Obfuscator(OptimizeOptions& optimizeOptions) collapse_key_stringpool_(optimizeOptions.table_flattener_options.collapse_key_stringpool) { } -std::string ShortenFileName(android::StringPiece file_path, int output_length) { +std::string Obfuscator::ShortenFileName(android::StringPiece file_path, int output_length) { std::size_t hash_num = std::hash<android::StringPiece>{}(file_path); - std::string result = ""; + std::string result; // Convert to (modified) base64 so that it is a proper file path. for (int i = 0; i < output_length; i++) { uint8_t sextet = hash_num & 0x3f; @@ -52,10 +52,33 @@ std::string ShortenFileName(android::StringPiece file_path, int output_length) { return result; } +static std::string RenameDisallowedFileNames(const std::string& file_name) { + // We are renaming shortened file names to make sure they not a reserved file name in Windows. + // See: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file. We are renaming + // "COM" and "LPT" too because we are appending a number in case of hash collisions; "COM1", + // "COM2", etc. are reserved names. + static const char* const reserved_windows_names[] = {"CON", "PRN", "AUX", "NUL", "COM", "LPT"}; + if (file_name.length() == 3) { + // Need to convert the file name to uppercase as Windows is case insensitive. E.g., "NuL", + // "nul", and "NUl" are also reserved. + std::string result_upper_cased(3, 0); + std::transform(file_name.begin(), file_name.end(), result_upper_cased.begin(), + [](unsigned char c) { return std::toupper(c); }); + for (auto reserved_windows_name : reserved_windows_names) { + if (result_upper_cased == reserved_windows_name) { + // Simple solution to make it a non-reserved name is to add an underscore + return "_" + file_name; + } + } + } + + return file_name; +} + // Return the optimal hash length such that at most 10% of resources collide in // their shortened path. // Reference: http://matt.might.net/articles/counting-hash-collisions/ -int OptimalShortenedLength(int num_resources) { +static int OptimalShortenedLength(int num_resources) { if (num_resources > 4000) { return 3; } else { @@ -63,8 +86,8 @@ int OptimalShortenedLength(int num_resources) { } } -std::string GetShortenedPath(android::StringPiece shortened_filename, - android::StringPiece extension, int collision_count) { +static std::string GetShortenedPath(android::StringPiece shortened_filename, + android::StringPiece extension, int collision_count) { std::string shortened_path = std::string("res/") += shortened_filename; if (collision_count > 0) { shortened_path += std::to_string(collision_count); @@ -82,9 +105,9 @@ struct PathComparator { } }; -static bool HandleShortenFilePaths(ResourceTable* table, - std::map<std::string, std::string>& shortened_path_map, - const std::set<ResourceName>& path_shorten_exemptions) { +bool Obfuscator::HandleShortenFilePaths(ResourceTable* table, + std::map<std::string, std::string>& shortened_path_map, + const std::set<ResourceName>& path_shorten_exemptions) { // used to detect collisions std::unordered_set<std::string> shortened_paths; std::set<FileReference*, PathComparator> file_refs; @@ -112,7 +135,8 @@ static bool HandleShortenFilePaths(ResourceTable* table, // Android detects ColorStateLists via pathname, skip res/color* if (util::StartsWith(res_subdir, "res/color")) continue; - std::string shortened_filename = ShortenFileName(*file_ref->path, num_chars); + std::string shortened_filename = + RenameDisallowedFileNames(ShortenFileName(*file_ref->path, num_chars)); int collision_count = 0; std::string shortened_path = GetShortenedPath(shortened_filename, extension, collision_count); while (shortened_paths.find(shortened_path) != shortened_paths.end()) { diff --git a/tools/aapt2/optimize/Obfuscator.h b/tools/aapt2/optimize/Obfuscator.h index 5ccf54383aae..79d7e088d1cc 100644 --- a/tools/aapt2/optimize/Obfuscator.h +++ b/tools/aapt2/optimize/Obfuscator.h @@ -53,7 +53,14 @@ class Obfuscator : public IResourceTableConsumer { const ResourceNamedType& type_name, const ResourceTableEntryView& entry, const android::base::function_ref<void(Result, const ResourceName&)> onObfuscate); + protected: + virtual std::string ShortenFileName(android::StringPiece file_path, int output_length); + private: + bool HandleShortenFilePaths(ResourceTable* table, + std::map<std::string, std::string>& shortened_path_map, + const std::set<ResourceName>& path_shorten_exemptions); + TableFlattenerOptions& options_; const bool shorten_resource_paths_; const bool collapse_key_stringpool_; diff --git a/tools/aapt2/optimize/Obfuscator_test.cpp b/tools/aapt2/optimize/Obfuscator_test.cpp index 940cf1096f92..c3429e0fc1d6 100644 --- a/tools/aapt2/optimize/Obfuscator_test.cpp +++ b/tools/aapt2/optimize/Obfuscator_test.cpp @@ -19,6 +19,7 @@ #include <map> #include <memory> #include <string> +#include <utility> #include "ResourceTable.h" #include "android-base/file.h" @@ -26,6 +27,7 @@ using ::aapt::test::GetValue; using ::testing::AnyOf; +using ::testing::Contains; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsFalse; @@ -33,6 +35,10 @@ using ::testing::IsTrue; using ::testing::Not; using ::testing::NotNull; +namespace aapt { + +namespace { + android::StringPiece GetExtension(android::StringPiece path) { auto iter = std::find(path.begin(), path.end(), '.'); return android::StringPiece(iter, path.end() - iter); @@ -45,7 +51,22 @@ void FillTable(aapt::test::ResourceTableBuilder& builder, int start, int end) { } } -namespace aapt { +class FakeObfuscator : public Obfuscator { + public: + explicit FakeObfuscator(OptimizeOptions& optimize_options, + const std::unordered_map<std::string, std::string>& shortened_name_map) + : Obfuscator(optimize_options), shortened_name_map_(shortened_name_map) { + } + + protected: + std::string ShortenFileName(android::StringPiece file_path, int output_length) override { + return shortened_name_map_[std::string(file_path)]; + } + + private: + std::unordered_map<std::string, std::string> shortened_name_map_; + DISALLOW_COPY_AND_ASSIGN(FakeObfuscator); +}; TEST(ObfuscatorTest, FileRefPathsChangedInResourceTable) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); @@ -127,7 +148,7 @@ TEST(ObfuscatorTest, SkipPathShortenExemptions) { EXPECT_THAT(path_map.find("res/drawables/xmlfile2.xml"), Not(Eq(path_map.end()))); FileReference* ref = GetValue<FileReference>(table.get(), "android:drawable/xmlfile"); - EXPECT_THAT(ref, NotNull()); + ASSERT_THAT(ref, NotNull()); ASSERT_THAT(HasFailure(), IsFalse()); // The path of first drawable in exemption was not changed EXPECT_THAT("res/drawables/xmlfile.xml", Eq(*ref->path)); @@ -161,13 +182,78 @@ TEST(ObfuscatorTest, KeepExtensions) { ASSERT_THAT(path_map.find("res/drawable/xmlfile.xml"), Not(Eq(path_map.end()))); ASSERT_THAT(path_map.find("res/drawable/pngfile.png"), Not(Eq(path_map.end()))); - auto shortend_xml_path = path_map[original_xml_path]; - auto shortend_png_path = path_map[original_png_path]; - EXPECT_THAT(GetExtension(path_map[original_xml_path]), Eq(android::StringPiece(".xml"))); EXPECT_THAT(GetExtension(path_map[original_png_path]), Eq(android::StringPiece(".png"))); } +TEST(ObfuscatorTest, ShortenedToReservedWindowsNames) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + + std::string original_path_1 = "res/drawable/pngfile_1.png"; + std::string original_path_2 = "res/drawable/pngfile_2.png"; + std::string original_path_3 = "res/drawable/pngfile_3.png"; + std::string original_path_4 = "res/drawable/pngfile_4.png"; + std::string original_path_5 = "res/drawable/pngfile_5.png"; + std::string original_path_6 = "res/drawable/pngfile_6.png"; + std::string original_path_7 = "res/drawable/pngfile_7.png"; + std::string original_path_8 = "res/drawable/pngfile_8.png"; + std::string original_path_9 = "res/drawable/pngfile_9.png"; + + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .AddFileReference("android:drawable/pngfile_1", original_path_1) + .AddFileReference("android:drawable/pngfile_2", original_path_2) + .AddFileReference("android:drawable/pngfile_3", original_path_3) + .AddFileReference("android:drawable/pngfile_4", original_path_4) + .AddFileReference("android:drawable/pngfile_5", original_path_5) + .AddFileReference("android:drawable/pngfile_6", original_path_6) + .AddFileReference("android:drawable/pngfile_7", original_path_7) + .AddFileReference("android:drawable/pngfile_8", original_path_8) + .AddFileReference("android:drawable/pngfile_9", original_path_9) + .Build(); + + OptimizeOptions options{.shorten_resource_paths = true}; + std::map<std::string, std::string>& path_map = options.table_flattener_options.shortened_path_map; + auto obfuscator = FakeObfuscator( + options, + { + {original_path_1, "CON"}, + {original_path_2, "Prn"}, + {original_path_3, "AuX"}, + {original_path_4, "nul"}, + {original_path_5, "cOM"}, + {original_path_6, "lPt"}, + {original_path_7, "lPt"}, + {original_path_8, "lPt"}, // 6, 7, and 8 will be appended with a number to disambiguate + {original_path_9, "F0o"}, // This one is not reserved + }); + ASSERT_TRUE(obfuscator.Consume(context.get(), table.get())); + + // Expect that the path map is populated + ASSERT_THAT(path_map.find(original_path_1), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_2), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_3), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_4), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_5), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_6), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_7), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_8), Not(Eq(path_map.end()))); + ASSERT_THAT(path_map.find(original_path_9), Not(Eq(path_map.end()))); + + EXPECT_THAT(path_map[original_path_1], Eq("res/_CON.png")); + EXPECT_THAT(path_map[original_path_2], Eq("res/_Prn.png")); + EXPECT_THAT(path_map[original_path_3], Eq("res/_AuX.png")); + EXPECT_THAT(path_map[original_path_4], Eq("res/_nul.png")); + EXPECT_THAT(path_map[original_path_5], Eq("res/_cOM.png")); + EXPECT_THAT(path_map[original_path_9], Eq("res/F0o.png")); + + std::set<std::string> lpt_shortened_names{path_map[original_path_6], path_map[original_path_7], + path_map[original_path_8]}; + EXPECT_THAT(lpt_shortened_names, Contains("res/_lPt.png")); + EXPECT_THAT(lpt_shortened_names, Contains("res/_lPt1.png")); + EXPECT_THAT(lpt_shortened_names, Contains("res/_lPt2.png")); +} + TEST(ObfuscatorTest, DeterministicallyHandleCollisions) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); @@ -247,7 +333,9 @@ TEST(ObfuscatorTest, DumpIdResourceMap) { ASSERT_TRUE(Obfuscator(options).Consume(context.get(), table.get())); // Expect that the id resource name map is populated + ASSERT_THAT(id_resource_map.find(0x7f020000), Not(Eq(id_resource_map.end()))); EXPECT_THAT(id_resource_map.at(0x7f020000), Eq("mycolor")); + ASSERT_THAT(id_resource_map.find(0x7f030000), Not(Eq(id_resource_map.end()))); EXPECT_THAT(id_resource_map.at(0x7f030000), Eq("mystring")); EXPECT_THAT(id_resource_map.find(0x7f030001), Eq(id_resource_map.end())); EXPECT_THAT(id_resource_map.find(0x7f030002), Eq(id_resource_map.end())); @@ -300,17 +388,18 @@ TEST(ObfuscatorTest, WriteObfuscationMapInProtocolBufferFormat) { ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(), getProtocolBufferTableUnderTest().get())); - obfuscator.WriteObfuscationMap("obfuscated_map.pb"); + const auto map_path = testing::TempDir() + "/obfuscated_map.pb"; + ASSERT_TRUE(obfuscator.WriteObfuscationMap(map_path)); std::string pbOut; - android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */); + ASSERT_TRUE(android::base::ReadFileToString(map_path, &pbOut, false /* follow_symlinks */)); EXPECT_THAT(pbOut, HasSubstr("drawable/xmlfile.xml")); EXPECT_THAT(pbOut, HasSubstr("drawable/pngfile.png")); EXPECT_THAT(pbOut, HasSubstr("mycolor")); EXPECT_THAT(pbOut, HasSubstr("mystring")); pb::ResourceMappings resourceMappings; - EXPECT_THAT(resourceMappings.ParseFromString(pbOut), IsTrue()); - EXPECT_THAT(resourceMappings.collapsed_names().resource_names_size(), Eq(2)); + ASSERT_THAT(resourceMappings.ParseFromString(pbOut), IsTrue()); + ASSERT_THAT(resourceMappings.collapsed_names().resource_names_size(), Eq(2)); auto& resource_names = resourceMappings.collapsed_names().resource_names(); EXPECT_THAT(resource_names.at(0).name(), AnyOf(Eq("mycolor"), Eq("mystring"))); EXPECT_THAT(resource_names.at(1).name(), AnyOf(Eq("mycolor"), Eq("mystring"))); @@ -328,11 +417,14 @@ TEST(ObfuscatorTest, WriteObfuscatingMapWithNonEnabledOption) { ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(), getProtocolBufferTableUnderTest().get())); - obfuscator.WriteObfuscationMap("obfuscated_map.pb"); + const auto map_path = testing::TempDir() + "/obfuscated_map.pb"; + ASSERT_TRUE(obfuscator.WriteObfuscationMap(map_path)); std::string pbOut; - android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */); + ASSERT_TRUE(android::base::ReadFileToString(map_path, &pbOut, false /* follow_symlinks */)); ASSERT_THAT(pbOut, Eq("")); } +} // namespace + } // namespace aapt diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index 83a0f3f3f652..e48668cf96a3 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -98,6 +98,10 @@ class TestFile : public io::IFile { return source_; } + bool GetModificationTime(struct tm* buf) const override { + return false; + }; + private: DISALLOW_COPY_AND_ASSIGN(TestFile); diff --git a/tools/aapt2/trace/TraceBuffer.cpp b/tools/aapt2/trace/TraceBuffer.cpp index da5373936306..0988c313b65b 100644 --- a/tools/aapt2/trace/TraceBuffer.cpp +++ b/tools/aapt2/trace/TraceBuffer.cpp @@ -36,116 +36,142 @@ constexpr char kBegin = 'B'; constexpr char kEnd = 'E'; struct TracePoint { + char type; pid_t tid; int64_t time; std::string tag; - char type; }; std::vector<TracePoint> traces; +bool enabled = true; +constinit std::chrono::steady_clock::time_point startTime = {}; int64_t GetTime() noexcept { auto now = std::chrono::steady_clock::now(); - return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count(); + if (startTime == decltype(tracebuffer::startTime){}) { + startTime = now; + } + return std::chrono::duration_cast<std::chrono::microseconds>(now - startTime).count(); } -} // namespace anonymous - -void AddWithTime(const std::string& tag, char type, int64_t time) noexcept { - TracePoint t = {getpid(), time, tag, type}; - traces.emplace_back(t); +void AddWithTime(std::string tag, char type, int64_t time) noexcept { + TracePoint t = {type, getpid(), time, std::move(tag)}; + traces.emplace_back(std::move(t)); } -void Add(const std::string& tag, char type) noexcept { - AddWithTime(tag, type, GetTime()); +void Add(std::string tag, char type) noexcept { + AddWithTime(std::move(tag), type, GetTime()); } - - - void Flush(const std::string& basePath) { - TRACE_CALL(); if (basePath.empty()) { return; } + BeginTrace(__func__); // We can't do much here, only record that it happened. - std::stringstream s; + std::ostringstream s; s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json"; FILE* f = android::base::utf8::fopen(s.str().c_str(), "a"); if (f == nullptr) { return; } - for(const TracePoint& trace : traces) { - fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", " - "\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str()); + // Wrap the trace in a JSON array [] to make Chrome/Perfetto UI handle it. + char delimiter = '['; + for (const TracePoint& trace : traces) { + fprintf(f, + "%c{\"ts\" : \"%" PRIu64 + "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", \"name\" : \"%s\" }\n", + delimiter, trace.time, trace.type, 0, trace.tid, trace.tag.c_str()); + delimiter = ','; + } + if (!traces.empty()) { + fprintf(f, "]"); } fclose(f); traces.clear(); } +} // namespace + } // namespace tracebuffer -void BeginTrace(const std::string& tag) { - tracebuffer::Add(tag, tracebuffer::kBegin); +void BeginTrace(std::string tag) { + if (!tracebuffer::enabled) return; + tracebuffer::Add(std::move(tag), tracebuffer::kBegin); +} + +void EndTrace(std::string tag) { + if (!tracebuffer::enabled) return; + tracebuffer::Add(std::move(tag), tracebuffer::kEnd); +} + +bool Trace::enable(bool value) { + return tracebuffer::enabled = value; } -void EndTrace() { - tracebuffer::Add("", tracebuffer::kEnd); +Trace::Trace(const char* tag) { + if (!tracebuffer::enabled) return; + tag_.assign(tag); + tracebuffer::Add(tag_, tracebuffer::kBegin); } -Trace::Trace(const std::string& tag) { - tracebuffer::Add(tag, tracebuffer::kBegin); +Trace::Trace(std::string tag) : tag_(std::move(tag)) { + if (!tracebuffer::enabled) return; + tracebuffer::Add(tag_, tracebuffer::kBegin); } -Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) { - std::stringstream s; +template <class SpanOfStrings> +std::string makeTag(std::string_view tag, const SpanOfStrings& args) { + std::ostringstream s; s << tag; - s << " "; - for (auto& arg : args) { - s << arg; - s << " "; + if (!args.empty()) { + for (const auto& arg : args) { + s << ' '; + s << arg; + } } - tracebuffer::Add(s.str(), tracebuffer::kBegin); + return std::move(s).str(); +} + +Trace::Trace(std::string_view tag, const std::vector<android::StringPiece>& args) { + if (!tracebuffer::enabled) return; + tag_ = makeTag(tag, args); + tracebuffer::Add(tag_, tracebuffer::kBegin); } Trace::~Trace() { - tracebuffer::Add("", tracebuffer::kEnd); + if (!tracebuffer::enabled) return; + tracebuffer::Add(std::move(tag_), tracebuffer::kEnd); } -FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag) - : basepath_(basepath) { - tracebuffer::Add(tag, tracebuffer::kBegin); +FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag) { + if (!Trace::enable(!basepath.empty())) return; + basepath_.assign(basepath); + tag_.assign(tag); + tracebuffer::Add(tag_, tracebuffer::kBegin); } -FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, - const std::vector<android::StringPiece>& args) : basepath_(basepath) { - std::stringstream s; - s << tag; - s << " "; - for (auto& arg : args) { - s << arg; - s << " "; - } - tracebuffer::Add(s.str(), tracebuffer::kBegin); +FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag, + const std::vector<android::StringPiece>& args) { + if (!Trace::enable(!basepath.empty())) return; + basepath_.assign(basepath); + tag_ = makeTag(tag, args); + tracebuffer::Add(tag_, tracebuffer::kBegin); } -FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, - const std::vector<std::string>& args) : basepath_(basepath){ - std::stringstream s; - s << tag; - s << " "; - for (auto& arg : args) { - s << arg; - s << " "; - } - tracebuffer::Add(s.str(), tracebuffer::kBegin); +FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag, + const std::vector<std::string>& args) { + if (!Trace::enable(!basepath.empty())) return; + basepath_.assign(basepath); + tag_ = makeTag(tag, args); + tracebuffer::Add(tag_, tracebuffer::kBegin); } FlushTrace::~FlushTrace() { - tracebuffer::Add("", tracebuffer::kEnd); + if (!tracebuffer::enabled) return; + tracebuffer::Add(std::move(tag_), tracebuffer::kEnd); tracebuffer::Flush(basepath_); } -} // namespace aapt - +} // namespace aapt diff --git a/tools/aapt2/trace/TraceBuffer.h b/tools/aapt2/trace/TraceBuffer.h index ba751dd72f41..f0333d1fe071 100644 --- a/tools/aapt2/trace/TraceBuffer.h +++ b/tools/aapt2/trace/TraceBuffer.h @@ -17,41 +17,50 @@ #ifndef AAPT_TRACEBUFFER_H #define AAPT_TRACEBUFFER_H +#include <androidfw/StringPiece.h> + #include <string> +#include <string_view> #include <vector> -#include <androidfw/StringPiece.h> - namespace aapt { // Record timestamps for beginning and end of a task and generate systrace json fragments. // This is an in-process ftrace which has the advantage of being platform independent. // These methods are NOT thread-safe since aapt2 is not multi-threaded. -// Convenience RIAA object to automatically finish an event when object goes out of scope. +// Convenience RAII object to automatically finish an event when object goes out of scope. class Trace { public: - Trace(const std::string& tag); - Trace(const std::string& tag, const std::vector<android::StringPiece>& args); - ~Trace(); + Trace(const char* tag); + Trace(std::string tag); + Trace(std::string_view tag, const std::vector<android::StringPiece>& args); + ~Trace(); + + static bool enable(bool value = true); + +private: + std::string tag_; }; // Manual markers. -void BeginTrace(const std::string& tag); -void EndTrace(); +void BeginTrace(std::string tag); +void EndTrace(std::string tag); // A main trace is required to flush events to disk. Events are formatted in systrace // json format. class FlushTrace { public: - explicit FlushTrace(const std::string& basepath, const std::string& tag); - explicit FlushTrace(const std::string& basepath, const std::string& tag, - const std::vector<android::StringPiece>& args); - explicit FlushTrace(const std::string& basepath, const std::string& tag, - const std::vector<std::string>& args); - ~FlushTrace(); + explicit FlushTrace(std::string_view basepath, std::string_view tag); + explicit FlushTrace(std::string_view basepath, std::string_view tag, + const std::vector<android::StringPiece>& args); + explicit FlushTrace(std::string_view basepath, std::string_view tag, + const std::vector<std::string>& args); + ~FlushTrace(); + private: std::string basepath_; + std::string tag_; }; #define TRACE_CALL() Trace __t(__func__) diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp index be877660ef72..3d83caf29bba 100644 --- a/tools/aapt2/util/Util.cpp +++ b/tools/aapt2/util/Util.cpp @@ -21,6 +21,7 @@ #include <string> #include <vector> +#include "android-base/parseint.h" #include "android-base/stringprintf.h" #include "android-base/strings.h" #include "androidfw/BigBuffer.h" @@ -229,14 +230,29 @@ std::string GetToolFingerprint() { static const char* const sMinorVersion = "19"; // The build id of aapt2 binary. - static std::string sBuildId = android::build::GetBuildNumber(); - - if (android::base::StartsWith(sBuildId, "eng.")) { - time_t now = time(0); - tm* ltm = localtime(&now); + static const std::string sBuildId = [] { + std::string buildNumber = android::build::GetBuildNumber(); + + if (android::base::StartsWith(buildNumber, "eng.")) { + // android::build::GetBuildNumber() returns something like "eng.user.20230725.214219" where + // the latter two parts are "yyyyMMdd.HHmmss" at build time. Use "yyyyMM" in the fingerprint. + std::vector<std::string> parts = util::Split(buildNumber, '.'); + int buildYear; + int buildMonth; + if (parts.size() < 3 || parts[2].length() < 6 || + !android::base::ParseInt(parts[2].substr(0, 4), &buildYear) || + !android::base::ParseInt(parts[2].substr(4, 2), &buildMonth)) { + // Fallback to localtime() if GetBuildNumber() returns an unexpected output. + time_t now = time(0); + tm* ltm = localtime(&now); + buildYear = 1900 + ltm->tm_year; + buildMonth = 1 + ltm->tm_mon; + } - sBuildId = android::base::StringPrintf("eng.%d%d", 1900 + ltm->tm_year, 1 + ltm->tm_mon); - } + buildNumber = android::base::StringPrintf("eng.%04d%02d", buildYear, buildMonth); + } + return buildNumber; + }(); return android::base::StringPrintf("%s.%s-%s", sMajorVersion, sMinorVersion, sBuildId.c_str()); } diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt index 685733386cae..d3a8b033dfff 100644 --- a/tools/codegen/src/com/android/codegen/Generators.kt +++ b/tools/codegen/src/com/android/codegen/Generators.kt @@ -327,7 +327,8 @@ private fun ClassPrinter.generateBuilderSetters(visibility: String) { +"return$maybeCast this;" } - val javadocSeeSetter = "/** @see #$setterName */" + val javadocSeeSetter = + if (isHidden()) "/** @see #$setterName @hide */" else "/** @see #$setterName */" val adderName = "add$SingularName" val singularNameCustomizationHint = if (SingularNameOrNull == null) { @@ -750,6 +751,15 @@ fun ClassPrinter.generateGetters() { } } +fun FieldInfo.isHidden(): Boolean { + if (javadocFull != null) { + (javadocFull ?: "/**\n */").lines().forEach { + if (it.contains("@hide")) return true + } + } + return false +} + fun FieldInfo.generateFieldJavadoc(forceHide: Boolean = false) = classPrinter { if (javadocFull != null || forceHide) { var hidden = false diff --git a/tools/hoststubgen/.gitignore b/tools/hoststubgen/.gitignore new file mode 100644 index 000000000000..6453bdef8cee --- /dev/null +++ b/tools/hoststubgen/.gitignore @@ -0,0 +1,3 @@ +out/ +*-out/ +*.log diff --git a/tools/hoststubgen/OWNERS b/tools/hoststubgen/OWNERS new file mode 100644 index 000000000000..a8c5321307d1 --- /dev/null +++ b/tools/hoststubgen/OWNERS @@ -0,0 +1,3 @@ +omakoto@google.com +jsharkey@google.com +jaggies@google.com diff --git a/tools/hoststubgen/README.md b/tools/hoststubgen/README.md new file mode 100644 index 000000000000..b0a126292063 --- /dev/null +++ b/tools/hoststubgen/README.md @@ -0,0 +1,76 @@ +# HostStubGen + +## Overview + +This directory contains tools / sample code / investigation for host side test support. + + +## Directories and files + +- `hoststubgen/` + Contains source code of the "hoststubgen" tool and relevant code + + - `framework-policy-override.txt` + This file contains "policy overrides", which allows to control what goes to stub/impl without + having to touch the target java files. This allows quicker iteration, because you can skip + having to rebuild framework.jar. + + - `src/` + + HostStubGen tool source code. + + - `annotations-src/` See `Android.bp`. + - `helper-framework-buildtime-src/` See `Android.bp`. + - `helper-framework-runtime-src/` See `Android.bp`. + - `helper-runtime-src/` See `Android.bp`. + + - `test-tiny-framework/` See `README.md` in it. + + - `test-framework` See `README.md` in it. + +- `scripts` + - `run-host-test.sh` + + Run a host side test. Use it instead of `atest` for now. (`atest` works "mostly" but it has + problems.) + + - `dump-jar.sh` + + A script to dump the content of `*.class` and `*.jar` files. + + - `run-all-tests.sh` + + Run all tests. Many tests may fail, but at least this should run til the end. + (It should print `run-all-tests.sh finished` at the end) + +## Build and run + +### Building `HostStubGen` binary + +``` +m hoststubgen +``` + +### Run the tests + +- Run all relevant tests and test scripts. Some of thests are still expected to fail, + but this should print "finished, with no unexpected failures" at the end. + + However, because some of the script it executes depend on internal file paths to Soong's + intermediate directory, some of it might fail when something changes in the build system. + + We need proper build system integration to fix them. +``` +$ ./scripts/run-all-tests.sh +``` + +- See also `README.md` in `test-*` directories. + +## TODOs, etc + + - Make sure the parent's visibility is not smaller than the member's. + +- @HostSideTestNativeSubstitutionClass should automatically add class-keep to the substitute class. + (or at least check it.) + + - The `HostStubGenTest-framework-test-host-test-lib` jar somehow contain all ASM classes? Figure out where the dependency is coming from. diff --git a/tools/hoststubgen/TEST_MAPPING b/tools/hoststubgen/TEST_MAPPING new file mode 100644 index 000000000000..192b6f2b5e25 --- /dev/null +++ b/tools/hoststubgen/TEST_MAPPING @@ -0,0 +1,11 @@ +{ + "presubmit": [ + { "name": "tiny-framework-dump-test" }, + { "name": "hoststubgentest" }, + { "name": "hoststubgen-invoke-test" } + + // As a smoke test. + // TODO: Enable it once the infra knows how to run it. + // { "name": "CtsUtilTestCasesRavenwood" } + ] +} diff --git a/tools/hoststubgen/common.sh b/tools/hoststubgen/common.sh new file mode 100644 index 000000000000..b49ee39a3142 --- /dev/null +++ b/tools/hoststubgen/common.sh @@ -0,0 +1,116 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e # Exit at failure +shopt -s globstar # Enable double-star wildcards (**) + +cd "${0%/*}" # Move to the script dir + +fail() { + echo "Error: $*" 1>&2 + exit 1 +} + +# Print the arguments and then execute. +run() { + echo "Running: $*" 1>&2 + "$@" +} + +# Concatenate the second and subsequent args with the first arg as a separator. +# e.g. `join : a b c` -> prints `a:b:c` +join() { + local IFS="$1" + shift + echo "$*" +} + +abspath() { + for name in "${@}"; do + readlink -f $name + done +} + +m() { + if (( $SKIP_BUILD )) ; then + echo "Skipping build: $*" 1>&2 + return 0 + fi + run ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@" +} + +# Extract given jar files +extract() { + for f in "${@}"; do + local out=$f.ext + run rm -fr $out + run mkdir -p $out + + # It's too noisy, so only show the first few lines. + { + # Hmm unzipping kotlin jar files may produce a warning? Let's just add `|| true`... + run unzip $f -d $out || true + } |& sed -e '5,$d' + echo ' (omitting remaining output)' + + done +} + +# Find all *.java files in $1, and print them as Java class names. +# For example, if there's a file `src/com/android/test/Test.java`, and you run +# `list_all_classes_under_dir src`, then it'll print `com.android.test.Test`. +list_all_classes_under_dir() { + local dir="$1" + ( # Use a subshell, so we won't change the current directory on the caller side. + cd "$dir" + + # List the java files, but replace the slashes with dots, and remove the `.java` suffix. + ls **/*.java | sed -e 's!/!.!g' -e 's!.java$!!' + ) +} + +checkenv() { + # Make sure $ANDROID_BUILD_TOP is set. + : ${ANDROID_BUILD_TOP:?} + + # Make sure ANDROID_BUILD_TOP doesn't contain whitespace. + set ${ANDROID_BUILD_TOP} + if [[ $# != 1 ]] ; then + fail "\$ANDROID_BUILD_TOP cannot contain whitespace." + fi +} + +checkenv + +JAVAC=${JAVAC:-javac} +JAVA=${JAVA:-java} +JAR=${JAR:-jar} + +JAVAC_OPTS=${JAVAC_OPTS:--Xmaxerrs 99999 -Xlint:none} + +SOONG_INT=$ANDROID_BUILD_TOP/out/soong/.intermediates + +JUNIT_TEST_MAIN_CLASS=com.android.hoststubgen.hosthelper.HostTestSuite + +run_junit_test_jar() { + local jar="$1" + echo "Starting test: $jar ..." + run cd "${jar%/*}" + + run $JAVA $JAVA_OPTS \ + -cp $jar \ + org.junit.runner.JUnitCore \ + $main_class || return 1 + return 0 +} diff --git a/tools/hoststubgen/hoststubgen/.gitignore b/tools/hoststubgen/hoststubgen/.gitignore new file mode 100644 index 000000000000..0f384074ed7f --- /dev/null +++ b/tools/hoststubgen/hoststubgen/.gitignore @@ -0,0 +1 @@ +framework-all-stub-out
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp new file mode 100644 index 000000000000..5949bca2f9a3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/Android.bp @@ -0,0 +1,375 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +// Visibility only for ravenwood prototype uses. +genrule_defaults { + name: "hoststubgen-for-prototype-only-genrule", + visibility: [ + ":__subpackages__", + "//frameworks/base", + "//frameworks/base/ravenwood:__subpackages__", + ], +} + +// Visibility only for ravenwood prototype uses. +java_defaults { + name: "hoststubgen-for-prototype-only-java", + visibility: [ + ":__subpackages__", + "//frameworks/base", + "//frameworks/base/ravenwood:__subpackages__", + ], +} + +// Visibility only for ravenwood prototype uses. +filegroup_defaults { + name: "hoststubgen-for-prototype-only-filegroup", + visibility: [ + ":__subpackages__", + "//frameworks/base", + "//frameworks/base/ravenwood:__subpackages__", + ], +} + +// This library contains the standard hoststubgen annotations. +// This is only for the prototype. The productionized version is "ravenwood-annotations". +java_library { + name: "hoststubgen-annotations", + defaults: ["hoststubgen-for-prototype-only-java"], + srcs: [ + "annotations-src/**/*.java", + ], + host_supported: true, + + sdk_version: "core_current", +} + +// This library contains helper classes used in the host side test environment at runtime. +// This library is _not_ specific to Android APIs. +java_library_host { + name: "hoststubgen-helper-runtime", + srcs: [ + "helper-runtime-src/**/*.java", + ], + libs: [ + "junit", + ], + static_libs: [ + "guava", + ], + jarjar_rules: "jarjar-rules.txt", + visibility: ["//visibility:public"], +} + +java_library { + name: "hoststubgen-helper-runtime.ravenwood", + srcs: [ + "helper-runtime-src/**/*.java", + ], + libs: [ + "junit", + ], + static_libs: [ + "guava", + ], + jarjar_rules: "jarjar-rules.txt", + visibility: ["//visibility:public"], +} + +// Host-side stub generator tool. +java_binary_host { + name: "hoststubgen", + main_class: "com.android.hoststubgen.Main", + srcs: ["src/**/*.kt"], + static_libs: [ + "hoststubgen-helper-runtime", + "junit", + "ow2-asm", + "ow2-asm-analysis", + "ow2-asm-commons", + "ow2-asm-tree", + "ow2-asm-util", + ], + visibility: ["//visibility:public"], +} + +java_test_host { + name: "hoststubgentest", + // main_class: "com.android.hoststubgen.Main", + srcs: ["test/**/*.kt"], + static_libs: [ + "hoststubgen", + "truth", + ], + test_suites: ["general-tests"], + visibility: ["//visibility:private"], +} + +// File that contains the standard command line argumetns to hoststubgen. +// This is only for the prototype. The productionized version is "ravenwood-standard-options". +filegroup { + name: "hoststubgen-standard-options", + defaults: ["hoststubgen-for-prototype-only-filegroup"], + srcs: [ + "hoststubgen-standard-options.txt", + ], +} + +hoststubgen_common_options = "$(location hoststubgen) " + + // "--in-jar $(location :framework-all) " + + // "--policy-override-file $(location framework-policy-override.txt) " + + "@$(location :hoststubgen-standard-options) " + + + "--out-stub-jar $(location host_stub.jar) " + + "--out-impl-jar $(location host_impl.jar) " + + + // "--keep-all-classes " + // Used it for an experiment. See KeepAllClassesFilter. + "--gen-keep-all-file $(location hoststubgen_keep_all.txt) " + + "--gen-input-dump-file $(location hoststubgen_dump.txt) " + + "" + +// Common defaults for stub generation. +// This one is not specific to Android APIs. +genrule_defaults { + name: "hoststubgen-command-defaults", + tools: ["hoststubgen"], + srcs: [ + ":hoststubgen-standard-options", + ], + // Create two jar files. + out: [ + "host_stub.jar", + "host_impl.jar", + + // Following files are created just as FYI. + "hoststubgen_keep_all.txt", + "hoststubgen_dump.txt", + ], +} + +// Generate the stub/impl from framework-all, with hidden APIs. +java_genrule_host { + name: "framework-all-hidden-api-host", + defaults: ["hoststubgen-command-defaults"], + cmd: hoststubgen_common_options + + "--in-jar $(location :framework-all) " + + "--policy-override-file $(location framework-policy-override.txt) ", + srcs: [ + ":framework-all", + "framework-policy-override.txt", + ], + visibility: ["//visibility:private"], +} + +// Extract the stub jar from "framework-all-host" for subsequent build rules. +// This is only for the prototype. Do not use it in "productionized" build rules. +java_genrule_host { + name: "framework-all-hidden-api-host-stub", + defaults: ["hoststubgen-for-prototype-only-genrule"], + cmd: "cp $(in) $(out)", + srcs: [ + ":framework-all-hidden-api-host{host_stub.jar}", + ], + out: [ + "host_stub.jar", + ], +} + +// Extract the impl jar from "framework-all-host" for subsequent build rules. +// This is only for the prototype. Do not use it in "productionized" build rules. +java_genrule_host { + name: "framework-all-hidden-api-host-impl", + defaults: ["hoststubgen-for-prototype-only-genrule"], + cmd: "cp $(in) $(out)", + srcs: [ + ":framework-all-hidden-api-host{host_impl.jar}", + ], + out: [ + "host_impl.jar", + ], +} + +// Generate the stub/impl from framework-all, with only public/system/test APIs, without +// hidden APIs. +// This is only for the prototype. Do not use it in "productionized" build rules. +java_genrule_host { + name: "framework-all-test-api-host", + defaults: ["hoststubgen-command-defaults"], + cmd: hoststubgen_common_options + + "--intersect-stub-jar $(location :android_test_stubs_current{.jar}) " + + "--in-jar $(location :framework-all) " + + "--policy-override-file $(location framework-policy-override.txt) ", + srcs: [ + ":framework-all", + ":android_test_stubs_current{.jar}", + "framework-policy-override.txt", + ], + visibility: ["//visibility:private"], +} + +// Extract the stub jar from "framework-all-test-api-host" for subsequent build rules. +// This is only for the prototype. Do not use it in "productionized" build rules. +java_genrule_host { + name: "framework-all-test-api-host-stub", + defaults: ["hoststubgen-for-prototype-only-genrule"], + cmd: "cp $(in) $(out)", + srcs: [ + ":framework-all-test-api-host{host_stub.jar}", + ], + out: [ + "host_stub.jar", + ], +} + +// Extract the impl jar from "framework-all-test-api-host" for subsequent build rules. +// This is only for the prototype. Do not use it in "productionized" build rules. +java_genrule_host { + name: "framework-all-test-api-host-impl", + defaults: ["hoststubgen-for-prototype-only-genrule"], + cmd: "cp $(in) $(out)", + srcs: [ + ":framework-all-test-api-host{host_impl.jar}", + ], + out: [ + "host_impl.jar", + ], +} + +// This library contains helper classes to build hostside tests/targets. +// This essentially contains dependencies from tests that we can't actually use the real ones. +// For example, the actual AndroidTestCase and AndroidJUnit4 don't run on the host side (yet), +// so we pup "fake" implementations here. +// Ideally this library should be empty. +java_library_host { + name: "hoststubgen-helper-framework-buildtime", + defaults: ["hoststubgen-for-prototype-only-java"], + srcs: [ + "helper-framework-buildtime-src/**/*.java", + ], + libs: [ + // We need it to pull in some of the framework classes used in this library, + // such as Context.java. + "framework-all-hidden-api-host-impl", + "junit", + ], +} + +// This module contains "fake" libcore/dalvik classes, framework native substitution, etc, +// that are needed at runtime. +java_library_host { + name: "hoststubgen-helper-framework-runtime", + defaults: ["hoststubgen-for-prototype-only-java"], + srcs: [ + "helper-framework-runtime-src/**/*.java", + ], + libs: [ + "hoststubgen-helper-runtime", + "framework-all-hidden-api-host-impl", + ], +} + +java_library { + name: "hoststubgen-helper-framework-runtime.ravenwood", + defaults: ["hoststubgen-for-prototype-only-java"], + srcs: [ + "helper-framework-runtime-src/framework/**/*.java", + ], + libs: [ + "hoststubgen-helper-runtime.ravenwood", + "framework-minus-apex.ravenwood", + ], + static_libs: [ + "core-xml-for-device", + ], +} + +// Defaults for host side test modules. +// We need two rules for each test. +// 1. A "-test-lib" jar, which compiles the test against the stub jar. +// This one is only used by the second rule, so it should be "private. +// 2. A "-test" jar, which includes 1 + the runtime (impl) jars. + +// This and next ones are for tests using framework-app, with hidden APIs. +java_defaults { + name: "hosttest-with-framework-all-hidden-api-test-lib-defaults", + installable: false, + libs: [ + "framework-all-hidden-api-host-stub", + ], + static_libs: [ + "hoststubgen-helper-framework-buildtime", + "framework-annotations-lib", + ], + visibility: ["//visibility:private"], +} + +// Default rules to include `libandroid_runtime`. For now, it's empty, but we'll use it +// once we start using JNI. +java_defaults { + name: "hosttest-with-libandroid_runtime", + jni_libs: [ + // "libandroid_runtime", + + // TODO: Figure out how to build them automatically. + // Following ones are depended by libandroid_runtime. + // Without listing them here, not only we won't get them under + // $ANDROID_HOST_OUT/testcases/*/lib64, but also not under + // $ANDROID_HOST_OUT/lib64, so we'd fail to load them at runtime. + // ($ANDROID_HOST_OUT/lib/ gets all of them though.) + // "libcutils", + // "libharfbuzz_ng", + // "libminikin", + // "libz", + // "libbinder", + // "libhidlbase", + // "libvintf", + // "libicu", + // "libutils", + // "libtinyxml2", + ], +} + +java_defaults { + name: "hosttest-with-framework-all-hidden-api-test-defaults", + defaults: ["hosttest-with-libandroid_runtime"], + installable: false, + test_config: "AndroidTest-host.xml", + static_libs: [ + "hoststubgen-helper-runtime", + "hoststubgen-helper-framework-runtime", + "framework-all-hidden-api-host-impl", + ], +} + +// This and next ones are for tests using framework-app, with public/system/test APIs, +// without hidden APIs. +java_defaults { + name: "hosttest-with-framework-all-test-api-test-lib-defaults", + installable: false, + libs: [ + "framework-all-test-api-host-stub", + ], + static_libs: [ + "hoststubgen-helper-framework-buildtime", + "framework-annotations-lib", + ], + visibility: ["//visibility:private"], +} + +java_defaults { + name: "hosttest-with-framework-all-test-api-test-defaults", + defaults: ["hosttest-with-libandroid_runtime"], + installable: false, + test_config: "AndroidTest-host.xml", + static_libs: [ + "hoststubgen-helper-runtime", + "hoststubgen-helper-framework-runtime", + "framework-all-test-api-host-impl", + ], +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java new file mode 100644 index 000000000000..a774336a897c --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * Add this with a fully-specified method name (e.g. {@code "com.package.Class.methodName"}) + * of a callback to get a callback at the class load time. + * + * The method must be {@code public static} with a single argument that takes + * {@link java.lang.Class}. + */ +@Target({TYPE}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestClassLoadHook { + String value(); +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java new file mode 100644 index 000000000000..06ad1c266a14 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * Mark a class, field or a method as "Stub", meaning tests can _not_ see the APIs, but they + * can indirectly be used on the host side. + * When applied to a class, it will _not_ affect the visibility of its members. They need to be + * individually marked. + * + * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub} + * instead. + * @hide + */ +@Target({TYPE, FIELD, METHOD, CONSTRUCTOR}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestKeep { +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java new file mode 100644 index 000000000000..9c8138351eb5 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * If a class has this annotation, all its native methods will be delegated to another class. + * (See {@link android.os.Parcel} as an example.) + */ +@Target({TYPE}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestNativeSubstitutionClass { + String value(); +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java new file mode 100644 index 000000000000..46e5078fb05d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * Mark an item as "remove", so this cannot be used on the host side even indirectly. + * This is the default behavior. + * + * @hide + */ +@Target({TYPE, FIELD, METHOD, CONSTRUCTOR}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestRemove { +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStaticInitializerKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStaticInitializerKeep.java new file mode 100644 index 000000000000..eec72269e0d3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStaticInitializerKeep.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * @hide + */ +@Target({TYPE, FIELD, METHOD, CONSTRUCTOR}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestStaticInitializerKeep { +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java new file mode 100644 index 000000000000..cabdfe0eeb77 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * Mark a class, field or a method as "Stub", meaning tests can see the APIs. + * When applied to a class, it will _not_ affect the visibility of its members. They need to be + * individually marked. + * + * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub} + * instead. + * + * @hide + */ +@Target({TYPE, FIELD, METHOD, CONSTRUCTOR}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestStub { +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java new file mode 100644 index 000000000000..510a67e0aaed --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.METHOD; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * If a method has this annotation, we'll replace it with another method on the host side. + * + * See {@link android.util.LruCache#getEldest()} and its substitution. + * + * @hide + */ +@Target({METHOD}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestSubstitute { + // TODO We should add "_host" as default. We're not doing it yet, because extractign the default + // value with ASM doesn't seem trivial. (? not sure.) + String suffix(); +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java new file mode 100644 index 000000000000..cd1bef4be505 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * If a method has this annotation, it will throw on the host side. + * + * @hide + */ +@Target({METHOD, CONSTRUCTOR}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestThrow { +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java new file mode 100644 index 000000000000..3d1ddea2cbb7 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * Same as {@link HostSideTestKeep} but it'll change the visibility of all its members too. + * @hide + */ +@Target({TYPE}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestWholeClassKeep { +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java new file mode 100644 index 000000000000..1824f6f01516 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation; + +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY + * QUESTIONS ABOUT IT. + * + * Same as {@link HostSideTestStub} but it'll change the visibility of all its members too. + * + * @hide + */ +@Target({TYPE}) +@Retention(RetentionPolicy.CLASS) +public @interface HostSideTestWholeClassStub { +} diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java new file mode 100644 index 000000000000..b10f0ff1a4b1 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hosttest.annotation.tests; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Target; + +/** + * Use this annotation to skip certain tests for host side tests. + * + * TODO: Actually use it in the test runner. + */ +@Target({TYPE, FIELD, METHOD}) +public @interface HostSideTestSuppress { +} diff --git a/tools/hoststubgen/hoststubgen/framework-policy-override.txt b/tools/hoststubgen/hoststubgen/framework-policy-override.txt new file mode 100644 index 000000000000..493ad56a5cbb --- /dev/null +++ b/tools/hoststubgen/hoststubgen/framework-policy-override.txt @@ -0,0 +1,102 @@ +# -------------------------------------------------------------------------------------------------- +# This file contains rules to process `framework-all.jar` to generate the host side test "stub" and +# "impl" jars, without using Java annotations. +# +# Useful when: +# - The class is auto-generated and annotations can't be added. +# (We need to figure out what to do on auto-generated classes.) +# - Want to quickly change filter rules without having to rebuild framework.jar. +# +# Using this file, one can control the visibility of APIs on a per-class, per-field and per-method +# basis, but in most cases, per-class directives would be sufficient. That is: +# +# - To put the entire class, including its members and nested classes, in the "stub" jar, +# so that the test / target code can use the API, use `stubclass`. +# +# class package.class stubclass +# +# - To put the entire class, including its members and nested classes, in the "impl" jar, +# but not in the "stub" jar, use `keepclass`. Use this when you don't want to expose an API to +# tests/target directly, but it's still needed at runtime, because it's used by other "stub" APIs +# directly or indirectly. +# +# class package.class keepclass +# +# All other classes will be removed from both the stub jar and impl jar. +# +# -------------------------------------------------------------------------------------------------- + +# -------------------------------------------------------------------------------------------------- +# Directions on auto-generated classes, where we can't use Java annotations (yet). +# -------------------------------------------------------------------------------------------------- +class android.Manifest stubclass +class android.R stubclass +class android.os.PersistableBundleProto keepclass + +# This is in module-utils, where using a HostStubGen annotation would be complicated, so we +# add a direction here rather than using a java annotation. +# The build file says it's deprecated, anyway...? Figure out what to do with it. +class com.android.internal.util.Preconditions keepclass + +# -------------------------------------------------------------------------------------------------- +# Actual framework classes +# -------------------------------------------------------------------------------------------------- + +# Put basic exception classes in the "impl" jar. +# We don't put them in stub yet (until something actually needs them). +class android.os.DeadObjectException keepclass +class android.os.DeadSystemRuntimeException keepclass +class android.os.NetworkOnMainThreadException keepclass +class android.os.RemoteException keepclass +class android.os.ServiceSpecificException keepclass +class android.util.AndroidException keepclass +class android.util.AndroidRuntimeException keepclass +class android.os.DeadSystemException keepclass + + +# For now, we only want to expose ArrayMap and Log, but they and their tests depend on +# more classes. + +class android.util.ArrayMap stubclass + +# Used by ArrayMap. No need to put them in the stub, but we need them in impl. +class android.util.MapCollections keepclass +class android.util.ContainerHelpers keepclass +class android.util.EmptyArray stubclass +class com.android.internal.util.XmlUtils keepclass +class com.android.internal.util.FastMath keepclass +class android.util.MathUtils keepclass + + +class android.util.Log stubclass +class android.util.Slog stubclass +# We don't use Log's native code, yet. Instead, the following line enables the Java substitution. +# Comment it out to disable Java substitution of Log's native methods. +class android.util.Log !com.android.hoststubgen.nativesubstitution.Log_host + +# Used by log +class com.android.internal.util.FastPrintWriter keepclass +class com.android.internal.util.LineBreakBufferedWriter keepclass + +class android.util.EventLog stubclass +class android.util.EventLog !com.android.hoststubgen.nativesubstitution.EventLog_host +class android.util.EventLog$Event stubclass + +# Expose Context because it's referred to by AndroidTestCase, but don't need to expose any of +# its members. +class android.content.Context keep + +# Expose Parcel, Parcel and there relevant classes, which are used by ArrayMapTets. +class android.os.Parcelable StubClass +class android.os.Parcel StubClass +class android.os.Parcel !com.android.hoststubgen.nativesubstitution.Parcel_host + +class android.os.IBinder stubClass +class android.os.IInterface stubclass + +class android.os.BadParcelableException stubclass +class android.os.BadTypeParcelableException stubclass + +class android.os.BaseBundle stubclass +class android.os.Bundle stubclass +class android.os.PersistableBundle stubclass diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java new file mode 100644 index 000000000000..e6d38668335a --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.test; + +import android.content.Context; + +import junit.framework.TestCase; + +public class AndroidTestCase extends TestCase { + protected Context mContext; + public Context getContext() { + throw new RuntimeException("[ravenwood] Class Context is not supported yet."); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java new file mode 100644 index 000000000000..51c5d9a05e52 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.annotation; + +// [ravenwood] TODO: Find the actual androidx jar containing it.s + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Denotes that a parameter, field or method return value can never be null. + * <p> + * This is a marker annotation and it has no specific attributes. + * + * @paramDoc This value cannot be {@code null}. + * @returnDoc This value cannot be {@code null}. + * @hide + */ +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface NonNull { +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java new file mode 100644 index 000000000000..f1f0e8b43f16 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.annotation; + +// [ravenwood] TODO: Find the actual androidx jar containing it.s + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Denotes that a parameter, field or method return value can be null. + * <p> + * When decorating a method call parameter, this denotes that the parameter can + * legitimately be null and the method will gracefully deal with it. Typically + * used on optional parameters. + * <p> + * When decorating a method, this denotes the method might legitimately return + * null. + * <p> + * This is a marker annotation and it has no specific attributes. + * + * @paramDoc This value may be {@code null}. + * @returnDoc This value may be {@code null}. + * @hide + */ +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface Nullable { +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java new file mode 100644 index 000000000000..0c82e4e268d3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.test.ext.junit.runners; + +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.InitializationError; + +// TODO: We need to simulate the androidx test runner. +// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/ext/junit/java/androidx/test/ext/junit/runners/AndroidJUnit4.java +// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/runner/android_junit_runner/java/androidx/test/internal/runner/junit4/AndroidJUnit4ClassRunner.java + +public class AndroidJUnit4 extends BlockJUnit4ClassRunner { + public AndroidJUnit4(Class<?> testClass) throws InitializationError { + super(testClass); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java new file mode 100644 index 000000000000..2470d8390f5d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.test.filters; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Designates a test as being flaky (non-deterministic). + * + * <p>Can then be used to filter tests on execution using -e annotation or -e notAnnotation as + * desired. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface FlakyTest { + /** + * An optional bug number associated with the test. -1 Means that no bug number is associated with + * the flaky annotation. + * + * @return int + */ + int bugId() default -1; + + /** + * Details, such as the reason of why the test is flaky. + * + * @return String + */ + String detail() default ""; +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java new file mode 100644 index 000000000000..578d7dc73647 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.test.filters; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to assign a large test size qualifier to a test. This annotation can be used at a + * method or class level. + * + * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a + * test suite of similar run time. + * + * <p>Execution time: >1000ms + * + * <p>Large tests should be focused on testing integration of all application components. These + * tests fully participate in the system and may make use of all resources such as databases, file + * systems and network. As a rule of thumb most functional UI tests are large tests. + * + * <p>Note: This class replaces the deprecated Android platform size qualifier <a + * href="{@docRoot}reference/android/test/suitebuilder/annotation/LargeTest.html"><code> + * android.test.suitebuilder.annotation.LargeTest</code></a> and is the recommended way to annotate + * tests written with the AndroidX Test Library. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface LargeTest {} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java new file mode 100644 index 000000000000..dfdaa53ee6ac --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.test.filters; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to assign a medium test size qualifier to a test. This annotation can be used at a + * method or class level. + * + * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a + * test suite of similar run time. + * + * <p>Execution time: <1000ms + * + * <p>Medium tests should be focused on a very limited subset of components or a single component. + * Resource access to the file system through well defined interfaces like databases, + * ContentProviders, or Context is permitted. Network access should be restricted, (long-running) + * blocking operations should be avoided and use mock objects instead. + * + * <p>Note: This class replaces the deprecated Android platform size qualifier <a + * href="{@docRoot}reference/android/test/suitebuilder/annotation/MediumTest.html"><code> + * android.test.suitebuilder.annotation.MediumTest</code></a> and is the recommended way to annotate + * tests written with the AndroidX Test Library. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface MediumTest {} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java new file mode 100644 index 000000000000..3d3ee3318bfa --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.test.filters; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates that a specific test should not be run on emulator. + * + * <p>It will be executed only if the test is running on the physical android device. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface RequiresDevice {} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java new file mode 100644 index 000000000000..dd65ddb382dc --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.test.filters; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates that a specific test or class requires a minimum or maximum API Level to execute. + * + * <p>Test(s) will be skipped when executed on android platforms less/more than specified level + * (inclusive). + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface SdkSuppress { + /** The minimum API level to execute (inclusive) */ + int minSdkVersion() default 1; + /** The maximum API level to execute (inclusive) */ + int maxSdkVersion() default Integer.MAX_VALUE; + /** + * The {@link android.os.Build.VERSION.CODENAME} to execute on. This is intended to be used to run + * on a pre-release SDK, where the {@link android.os.Build.VERSION.SDK_INT} has not yet been + * finalized. This is treated as an OR operation with respect to the minSdkVersion and + * maxSdkVersion attributes. + * + * <p>For example, to filter a test so it runs on only the prerelease R SDK: <code> + * {@literal @}SdkSuppress(minSdkVersion = Build.VERSION_CODES.R, codeName = "R") + * </code> + */ + String codeName() default "unset"; +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java new file mode 100644 index 000000000000..dd32df44effe --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.test.filters; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to assign a small test size qualifier to a test. This annotation can be used at a + * method or class level. + * + * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a + * test suite of similar run time. + * + * <p>Execution time: <200ms + * + * <p>Small tests should be run very frequently. Focused on units of code to verify specific logical + * conditions. These tests should runs in an isolated environment and use mock objects for external + * dependencies. Resource access (such as file system, network, or databases) are not permitted. + * Tests that interact with hardware, make binder calls, or that facilitate android instrumentation + * should not use this annotation. + * + * <p>Note: This class replaces the deprecated Android platform size qualifier <a + * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/SmallTest.html"> + * android.test.suitebuilder.annotation.SmallTest</a> and is the recommended way to annotate tests + * written with the AndroidX Test Library. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface SmallTest {} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java new file mode 100644 index 000000000000..88e636c2dd77 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.test.filters; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Use this annotation on test classes or test methods that should not be included in a test suite. + * If the annotation appears on the class then no tests in that class will be included. If the + * annotation appears only on a test method then only that method will be excluded. + * + * <p>Note: This class replaces the deprecated Android platform annotation <a + * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/Suppress.html"> + * android.test.suitebuilder.annotation.Suppress</a> and is the recommended way to suppress tests + * written with the AndroidX Test Library. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface Suppress {} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java new file mode 100644 index 000000000000..e1379390f98b --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.test.runner; + +import org.junit.runners.model.InitializationError; + +public class AndroidJUnit4 extends androidx.test.ext.junit.runners.AndroidJUnit4 { + public AndroidJUnit4(Class<?> testClass) throws InitializationError { + super(testClass); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/EventLog_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/EventLog_host.java new file mode 100644 index 000000000000..292e8da0de10 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/EventLog_host.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.nativesubstitution; + +import android.util.Log; +import android.util.Log.Level; + +import java.util.Collection; + +public class EventLog_host { + public static int writeEvent(int tag, int value) { + return writeEvent(tag, (Object) value); + } + + public static int writeEvent(int tag, long value) { + return writeEvent(tag, (Object) value); + } + + public static int writeEvent(int tag, float value) { + return writeEvent(tag, (Object) value); + } + + public static int writeEvent(int tag, String str) { + return writeEvent(tag, (Object) str); + } + + public static int writeEvent(int tag, Object... list) { + final StringBuilder sb = new StringBuilder(); + sb.append("logd: [event] "); + final String tagName = android.util.EventLog.getTagName(tag); + if (tagName != null) { + sb.append(tagName); + } else { + sb.append(tag); + } + sb.append(": ["); + for (int i = 0; i < list.length; i++) { + sb.append(String.valueOf(list[i])); + if (i < list.length - 1) { + sb.append(','); + } + } + sb.append(']'); + System.out.println(sb.toString()); + return sb.length(); + } + + public static void readEvents(int[] tags, Collection<android.util.EventLog.Event> output) { + throw new UnsupportedOperationException(); + } + + public static void readEventsOnWrapping(int[] tags, long timestamp, + Collection<android.util.EventLog.Event> output) { + throw new UnsupportedOperationException(); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java new file mode 100644 index 000000000000..ee55c7ac6ae2 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.nativesubstitution; + +import android.util.Log; +import android.util.Log.Level; + +import java.io.PrintStream; + +public class Log_host { + + public static boolean isLoggable(String tag, @Level int level) { + return true; + } + + public static int println_native(int bufID, int priority, String tag, String msg) { + final PrintStream out = System.out; + final String buffer; + switch (bufID) { + case Log.LOG_ID_MAIN: buffer = "main"; break; + case Log.LOG_ID_RADIO: buffer = "radio"; break; + case Log.LOG_ID_EVENTS: buffer = "event"; break; + case Log.LOG_ID_SYSTEM: buffer = "system"; break; + case Log.LOG_ID_CRASH: buffer = "crash"; break; + default: buffer = "buf:" + bufID; break; + }; + + final String prio; + switch (priority) { + case Log.VERBOSE: prio = "V"; break; + case Log.DEBUG: prio = "D"; break; + case Log.INFO: prio = "I"; break; + case Log.WARN: prio = "W"; break; + case Log.ERROR: prio = "E"; break; + case Log.ASSERT: prio = "A"; break; + default: prio = "prio:" + priority; break; + }; + + for (String s : msg.split("\\n")) { + out.println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s)); + } + return msg.length(); + } + + public static int logger_entry_max_payload_native() { + return 4068; // [ravenwood] This is what people use in various places. + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java new file mode 100644 index 000000000000..668c94c0f91c --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.nativesubstitution; + +import android.os.IBinder; + +import java.io.FileDescriptor; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Tentative, partial implementation of the Parcel native methods, using Java's + * {@code byte[]}. + * (We don't use a {@link ByteBuffer} because there's enough semantics differences between Parcel + * and {@link ByteBuffer}, and it didn't work out. + * e.g. Parcel seems to allow moving the data position to be beyond its size? Which + * {@link ByteBuffer} wouldn't allow...) + */ +public class Parcel_host { + private Parcel_host() { + } + + private static final AtomicLong sNextId = new AtomicLong(0); + + private static final Map<Long, Parcel_host> sInstances = new ConcurrentHashMap<>(); + + private boolean mDeleted = false; + + private byte[] mBuffer; + private int mSize; + private int mPos; + + private boolean mSensitive; + private boolean mAllowFds; + + // TODO Use the actual value from Parcel.java. + private static final int OK = 0; + + private void validate() { + if (mDeleted) { + // TODO: Put more info + throw new RuntimeException("Parcel already destroyed"); + } + } + + private static Parcel_host getInstance(long id) { + Parcel_host p = sInstances.get(id); + if (p == null) { + // TODO: Put more info + throw new RuntimeException("Parcel doesn't exist with id=" + id); + } + p.validate(); + return p; + } + + public static long nativeCreate() { + final long id = sNextId.getAndIncrement(); + final Parcel_host p = new Parcel_host(); + sInstances.put(id, p); + p.init(); + return id; + } + + private void init() { + mBuffer = new byte[0]; + mSize = 0; + mPos = 0; + mSensitive = false; + mAllowFds = false; + } + + private void updateSize() { + if (mSize < mPos) { + mSize = mPos; + } + } + + public static void nativeDestroy(long nativePtr) { + getInstance(nativePtr).mDeleted = true; + sInstances.remove(nativePtr); + } + + public static void nativeFreeBuffer(long nativePtr) { + getInstance(nativePtr).freeBuffer(); + } + + public void freeBuffer() { + init(); + } + + private int getCapacity() { + return mBuffer.length; + } + + private void ensureMoreCapacity(int size) { + ensureCapacity(mPos + size); + } + + private void ensureCapacity(int targetSize) { + if (targetSize <= getCapacity()) { + return; + } + var newSize = getCapacity() * 2; + if (newSize < targetSize) { + newSize = targetSize; + } + forceSetCapacity(newSize); + } + + private void forceSetCapacity(int newSize) { + var newBuf = new byte[newSize]; + + // Copy + System.arraycopy(mBuffer, 0, newBuf, 0, Math.min(newSize, getCapacity())); + + this.mBuffer = newBuf; + } + + private void ensureDataAvailable(int requestSize) { + if (mSize - mPos < requestSize) { + throw new RuntimeException(String.format( + "Pacel data underflow. size=%d, pos=%d, request=%d", mSize, mPos, requestSize)); + } + } + + public static void nativeMarkSensitive(long nativePtr) { + getInstance(nativePtr).mSensitive = true; + } + public static void nativeMarkForBinder(long nativePtr, IBinder binder) { + throw new RuntimeException("Not implemented yet"); + } + public static boolean nativeIsForRpc(long nativePtr) { + throw new RuntimeException("Not implemented yet"); + } + public static int nativeDataSize(long nativePtr) { + return getInstance(nativePtr).mSize; + } + public static int nativeDataAvail(long nativePtr) { + var p = getInstance(nativePtr); + return p.mSize - p.mPos; + } + public static int nativeDataPosition(long nativePtr) { + return getInstance(nativePtr).mPos; + } + public static int nativeDataCapacity(long nativePtr) { + return getInstance(nativePtr).mBuffer.length; + } + public static void nativeSetDataSize(long nativePtr, int size) { + var p = getInstance(nativePtr); + p.ensureCapacity(size); + getInstance(nativePtr).mSize = size; + } + public static void nativeSetDataPosition(long nativePtr, int pos) { + var p = getInstance(nativePtr); + // TODO: Should this change the size or the capacity?? + p.mPos = pos; + } + public static void nativeSetDataCapacity(long nativePtr, int size) { + var p = getInstance(nativePtr); + if (p.getCapacity() < size) { + p.forceSetCapacity(size); + } + } + + public static boolean nativePushAllowFds(long nativePtr, boolean allowFds) { + var p = getInstance(nativePtr); + var prev = p.mAllowFds; + p.mAllowFds = allowFds; + return prev; + } + public static void nativeRestoreAllowFds(long nativePtr, boolean lastValue) { + getInstance(nativePtr).mAllowFds = lastValue; + } + + public static void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len) { + nativeWriteBlob(nativePtr, b, offset, len); + } + + public static void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len) { + var p = getInstance(nativePtr); + + if (b == null) { + nativeWriteInt(nativePtr, -1); + } else { + final var alignedSize = align4(len); + + nativeWriteInt(nativePtr, len); + + p.ensureMoreCapacity(alignedSize); + + System.arraycopy(b, offset, p.mBuffer, p.mPos, len); + p.mPos += alignedSize; + p.updateSize(); + } + } + + public static int nativeWriteInt(long nativePtr, int value) { + var p = getInstance(nativePtr); + p.ensureMoreCapacity(Integer.BYTES); + + p.mBuffer[p.mPos++] = (byte) ((value >> 24) & 0xff); + p.mBuffer[p.mPos++] = (byte) ((value >> 16) & 0xff); + p.mBuffer[p.mPos++] = (byte) ((value >> 8) & 0xff); + p.mBuffer[p.mPos++] = (byte) ((value >> 0) & 0xff); + + p.updateSize(); + + return OK; + } + + public static int nativeWriteLong(long nativePtr, long value) { + nativeWriteInt(nativePtr, (int) (value >>> 32)); + nativeWriteInt(nativePtr, (int) (value)); + return OK; + } + public static int nativeWriteFloat(long nativePtr, float val) { + return nativeWriteInt(nativePtr, Float.floatToIntBits(val)); + } + public static int nativeWriteDouble(long nativePtr, double val) { + return nativeWriteLong(nativePtr, Double.doubleToLongBits(val)); + } + public static void nativeSignalExceptionForError(int error) { + throw new RuntimeException("Not implemented yet"); + } + + private static int align4(int val) { + return ((val + 3) / 4) * 4; + } + + public static void nativeWriteString8(long nativePtr, String val) { + if (val == null) { + nativeWriteBlob(nativePtr, null, 0, 0); + } else { + var bytes = val.getBytes(StandardCharsets.UTF_8); + nativeWriteBlob(nativePtr, bytes, 0, bytes.length); + } + } + public static void nativeWriteString16(long nativePtr, String val) { + // Just reuse String8 + nativeWriteString8(nativePtr, val); + } + public static void nativeWriteStrongBinder(long nativePtr, IBinder val) { + throw new RuntimeException("Not implemented yet"); + } + public static void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val) { + throw new RuntimeException("Not implemented yet"); + } + + public static byte[] nativeCreateByteArray(long nativePtr) { + return nativeReadBlob(nativePtr); + } + + public static boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen) { + if (dest == null) { + return false; + } + var data = nativeReadBlob(nativePtr); + if (data == null) { + System.err.println("Percel has NULL, which is unexpected."); // TODO: Is this correct? + return false; + } + // TODO: Make sure the check logic is correct. + if (data.length != destLen) { + System.err.println("Byte array size mismatch: expected=" + + data.length + " given=" + destLen); + return false; + } + System.arraycopy(data, 0, dest, 0, data.length); + return true; + } + + public static byte[] nativeReadBlob(long nativePtr) { + var p = getInstance(nativePtr); + if (p.mSize - p.mPos < 4) { + // Match native impl that returns "null" when not enough data + return null; + } + final var size = nativeReadInt(nativePtr); + if (size == -1) { + return null; + } + try { + p.ensureDataAvailable(align4(size)); + } catch (Exception e) { + System.err.println(e.toString()); + return null; + } + + var bytes = new byte[size]; + System.arraycopy(p.mBuffer, p.mPos, bytes, 0, size); + + p.mPos += align4(size); + + return bytes; + } + public static int nativeReadInt(long nativePtr) { + var p = getInstance(nativePtr); + + if (p.mSize - p.mPos < 4) { + // Match native impl that returns "0" when not enough data + return 0; + } + + var ret = (((p.mBuffer[p.mPos++] & 0xff) << 24) + | ((p.mBuffer[p.mPos++] & 0xff) << 16) + | ((p.mBuffer[p.mPos++] & 0xff) << 8) + | ((p.mBuffer[p.mPos++] & 0xff) << 0)); + + return ret; + } + public static long nativeReadLong(long nativePtr) { + return (((long) nativeReadInt(nativePtr)) << 32) + | (((long) nativeReadInt(nativePtr)) & 0xffff_ffffL); + } + + public static float nativeReadFloat(long nativePtr) { + return Float.intBitsToFloat(nativeReadInt(nativePtr)); + } + + public static double nativeReadDouble(long nativePtr) { + return Double.longBitsToDouble(nativeReadLong(nativePtr)); + } + + public static String nativeReadString8(long nativePtr) { + final var bytes = nativeReadBlob(nativePtr); + if (bytes == null) { + return null; + } + return new String(bytes, StandardCharsets.UTF_8); + } + public static String nativeReadString16(long nativePtr) { + return nativeReadString8(nativePtr); + } + public static IBinder nativeReadStrongBinder(long nativePtr) { + throw new RuntimeException("Not implemented yet"); + } + public static FileDescriptor nativeReadFileDescriptor(long nativePtr) { + throw new RuntimeException("Not implemented yet"); + } + + public static byte[] nativeMarshall(long nativePtr) { + var p = getInstance(nativePtr); + return Arrays.copyOf(p.mBuffer, p.mSize); + } + public static void nativeUnmarshall( + long nativePtr, byte[] data, int offset, int length) { + var p = getInstance(nativePtr); + p.ensureMoreCapacity(length); + System.arraycopy(data, offset, p.mBuffer, p.mPos, length); + p.mPos += length; + p.updateSize(); + } + public static int nativeCompareData(long thisNativePtr, long otherNativePtr) { + throw new RuntimeException("Not implemented yet"); + } + public static boolean nativeCompareDataInRange( + long ptrA, int offsetA, long ptrB, int offsetB, int length) { + throw new RuntimeException("Not implemented yet"); + } + public static void nativeAppendFrom( + long thisNativePtr, long otherNativePtr, int srcOffset, int length) { + var dst = getInstance(thisNativePtr); + var src = getInstance(otherNativePtr); + + dst.ensureMoreCapacity(length); + + System.arraycopy(src.mBuffer, srcOffset, dst.mBuffer, dst.mPos, length); + dst.mPos += length; // TODO: 4 byte align? + dst.updateSize(); + + // TODO: Update the other's position? + } + + public static boolean nativeHasFileDescriptors(long nativePtr) { + // Assume false for now, because we don't support writing FDs yet. + return false; + } + public static boolean nativeHasFileDescriptorsInRange( + long nativePtr, int offset, int length) { + // Assume false for now, because we don't support writing FDs yet. + return false; + } + public static void nativeWriteInterfaceToken(long nativePtr, String interfaceName) { + throw new RuntimeException("Not implemented yet"); + } + public static void nativeEnforceInterface(long nativePtr, String interfaceName) { + throw new RuntimeException("Not implemented yet"); + } + + public static boolean nativeReplaceCallingWorkSourceUid( + long nativePtr, int workSourceUid) { + throw new RuntimeException("Not implemented yet"); + } + public static int nativeReadCallingWorkSourceUid(long nativePtr) { + throw new RuntimeException("Not implemented yet"); + } + + public static long nativeGetOpenAshmemSize(long nativePtr) { + throw new RuntimeException("Not implemented yet"); + } + public static long getGlobalAllocSize() { + throw new RuntimeException("Not implemented yet"); + } + public static long getGlobalAllocCount() { + throw new RuntimeException("Not implemented yet"); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java new file mode 100644 index 000000000000..1ec1d5f307e1 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.nativesubstitution; + +public class SystemProperties_host { + public static String native_get(String key, String def) { + throw new RuntimeException("Not implemented yet"); + } + public static int native_get_int(String key, int def) { + throw new RuntimeException("Not implemented yet"); + } + public static long native_get_long(String key, long def) { + throw new RuntimeException("Not implemented yet"); + } + public static boolean native_get_boolean(String key, boolean def) { + throw new RuntimeException("Not implemented yet"); + } + + public static long native_find(String name) { + throw new RuntimeException("Not implemented yet"); + } + public static String native_get(long handle) { + throw new RuntimeException("Not implemented yet"); + } + public static int native_get_int(long handle, int def) { + throw new RuntimeException("Not implemented yet"); + } + public static long native_get_long(long handle, long def) { + throw new RuntimeException("Not implemented yet"); + } + public static boolean native_get_boolean(long handle, boolean def) { + throw new RuntimeException("Not implemented yet"); + } + public static void native_set(String key, String def) { + throw new RuntimeException("Not implemented yet"); + } + public static void native_add_change_callback() { + throw new RuntimeException("Not implemented yet"); + } + public static void native_report_sysprop_change() { + throw new RuntimeException("Not implemented yet"); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java new file mode 100644 index 000000000000..fbcc64892798 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.runtimehelper; + +import com.android.hoststubgen.hosthelper.HostTestException; + +import java.io.File; +import java.io.PrintStream; +import java.lang.reflect.Modifier; +import java.util.ArrayList; + +/** + * Standard class loader hook. + * + * Currently, we use this class to load libandroid_runtime (if needed). In the future, we may + * load other JNI or do other set up here. + */ +public class ClassLoadHook { + private static PrintStream sOut = System.out; + + /** + * If true, we won't load `libandroid_runtime` + * + * <p>Looks like there's some complexity in running a host test with JNI with `atest`, + * so we need a way to remove the dependency. + */ + private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv( + "HOSTTEST_SKIP_LOADING_LIBANDROID")); + + public static final String CORE_NATIVE_CLASSES = "core_native_classes"; + public static final String ICU_DATA_PATH = "icu.data.path"; + public static final String KEYBOARD_PATHS = "keyboard_paths"; + public static final String GRAPHICS_NATIVE_CLASSES = "graphics_native_classes"; + + public static final String VALUE_N_A = "**n/a**"; + public static final String LIBANDROID_RUNTIME_NAME = "libandroid_runtime"; + + private static String sInitialDir = new File("").getAbsolutePath(); + + static { + log("Initialized. Current dir=" + sInitialDir); + } + + private ClassLoadHook() { + } + + /** + * Called when classes with + * {@code @HostSideTestClassLoadHook( + * "com.android.hoststubgen.runtimehelper.LibandroidLoadingHook.onClassLoaded") } + * are loaded. + */ + public static void onClassLoaded(Class<?> clazz) { + System.out.println("Framework class loaded: " + clazz.getCanonicalName()); + + loadFrameworkNativeCode(); + } + + private static void log(String message) { + sOut.println("ClassLoadHook: " + message); + } + + private static void log(String fmt, Object... args) { + log(String.format(fmt, args)); + } + + private static void ensurePropertyNotSet(String key) { + if (System.getProperty(key) != null) { + throw new HostTestException("System property \"" + key + "\" is set unexpectedly"); + } + } + + private static void setProperty(String key, String value) { + System.setProperty(key, value); + log("Property set: %s=\"%s\"", key, value); + } + + private static void dumpSystemProperties() { + for (var prop : System.getProperties().entrySet()) { + log(" %s=\"%s\"", prop.getKey(), prop.getValue()); + } + } + + private static void loadJniLibrary(String name) { + final String path = sInitialDir + "/lib64/" + name + ".so"; + System.out.println("Loading " + path + " ..."); + System.load(path); + System.out.println("Done loading " + path); + } + + private static boolean sLoadFrameworkNativeCodeCalled = false; + + /** + * Load `libandroid_runtime` if needed. + */ + private static void loadFrameworkNativeCode() { + // This is called from class-initializers, so no synchronization is needed. + if (sLoadFrameworkNativeCodeCalled) { + // This method has already been called before.s + return; + } + sLoadFrameworkNativeCodeCalled = true; + + // libandroid_runtime uses Java's system properties to decide what JNI methods to set up. + // Set up these properties for host-side tests. + + if ("1".equals(System.getenv("HOSTTEST_DUMP_PROPERTIES"))) { + log("Java system properties:"); + dumpSystemProperties(); + } + + if (SKIP_LOADING_LIBANDROID) { + log("Skip loading " + LIBANDROID_RUNTIME_NAME); + } + + // Make sure these properties are not set. + ensurePropertyNotSet(CORE_NATIVE_CLASSES); + ensurePropertyNotSet(ICU_DATA_PATH); + ensurePropertyNotSet(KEYBOARD_PATHS); + ensurePropertyNotSet(GRAPHICS_NATIVE_CLASSES); + + // Tell libandroid what JNI to use. + final var jniClasses = getCoreNativeClassesToUse(); + if (jniClasses.isEmpty()) { + log("No classes require JNI methods, skip loading " + LIBANDROID_RUNTIME_NAME); + return; + } + setProperty(CORE_NATIVE_CLASSES, jniClasses); + setProperty(GRAPHICS_NATIVE_CLASSES, ""); + setProperty(ICU_DATA_PATH, VALUE_N_A); + setProperty(KEYBOARD_PATHS, VALUE_N_A); + + loadJniLibrary(LIBANDROID_RUNTIME_NAME); + } + + /** + * Classes with native methods that are backed by `libandroid_runtime`. + * + * At runtime, we check if these classes have any methods, and if so, we'll have + * `libandroid_runtime` register the native functions. + */ + private static final Class<?>[] sClassesWithLibandroidNativeMethods = { + android.util.Log.class, + android.os.Parcel.class, + }; + + /** + * @return if a given method is a native method or not. + */ + private static boolean hasNativeMethod(Class<?> clazz) { + for (var method : clazz.getDeclaredMethods()) { + if (Modifier.isNative(method.getModifiers())) { + return true; + } + } + return false; + } + + /** + * Create a list of classes as comma-separated that require JNI methods to be set up. + * + * <p>This list is used by frameworks/base/core/jni/LayoutlibLoader.cpp to decide + * what JNI methods to set up. + */ + private static String getCoreNativeClassesToUse() { + final var coreNativeClassesToLoad = new ArrayList<String>(); + + for (var clazz : sClassesWithLibandroidNativeMethods) { + if (hasNativeMethod(clazz)) { + log("Class %s has native methods", clazz); + coreNativeClassesToLoad.add(clazz.getName()); + } + } + + return String.join(",", coreNativeClassesToLoad); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java new file mode 100644 index 000000000000..7d2b00d9420d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dalvik.system; + +// [ravenwood] It's in libart, so until we get ART to work, we need to use a fake. +// The original is here: +// $ANDROID_BUILD_TOP/libcore/libart/src/main/java/dalvik/system/VMRuntime.java + +import java.lang.reflect.Array; + +public class VMRuntime { + private static final VMRuntime THE_ONE = new VMRuntime(); + + private VMRuntime() { + } + + public static VMRuntime getRuntime() { + return THE_ONE; + } + + public boolean is64Bit() { + return true; + } + + public static boolean is64BitAbi(String abi) { + return true; + } + + public Object newUnpaddedArray(Class<?> componentType, int minLength) { + return Array.newInstance(componentType, minLength); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java new file mode 100644 index 000000000000..a1ae35a88656 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package libcore.util; + +import java.lang.annotation.Annotation; + +// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore. +public class EmptyArray { + private EmptyArray() {} + + public static final boolean[] BOOLEAN = new boolean[0]; + + public static final byte[] BYTE = new byte[0]; + + public static final char[] CHAR = new char[0]; + + public static final double[] DOUBLE = new double[0]; + + public static final float[] FLOAT = new float[0]; + + public static final int[] INT = new int[0]; + + public static final long[] LONG = new long[0]; + + public static final Class<?>[] CLASS = new Class[0]; + + public static final Object[] OBJECT = new Object[0]; + + public static final String[] STRING = new String[0]; + + public static final Throwable[] THROWABLE = new Throwable[0]; + + public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0]; + + public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0]; + + public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE = + new java.lang.reflect.TypeVariable[0]; + public static final Annotation[] ANNOTATION = new Annotation[0]; + +} diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java new file mode 100644 index 000000000000..e142c46bc311 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.util; + +// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore. + +public class SneakyThrow { + + private SneakyThrow() { + } + + public static void sneakyThrow(Throwable t) { + SneakyThrow.<RuntimeException>sneakyThrow_(t); + } + + private static <T extends Throwable> void sneakyThrow_(Throwable t) throws T { + throw (T) t; + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java new file mode 100644 index 000000000000..7ada961d710f --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.hosthelper; + +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation added to all "stub" classes generated by HostStubGen. + */ +@Target({TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface HostStubGenProcessedKeepClass { + String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedKeepClass.class); + String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";"; +} diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java new file mode 100644 index 000000000000..e598da0a3cb9 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.hosthelper; + +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation added to all "stub" classes generated by HostStubGen. + */ +@Target({TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface HostStubGenProcessedStubClass { + String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedStubClass.class); + String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";"; +} diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java new file mode 100644 index 000000000000..c54c2c111229 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.hosthelper; + +public class HostTestException extends RuntimeException { + public HostTestException(String message) { + super(message); + } + + public HostTestException(String message, Throwable inner) { + super(message, inner); + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java new file mode 100644 index 000000000000..29f7be008eef --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.hosthelper; + +import com.google.common.reflect.ClassPath; +import com.google.common.reflect.ClassPath.ClassInfo; + +import junit.framework.JUnit4TestAdapter; +import junit.framework.TestSuite; + +import java.util.regex.Pattern; + +/** + * A very simple Junit {@link TestSuite} builder that finds all classes that look like test classes. + * + * We use it to run ravenwood test jars from the command line. + */ +public class HostTestSuite { + private static final String CLASS_NAME_REGEX_ENV = "HOST_TEST_CLASS_NAME_REGEX"; + + /** + * Called by junit, and return all test-looking classes as a suite. + */ + public static TestSuite suite() { + TestSuite suite = new TestSuite(); + + final Pattern classNamePattern; + final var filterRegex = System.getenv(CLASS_NAME_REGEX_ENV); + if (filterRegex == null) { + classNamePattern = Pattern.compile(""); + } else { + classNamePattern = Pattern.compile(filterRegex); + } + try { + // We use guava to list all classes. + ClassPath cp = ClassPath.from(HostTestSuite.class.getClassLoader()); + + for (var classInfo : cp.getAllClasses()) { + Class<?> clazz = asTestClass(classInfo); + if (clazz != null) { + if (classNamePattern.matcher(clazz.getSimpleName()).find()) { + System.out.println("Test class found " + clazz.getName()); + } else { + System.out.println("Skipping test class (for $" + + CLASS_NAME_REGEX_ENV + "): " + clazz.getName()); + } + suite.addTest(new JUnit4TestAdapter(clazz)); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return suite; + } + + /** + * Decide whether a class looks like a test class or not, and if so, return it as a Class + * instance. + */ + private static Class<?> asTestClass(ClassInfo classInfo) { + try { + final Class<?> clazz = classInfo.load(); + + // Does it extend junit.framework.TestCase? + if (junit.framework.TestCase.class.isAssignableFrom(clazz)) { + // Ignore classes in JUnit itself, or the android(x) test lib. + if (classInfo.getName().startsWith("junit.") + || classInfo.getName().startsWith("org.junit.") + || classInfo.getName().startsWith("android.test.") + || classInfo.getName().startsWith("androidx.test.")) { + return null; // Ignore junit classes. + } + return clazz; + } + // Does it have any "@Test" method? + for (var method : clazz.getMethods()) { + for (var an : method.getAnnotations()) { + if (an.annotationType() == org.junit.Test.class) { + return clazz; + } + } + } + return null; + } catch (java.lang.NoClassDefFoundError e) { + // Ignore unloadable classes. + return null; + } + } +} diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java new file mode 100644 index 000000000000..c770b9ccc800 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.hosthelper; + +import java.io.PrintStream; +import java.lang.StackWalker.Option; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; + +import javax.annotation.concurrent.GuardedBy; + +import org.junit.AssumptionViolatedException; + +/** + * Utilities used in the host side test environment. + */ +public class HostTestUtils { + private HostTestUtils() { + } + + /** + * Same as ASM's Type.getInternalName(). Copied here, to avoid having a reference to ASM + * in this JAR. + */ + public static String getInternalName(final Class<?> clazz) { + return clazz.getName().replace('.', '/'); + } + + public static final String CLASS_INTERNAL_NAME = getInternalName(HostTestUtils.class); + + /** If true, we won't print method call log. */ + private static final boolean SKIP_METHOD_LOG = "1".equals(System.getenv( + "HOSTTEST_SKIP_METHOD_LOG")); + + /** If true, we won't print class load log. */ + private static final boolean SKIP_CLASS_LOG = "1".equals(System.getenv( + "HOSTTEST_SKIP_CLASS_LOG")); + + /** If true, we won't perform non-stub method direct call check. */ + private static final boolean SKIP_NON_STUB_METHOD_CHECK = "1".equals(System.getenv( + "HOSTTEST_SKIP_NON_STUB_METHOD_CHECK")); + + + /** + * Method call log will be printed to it. + */ + public static PrintStream logPrintStream = System.out; + + /** + * Called from methods with FilterPolicy.Throw. + */ + public static void onThrowMethodCalled() { + // TODO: Maybe add call tracking? + throw new RuntimeException("This method is not supported on the host side"); + } + + /** + * Trampoline method for method-call-hook. + */ + public static void callMethodCallHook( + Class<?> methodClass, + String methodName, + String methodDescriptor, + String callbackMethod + ) { + callStaticMethodByName(callbackMethod, "method call hook", methodClass, + methodName, methodDescriptor); + } + + /** + * I can be used as + * {@code --default-method-call-hook + * com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall}. + * + * It logs every single methods called. + */ + public static void logMethodCall( + Class<?> methodClass, + String methodName, + String methodDescriptor + ) { + if (SKIP_METHOD_LOG) { + return; + } + logPrintStream.println("# method called: " + methodClass.getCanonicalName() + "." + + methodName + methodDescriptor); + } + + private static final StackWalker sStackWalker = + StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE); + + /** + * Return a {@link StackWalker} that supports {@link StackWalker#getCallerClass()}. + */ + public static StackWalker getStackWalker() { + return sStackWalker; + } + + /** + * Cache used by {@link #isClassAllowedToCallNonStubMethods}. + */ + @GuardedBy("sAllowedClasses") + private static final HashMap<Class, Boolean> sAllowedClasses = new HashMap(); + + /** + * Return true if a given class is allowed to access non-stub methods -- that is, if the class + * is in the hoststubgen generated JARs. (not in the test jar.) + */ + private static boolean isClassAllowedToCallNonStubMethods(Class<?> clazz) { + synchronized (sAllowedClasses) { + var cached = sAllowedClasses.get(clazz); + if (cached != null) { + return cached; + } + } + // All processed classes have this annotation. + var allowed = clazz.getAnnotation(HostStubGenProcessedKeepClass.class) != null; + + // Java classes should be able to access any methods. (via callbacks, etc.) + if (!allowed) { + if (clazz.getPackageName().startsWith("java.") + || clazz.getPackageName().startsWith("javax.")) { + allowed = true; + } + } + synchronized (sAllowedClasses) { + sAllowedClasses.put(clazz, allowed); + } + return allowed; + } + + /** + * Called when non-stub methods are called. We do a host-unsupported method direct call check + * in here. + */ + public static void onNonStubMethodCalled( + String methodClass, + String methodName, + String methodDescriptor, + Class<?> callerClass) { + if (SKIP_NON_STUB_METHOD_CHECK) { + return; + } + if (isClassAllowedToCallNonStubMethods(callerClass)) { + return; // Generated class is allowed to call framework class. + } + logPrintStream.println("! " + methodClass + "." + methodName + methodDescriptor + + " called by " + callerClass.getCanonicalName()); + } + + /** + * Called when any top level class (not nested classes) in the impl jar is loaded. + * + * When HostStubGen inject a class-load hook, it's always a call to this method, with the + * actual method name as the second argument. + * + * This method discovers the hook method with reflections and call it. + * + * TODO: Add a unit test. + */ + public static void onClassLoaded(Class<?> loadedClass, String callbackMethod) { + logPrintStream.println("! Class loaded: " + loadedClass.getCanonicalName() + + " calling hook " + callbackMethod); + + callStaticMethodByName(callbackMethod, "class load hook", loadedClass); + } + + private static void callStaticMethodByName(String classAndMethodName, + String description, Object... args) { + // Forward the call to callbackMethod. + final int lastPeriod = classAndMethodName.lastIndexOf("."); + + if ((lastPeriod) < 0 || (lastPeriod == classAndMethodName.length() - 1)) { + throw new HostTestException(String.format( + "Unable to find %s: malformed method name \"%s\"", + description, + classAndMethodName)); + } + + final String className = classAndMethodName.substring(0, lastPeriod); + final String methodName = classAndMethodName.substring(lastPeriod + 1); + + Class<?> clazz = null; + try { + clazz = Class.forName(className); + } catch (Exception e) { + throw new HostTestException(String.format( + "Unable to find %s: Class %s not found", + description, + className), e); + } + if (!Modifier.isPublic(clazz.getModifiers())) { + throw new HostTestException(String.format( + "Unable to find %s: Class %s must be public", + description, + className)); + } + + Class<?>[] argTypes = new Class[args.length]; + for (int i = 0; i < args.length; i++) { + argTypes[i] = args[i].getClass(); + } + + Method method = null; + try { + method = clazz.getMethod(methodName, argTypes); + } catch (Exception e) { + throw new HostTestException(String.format( + "Unable to find %s: class %s doesn't have method %s" + + " (method must take exactly one parameter of type Class," + + " and public static)", + description, className, methodName), e); + } + if (!(Modifier.isPublic(method.getModifiers()) + && Modifier.isStatic(method.getModifiers()))) { + throw new HostTestException(String.format( + "Unable to find %s: Method %s in class %s must be public static", + description, methodName, className)); + } + try { + method.invoke(null, args); + } catch (Exception e) { + throw new HostTestException(String.format( + "Unable to invoke %s %s.%s", + description, className, methodName), e); + } + } + + /** + * I can be used as + * {@code --default-class-load-hook + * com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded}. + * + * It logs every loaded class. + */ + public static void logClassLoaded(Class<?> clazz) { + if (SKIP_CLASS_LOG) { + return; + } + logPrintStream.println("# class loaded: " + clazz.getCanonicalName()); + } +} diff --git a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt new file mode 100644 index 000000000000..c371b5d54ebd --- /dev/null +++ b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt @@ -0,0 +1,44 @@ +# File containing standard options to HostStubGen + +--debug + +# Uncomment below lines to enable each feature. +--enable-non-stub-method-check +# --no-non-stub-method-check + +#--default-method-call-hook +# com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall +#--default-class-load-hook +# com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + +# Standard annotations. +# Note, each line is a single argument, so we need newlines after each `--xxx-annotation`. +--stub-annotation + android.hosttest.annotation.HostSideTestStub + +--keep-annotation + android.hosttest.annotation.HostSideTestKeep + +--stub-class-annotation + android.hosttest.annotation.HostSideTestWholeClassStub + +--keep-class-annotation + android.hosttest.annotation.HostSideTestWholeClassKeep + +--throw-annotation + android.hosttest.annotation.HostSideTestThrow + +--remove-annotation + android.hosttest.annotation.HostSideTestRemove + +--substitute-annotation + android.hosttest.annotation.HostSideTestSubstitute + +--native-substitute-annotation + android.hosttest.annotation.HostSideTestNativeSubstitutionClass + +--class-load-hook-annotation + android.hosttest.annotation.HostSideTestClassLoadHook + +--keep-static-initializer-annotation + android.hosttest.annotation.HostSideTestStaticInitializerKeep diff --git a/tools/hoststubgen/hoststubgen/invoketest/Android.bp b/tools/hoststubgen/hoststubgen/invoketest/Android.bp new file mode 100644 index 000000000000..7e90e421a1f9 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/invoketest/Android.bp @@ -0,0 +1,20 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +sh_test_host { + name: "hoststubgen-invoke-test", + src: "hoststubgen-invoke-test.sh", + test_suites: ["general-tests"], + + // Note: java_data: ["hoststubgen"] will only install the jar file, but not the command wrapper. + java_data: [ + "hoststubgen", + "hoststubgen-test-tiny-framework", + ], +} diff --git a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh new file mode 100755 index 000000000000..85038be80c51 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh @@ -0,0 +1,234 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This command is expected to be executed with: atest hoststubgen-invoke-test + +set -e # Exit when any command files + +# This script runs HostStubGen directly with various arguments and make sure +# the tool behaves in the expected way. + + +echo "# Listing files in the test environment" +ls -lR + +echo "# Dumping the environment variables" +env + +# Set up the constants and variables + +# Bazel sets $TEST_TMPDIR. +export TEMP=$TEST_TMPDIR + +if [[ "$TEMP" == "" ]] ; then + TEMP=./tmp + mkdir -p $TEMP +fi + +cleanup_temp() { + rm -fr $TEMP/* +} + +cleanup_temp + +JAR=hoststubgen-test-tiny-framework.jar +STUB=$TEMP/stub.jar +IMPL=$TEMP/impl.jar + +ANNOTATION_FILTER=$TEMP/annotation-filter.txt + +HOSTSTUBGEN_OUT=$TEMP/output.txt + +# Because of `set -e`, we can't return non-zero from functions, so we store +# HostStubGen result in it. +HOSTSTUBGEN_RC=0 + +# Note, because the build rule will only install hoststubgen.jar, but not the wrapper script, +# we need to execute it manually with the java command. +hoststubgen() { + echo "Running hoststubgen with: $*" + java -jar ./hoststubgen.jar "$@" +} + +run_hoststubgen() { + local test_name="$1" + local annotation_filter="$2" + + echo "# Test: $test_name" + + cleanup_temp + + local filter_arg="" + + if [[ "$annotation_filter" != "" ]] ; then + echo "$annotation_filter" > $ANNOTATION_FILTER + filter_arg="--annotation-allowed-classes-file $ANNOTATION_FILTER" + echo "=== filter ===" + cat $ANNOTATION_FILTER + fi + + local stub_arg="" + local impl_arg="" + + if [[ "$STUB" != "" ]] ; then + stub_arg="--out-stub-jar $STUB" + fi + if [[ "$IMPL" != "" ]] ; then + impl_arg="--out-impl-jar $IMPL" + fi + + hoststubgen \ + --debug \ + --in-jar $JAR \ + $stub_arg \ + $impl_arg \ + --stub-annotation \ + android.hosttest.annotation.HostSideTestStub \ + --keep-annotation \ + android.hosttest.annotation.HostSideTestKeep \ + --stub-class-annotation \ + android.hosttest.annotation.HostSideTestWholeClassStub \ + --keep-class-annotation \ + android.hosttest.annotation.HostSideTestWholeClassKeep \ + --throw-annotation \ + android.hosttest.annotation.HostSideTestThrow \ + --remove-annotation \ + android.hosttest.annotation.HostSideTestRemove \ + --substitute-annotation \ + android.hosttest.annotation.HostSideTestSubstitute \ + --native-substitute-annotation \ + android.hosttest.annotation.HostSideTestNativeSubstitutionClass \ + --class-load-hook-annotation \ + android.hosttest.annotation.HostSideTestClassLoadHook \ + --keep-static-initializer-annotation \ + android.hosttest.annotation.HostSideTestStaticInitializerKeep \ + $filter_arg \ + |& tee $HOSTSTUBGEN_OUT + HOSTSTUBGEN_RC=${PIPESTATUS[0]} + echo "HostStubGen exited with $HOSTSTUBGEN_RC" + return 0 +} + +assert_file_generated() { + local file="$1" + if [[ "$file" == "" ]] ; then + if [[ -f "$file" ]] ; then + echo "HostStubGen shouldn't have generated $file" + return 1 + fi + else + if ! [[ -f "$file" ]] ; then + echo "HostStubGen didn't generate $file" + return 1 + fi + fi +} + +run_hoststubgen_for_success() { + run_hoststubgen "$@" + + if (( $HOSTSTUBGEN_RC != 0 )) ; then + echo "HostStubGen expected to finish successfully, but failed with $rc" + return 1 + fi + + assert_file_generated "$STUB" + assert_file_generated "$IMPL" +} + +run_hoststubgen_for_failure() { + local test_name="$1" + local expected_error_message="$2" + shift 2 + + run_hoststubgen "$test_name" "$@" + + if (( $HOSTSTUBGEN_RC == 0 )) ; then + echo "HostStubGen expected to fail, but it didn't fail" + return 1 + fi + + # The output should contain the expected message. (note we se fgrep here.) + grep -Fq "$expected_error_message" $HOSTSTUBGEN_OUT +} + +# Start the tests... + +# Pass "" as a filter to _not_ add `--annotation-allowed-classes-file`. +run_hoststubgen_for_success "No annotation filter" "" + +# Now, we use " ", so we do add `--annotation-allowed-classes-file`. +run_hoststubgen_for_failure "No classes are allowed to have annotations" \ + "not allowed to have Ravenwood annotations" \ + " " + +run_hoststubgen_for_success "All classes allowed (wildcard)" \ + " +* # Allow all classes +" + +run_hoststubgen_for_failure "All classes disallowed (wildcard)" \ + "not allowed to have Ravenwood annotations" \ + " +!* # Disallow all classes +" + +run_hoststubgen_for_failure "Some classes not allowed (1)" \ + "not allowed to have Ravenwood annotations" \ + " +android.hosttest.* +com.android.hoststubgen.* +com.supported.* +" + +run_hoststubgen_for_failure "Some classes not allowed (2)" \ + "not allowed to have Ravenwood annotations" \ + " +android.hosttest.* +com.android.hoststubgen.* +com.unsupported.* +" + +run_hoststubgen_for_success "All classes allowed (package wildcard)" \ + " +android.hosttest.* +com.android.hoststubgen.* +com.supported.* +com.unsupported.* +" + + +run_hoststubgen_for_failure "One specific class disallowed" \ + "TinyFrameworkClassAnnotations is not allowed to have Ravenwood annotations" \ + " +!com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations +* # All other classes allowed +" + +run_hoststubgen_for_success "One specific class disallowed, but it doesn't use annotations" \ + " +!com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy +* # All other classes allowed +" + +STUB="" run_hoststubgen_for_success "No stub generation" "" + +IMPL="" run_hoststubgen_for_success "No impl generation" "" + +STUB="" IMPL="" run_hoststubgen_for_success "No stub, no impl generation" "" + + +echo "All tests passed" +exit 0
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/jarjar-rules.txt b/tools/hoststubgen/hoststubgen/jarjar-rules.txt new file mode 100644 index 000000000000..4e61ba6f67b3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/jarjar-rules.txt @@ -0,0 +1,2 @@ +# Rename guava +rule com.google.common.** com.android.hoststubgen.x.@0
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt new file mode 100644 index 000000000000..207ba52685f8 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen + +/** + * We will not print the stack trace for exceptions implementing it. + */ +interface UserErrorException + +/** + * Exceptions about parsing class files. + */ +class ClassParseException(message: String) : Exception(message) + +/** + * Use it for internal exception that really shouldn't happen. + */ +class HostStubGenInternalException(message: String) : Exception(message) + +/** + * Exceptions about the content in a jar file. + */ +class InvalidJarFileException(message: String) : Exception(message), UserErrorException + +/** + * Exceptions missing classes, fields, methods, etc. + */ +class UnknownApiException(message: String) : Exception(message), UserErrorException + +/** + * Exceptions related to invalid annotations -- e.g. more than one visibility annotation + * on a single API. + */ +class InvalidAnnotationException(message: String) : Exception(message), UserErrorException + diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt new file mode 100644 index 000000000000..3cdddc23b332 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt @@ -0,0 +1,437 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen + +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.filters.AnnotationBasedFilter +import com.android.hoststubgen.filters.ClassWidePolicyPropagatingFilter +import com.android.hoststubgen.filters.ConstantFilter +import com.android.hoststubgen.filters.DefaultHookInjectingFilter +import com.android.hoststubgen.filters.FilterPolicy +import com.android.hoststubgen.filters.ImplicitOutputFilter +import com.android.hoststubgen.filters.KeepAllClassesFilter +import com.android.hoststubgen.filters.OutputFilter +import com.android.hoststubgen.filters.StubIntersectingFilter +import com.android.hoststubgen.filters.createFilterFromTextPolicyFile +import com.android.hoststubgen.filters.printAsTextPolicy +import com.android.hoststubgen.utils.ClassFilter +import com.android.hoststubgen.visitors.BaseAdapter +import com.android.hoststubgen.visitors.PackageRedirectRemapper +import org.objectweb.asm.ClassReader +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.ClassWriter +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.util.CheckClassAdapter +import java.io.BufferedInputStream +import java.io.FileOutputStream +import java.io.InputStream +import java.io.OutputStream +import java.io.PrintWriter +import java.util.zip.ZipEntry +import java.util.zip.ZipFile +import java.util.zip.ZipOutputStream + +/** + * Actual main class. + */ +class HostStubGen(val options: HostStubGenOptions) { + fun run() { + val errors = HostStubGenErrors() + + // Load all classes. + val allClasses = loadClassStructures(options.inJar) + + // Dump the classes, if specified. + options.inputJarDumpFile?.let { + PrintWriter(it).use { pw -> allClasses.dump(pw) } + log.i("Dump file created at $it") + } + + options.inputJarAsKeepAllFile?.let { + PrintWriter(it).use { + pw -> allClasses.forEach { + classNode -> printAsTextPolicy(pw, classNode) + } + } + log.i("Dump file created at $it") + } + + // Build the filters. + val filter = buildFilter(errors, allClasses, options) + + // Transform the jar. + convert( + options.inJar, + options.outStubJar, + options.outImplJar, + filter, + options.enableClassChecker, + allClasses, + errors, + ) + } + + /** + * Load all the classes, without code. + */ + private fun loadClassStructures(inJar: String): ClassNodes { + log.i("Reading class structure from $inJar ...") + val start = System.currentTimeMillis() + + val allClasses = ClassNodes() + + log.withIndent { + ZipFile(inJar).use { inZip -> + val inEntries = inZip.entries() + + while (inEntries.hasMoreElements()) { + val entry = inEntries.nextElement() + + BufferedInputStream(inZip.getInputStream(entry)).use { bis -> + if (entry.name.endsWith(".class")) { + val cr = ClassReader(bis) + val cn = ClassNode() + cr.accept(cn, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG + or ClassReader.SKIP_FRAMES) + if (!allClasses.addClass(cn)) { + log.w("Duplicate class found: ${cn.name}") + } + } else if (entry.name.endsWith(".dex")) { + // Seems like it's an ART jar file. We can't process it. + // It's a fatal error. + throw InvalidJarFileException( + "$inJar is not a desktop jar file. It contains a *.dex file.") + } else { + // Unknown file type. Skip. + while (bis.available() > 0) { + bis.skip((1024 * 1024).toLong()) + } + } + } + } + } + } + if (allClasses.size == 0) { + log.w("$inJar contains no *.class files.") + } + + val end = System.currentTimeMillis() + log.v("Done reading class structure in %.1f second(s).", (end - start) / 1000.0) + return allClasses + } + + /** + * Build the filter, which decides what classes/methods/fields should be put in stub or impl + * jars, and "how". (e.g. with substitution?) + */ + private fun buildFilter( + errors: HostStubGenErrors, + allClasses: ClassNodes, + options: HostStubGenOptions, + ): OutputFilter { + // We build a "chain" of multiple filters here. + // + // The filters are build in from "inside", meaning the first filter created here is + // the last filter used, so it has the least precedence. + // + // So, for example, the "remove" annotation, which is handled by AnnotationBasedFilter, + // can override a class-wide annotation, which is handled by + // ClassWidePolicyPropagatingFilter, and any annotations can be overridden by the + // text-file based filter, which is handled by parseTextFilterPolicyFile. + + // The first filter is for the default policy from the command line options. + var filter: OutputFilter = ConstantFilter(options.defaultPolicy, "default-by-options") + + // Next, we need a filter that resolves "class-wide" policies. + // This is used when a member (methods, fields, nested classes) don't get any polices + // from upper filters. e.g. when a method has no annotations, then this filter will apply + // the class-wide policy, if any. (if not, we'll fall back to the above filter.) + filter = ClassWidePolicyPropagatingFilter(filter) + + // Inject default hooks from options. + filter = DefaultHookInjectingFilter( + options.defaultClassLoadHook, + options.defaultMethodCallHook, + filter + ) + + val annotationAllowedClassesFilter = options.annotationAllowedClassesFile.let { filename -> + if (filename == null) { + ClassFilter.newNullFilter(true) // Allow all classes + } else { + ClassFilter.loadFromFile(filename, false) + } + } + + // Next, Java annotation based filter. + filter = AnnotationBasedFilter( + errors, + allClasses, + options.stubAnnotations, + options.keepAnnotations, + options.stubClassAnnotations, + options.keepClassAnnotations, + options.throwAnnotations, + options.removeAnnotations, + options.substituteAnnotations, + options.nativeSubstituteAnnotations, + options.classLoadHookAnnotations, + options.keepStaticInitializerAnnotations, + annotationAllowedClassesFilter, + filter, + ) + + // Next, "text based" filter, which allows to override polices without touching + // the target code. + options.policyOverrideFile?.let { + filter = createFilterFromTextPolicyFile(it, allClasses, filter) + } + + // If `--intersect-stub-jar` is provided, load from these jar files too. + // We use this to restrict stub APIs to public/system/test APIs, + // by intersecting with a stub jar file created by metalava. + if (options.intersectStubJars.size > 0) { + val intersectingJars = loadIntersectingJars(options.intersectStubJars) + + filter = StubIntersectingFilter(errors, intersectingJars, filter) + } + + // Apply the implicit filter. + filter = ImplicitOutputFilter(errors, allClasses, filter) + + // Optionally keep all classes. + if (options.keepAllClasses) { + filter = KeepAllClassesFilter(filter) + } + + return filter + } + + /** + * Load jar files specified with "--intersect-stub-jar". + */ + private fun loadIntersectingJars(filenames: Set<String>): Map<String, ClassNodes> { + val intersectingJars = mutableMapOf<String, ClassNodes>() + + filenames.forEach { filename -> + intersectingJars[filename] = loadClassStructures(filename) + } + return intersectingJars + } + + /** + * Convert a JAR file into "stub" and "impl" JAR files. + */ + private fun convert( + inJar: String, + outStubJar: String?, + outImplJar: String?, + filter: OutputFilter, + enableChecker: Boolean, + classes: ClassNodes, + errors: HostStubGenErrors, + ) { + log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar) + log.i("Checker is %s", if (enableChecker) "enabled" else "disabled") + + val start = System.currentTimeMillis() + + val packageRedirector = PackageRedirectRemapper(options.packageRedirects) + + log.withIndent { + // Open the input jar file and process each entry. + ZipFile(inJar).use { inZip -> + maybeWithZipOutputStream(outStubJar) { stubOutStream -> + maybeWithZipOutputStream(outImplJar) { implOutStream -> + val inEntries = inZip.entries() + while (inEntries.hasMoreElements()) { + val entry = inEntries.nextElement() + convertSingleEntry(inZip, entry, stubOutStream, implOutStream, + filter, packageRedirector, enableChecker, classes, errors) + } + log.i("Converted all entries.") + } + } + outStubJar?.let { log.i("Created stub: $it") } + outImplJar?.let { log.i("Created impl: $it") } + } + } + val end = System.currentTimeMillis() + log.v("Done transforming the jar in %.1f second(s).", (end - start) / 1000.0) + } + + private fun <T> maybeWithZipOutputStream(filename: String?, block: (ZipOutputStream?) -> T): T { + if (filename == null) { + return block(null) + } + return ZipOutputStream(FileOutputStream(filename)).use(block) + } + + /** + * Convert a single ZIP entry, which may or may not be a class file. + */ + private fun convertSingleEntry( + inZip: ZipFile, + entry: ZipEntry, + stubOutStream: ZipOutputStream?, + implOutStream: ZipOutputStream?, + filter: OutputFilter, + packageRedirector: PackageRedirectRemapper, + enableChecker: Boolean, + classes: ClassNodes, + errors: HostStubGenErrors, + ) { + log.d("Entry: %s", entry.name) + log.withIndent { + val name = entry.name + + // Just ignore all the directories. (TODO: make sure it's okay) + if (name.endsWith("/")) { + return + } + + // If it's a class, convert it. + if (name.endsWith(".class")) { + processSingleClass(inZip, entry, stubOutStream, implOutStream, filter, + packageRedirector, enableChecker, classes, errors) + return + } + + // Handle other file types... + + // - *.uau seems to contain hidden API information. + // - *_compat_config.xml is also about compat-framework. + if (name.endsWith(".uau") || + name.endsWith("_compat_config.xml")) { + log.d("Not needed: %s", entry.name) + return + } + + // Unknown type, we just copy it to both output zip files. + // TODO: We probably shouldn't do it for stub jar? + log.v("Copying: %s", entry.name) + stubOutStream?.let { copyZipEntry(inZip, entry, it) } + implOutStream?.let { copyZipEntry(inZip, entry, it) } + } + } + + /** + * Copy a single ZIP entry to the output. + */ + private fun copyZipEntry( + inZip: ZipFile, + entry: ZipEntry, + out: ZipOutputStream, + ) { + BufferedInputStream(inZip.getInputStream(entry)).use { bis -> + // Copy unknown entries as is to the impl out. (but not to the stub out.) + val outEntry = ZipEntry(entry.name) + out.putNextEntry(outEntry) + while (bis.available() > 0) { + out.write(bis.read()) + } + out.closeEntry() + } + } + + /** + * Convert a single class to "stub" and "impl". + */ + private fun processSingleClass( + inZip: ZipFile, + entry: ZipEntry, + stubOutStream: ZipOutputStream?, + implOutStream: ZipOutputStream?, + filter: OutputFilter, + packageRedirector: PackageRedirectRemapper, + enableChecker: Boolean, + classes: ClassNodes, + errors: HostStubGenErrors, + ) { + val classInternalName = entry.name.replaceFirst("\\.class$".toRegex(), "") + val classPolicy = filter.getPolicyForClass(classInternalName) + if (classPolicy.policy == FilterPolicy.Remove) { + log.d("Removing class: %s %s", classInternalName, classPolicy) + return + } + // Generate stub first. + if (stubOutStream != null && classPolicy.policy.needsInStub) { + log.v("Creating stub class: %s Policy: %s", classInternalName, classPolicy) + log.withIndent { + BufferedInputStream(inZip.getInputStream(entry)).use { bis -> + val newEntry = ZipEntry(entry.name) + stubOutStream.putNextEntry(newEntry) + convertClass(classInternalName, /*forImpl=*/false, bis, + stubOutStream, filter, packageRedirector, enableChecker, classes, + errors) + stubOutStream.closeEntry() + } + } + } + if (implOutStream != null && classPolicy.policy.needsInImpl) { + log.v("Creating impl class: %s Policy: %s", classInternalName, classPolicy) + log.withIndent { + BufferedInputStream(inZip.getInputStream(entry)).use { bis -> + val newEntry = ZipEntry(entry.name) + implOutStream.putNextEntry(newEntry) + convertClass(classInternalName, /*forImpl=*/true, bis, + implOutStream, filter, packageRedirector, enableChecker, classes, + errors) + implOutStream.closeEntry() + } + } + } + } + + /** + * Convert a single class to either "stub" or "impl". + */ + private fun convertClass( + classInternalName: String, + forImpl: Boolean, + input: InputStream, + out: OutputStream, + filter: OutputFilter, + packageRedirector: PackageRedirectRemapper, + enableChecker: Boolean, + classes: ClassNodes, + errors: HostStubGenErrors, + ) { + val cr = ClassReader(input) + + // COMPUTE_FRAMES wouldn't be happy if code uses + val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES + val cw = ClassWriter(flags) + + // Connect to the class writer + var outVisitor: ClassVisitor = cw + if (enableChecker) { + outVisitor = CheckClassAdapter(outVisitor) + } + val visitorOptions = BaseAdapter.Options( + enablePreTrace = options.enablePreTrace, + enablePostTrace = options.enablePostTrace, + enableNonStubMethodCallDetection = options.enableNonStubMethodCallDetection, + errors = errors, + ) + outVisitor = BaseAdapter.getVisitor(classInternalName, classes, outVisitor, filter, + packageRedirector, forImpl, visitorOptions) + + cr.accept(outVisitor, ClassReader.EXPAND_FRAMES) + val data = cw.toByteArray() + out.write(data) + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt new file mode 100644 index 000000000000..9df04892ddbd --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen + +class HostStubGenErrors { + fun onErrorFound(message: String) { + // For now, we just throw as soon as any error is found, but eventually we should keep + // all errors and print them at the end. + throw RuntimeException(message) + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt new file mode 100644 index 000000000000..5e71a3690700 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen + +import java.io.OutputStream +import java.io.PrintStream + +val log: HostStubGenLogger = HostStubGenLogger() + +/** Logging level */ +enum class LogLevel { + None, + Error, + Warn, + Info, + Verbose, + Debug, +} + +/** Simple logging class. */ +class HostStubGenLogger( + private var out: PrintStream = System.out!!, + var level: LogLevel = LogLevel.Info, +) { + companion object { + private val sNullPrintStream: PrintStream = PrintStream(OutputStream.nullOutputStream()) + } + + private var indentLevel: Int = 0 + get() = field + set(value) { + field = value + indent = " ".repeat(value) + } + private var indent: String = "" + + fun indent() { + indentLevel++ + } + + fun unindent() { + if (indentLevel <= 0) { + throw IllegalStateException("Unbalanced unindent() call.") + } + indentLevel-- + } + + inline fun <T> withIndent(block: () -> T): T { + try { + indent() + return block() + } finally { + unindent() + } + } + + fun isEnabled(level: LogLevel): Boolean { + return level.ordinal <= this.level.ordinal + } + + private fun println(message: String) { + out.print(indent) + out.println(message) + } + + /** Log an error. */ + fun e(message: String) { + if (level.ordinal < LogLevel.Error.ordinal) { + return + } + println(message) + } + + /** Log an error. */ + fun e(format: String, vararg args: Any?) { + if (level.ordinal < LogLevel.Error.ordinal) { + return + } + e(String.format(format, *args)) + } + + /** Log a warning. */ + fun w(message: String) { + if (level.ordinal < LogLevel.Warn.ordinal) { + return + } + println(message) + } + + /** Log a warning. */ + fun w(format: String, vararg args: Any?) { + if (level.ordinal < LogLevel.Warn.ordinal) { + return + } + w(String.format(format, *args)) + } + + /** Log an info message. */ + fun i(message: String) { + if (level.ordinal < LogLevel.Info.ordinal) { + return + } + println(message) + } + + /** Log a debug message. */ + fun i(format: String, vararg args: Any?) { + if (level.ordinal < LogLevel.Warn.ordinal) { + return + } + i(String.format(format, *args)) + } + + /** Log a verbose message. */ + fun v(message: String) { + if (level.ordinal < LogLevel.Verbose.ordinal) { + return + } + println(message) + } + + /** Log a verbose message. */ + fun v(format: String, vararg args: Any?) { + if (level.ordinal < LogLevel.Verbose.ordinal) { + return + } + v(String.format(format, *args)) + } + + /** Log a debug message. */ + fun d(message: String) { + if (level.ordinal < LogLevel.Debug.ordinal) { + return + } + println(message) + } + + /** Log a debug message. */ + fun d(format: String, vararg args: Any?) { + if (level.ordinal < LogLevel.Warn.ordinal) { + return + } + d(String.format(format, *args)) + } + + inline fun forVerbose(block: () -> Unit) { + if (isEnabled(LogLevel.Verbose)) { + block() + } + } + + inline fun forDebug(block: () -> Unit) { + if (isEnabled(LogLevel.Debug)) { + block() + } + } + + /** Return a stream for error. */ + fun getErrorPrintStream(): PrintStream { + if (level.ordinal < LogLevel.Error.ordinal) { + return sNullPrintStream + } + + // TODO Apply indent + return PrintStream(out) + } + + /** Return a stream for verbose messages. */ + fun getVerbosePrintStream(): PrintStream { + if (level.ordinal < LogLevel.Verbose.ordinal) { + return sNullPrintStream + } + // TODO Apply indent + return PrintStream(out) + } + + /** Return a stream for debug messages. */ + fun getInfoPrintStream(): PrintStream { + if (level.ordinal < LogLevel.Info.ordinal) { + return sNullPrintStream + } + // TODO Apply indent + return PrintStream(out) + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt new file mode 100644 index 000000000000..83f873d38f1b --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen + +import com.android.hoststubgen.filters.FilterPolicy +import java.io.BufferedReader +import java.io.File +import java.io.FileReader + +/** + * Options that can be set from command line arguments. + */ +class HostStubGenOptions( + /** Input jar file*/ + var inJar: String = "", + + /** Output stub jar file */ + var outStubJar: String? = null, + + /** Output implementation jar file */ + var outImplJar: String? = null, + + var inputJarDumpFile: String? = null, + + var inputJarAsKeepAllFile: String? = null, + + var stubAnnotations: MutableSet<String> = mutableSetOf(), + var keepAnnotations: MutableSet<String> = mutableSetOf(), + var throwAnnotations: MutableSet<String> = mutableSetOf(), + var removeAnnotations: MutableSet<String> = mutableSetOf(), + var stubClassAnnotations: MutableSet<String> = mutableSetOf(), + var keepClassAnnotations: MutableSet<String> = mutableSetOf(), + + var substituteAnnotations: MutableSet<String> = mutableSetOf(), + var nativeSubstituteAnnotations: MutableSet<String> = mutableSetOf(), + var classLoadHookAnnotations: MutableSet<String> = mutableSetOf(), + var keepStaticInitializerAnnotations: MutableSet<String> = mutableSetOf(), + + var packageRedirects: MutableList<Pair<String, String>> = mutableListOf(), + + var annotationAllowedClassesFile: String? = null, + + var defaultClassLoadHook: String? = null, + var defaultMethodCallHook: String? = null, + + var intersectStubJars: MutableSet<String> = mutableSetOf(), + + var policyOverrideFile: String? = null, + + var defaultPolicy: FilterPolicy = FilterPolicy.Remove, + var keepAllClasses: Boolean = false, + + var logLevel: LogLevel = LogLevel.Info, + + var cleanUpOnError: Boolean = false, + + var enableClassChecker: Boolean = false, + var enablePreTrace: Boolean = false, + var enablePostTrace: Boolean = false, + + var enableNonStubMethodCallDetection: Boolean = false, +) { + companion object { + + private fun String.ensureFileExists(): String { + if (!File(this).exists()) { + throw InputFileNotFoundException(this) + } + return this + } + + private fun parsePackageRedirect(fromColonTo: String): Pair<String, String> { + val colon = fromColonTo.indexOf(':') + if ((colon < 1) || (colon + 1 >= fromColonTo.length)) { + throw ArgumentsException("--package-redirect must be a colon-separated string") + } + // TODO check for duplicates + return Pair(fromColonTo.substring(0, colon), fromColonTo.substring(colon + 1)) + } + + fun parseArgs(args: Array<String>): HostStubGenOptions { + val ret = HostStubGenOptions() + + val ai = ArgIterator(expandAtFiles(args)) + + var allAnnotations = mutableSetOf<String>() + + fun ensureUniqueAnnotation(name: String): String { + if (!allAnnotations.add(name)) { + throw DuplicateAnnotationException(ai.current) + } + return name + } + + while (true) { + val arg = ai.nextArgOptional() + if (arg == null) { + break + } + + when (arg) { + // TODO: Write help + "-h", "--h" -> TODO("Help is not implemented yet") + + "-v", "--verbose" -> ret.logLevel = LogLevel.Verbose + "-d", "--debug" -> ret.logLevel = LogLevel.Debug + "-q", "--quiet" -> ret.logLevel = LogLevel.None + + "--in-jar" -> ret.inJar = ai.nextArgRequired(arg).ensureFileExists() + "--out-stub-jar" -> ret.outStubJar = ai.nextArgRequired(arg) + "--out-impl-jar" -> ret.outImplJar = ai.nextArgRequired(arg) + + "--policy-override-file" -> + ret.policyOverrideFile = ai.nextArgRequired(arg).ensureFileExists() + + "--clean-up-on-error" -> ret.cleanUpOnError = true + "--no-clean-up-on-error" -> ret.cleanUpOnError = false + + "--default-remove" -> ret.defaultPolicy = FilterPolicy.Remove + "--default-throw" -> ret.defaultPolicy = FilterPolicy.Throw + "--default-keep" -> ret.defaultPolicy = FilterPolicy.Keep + "--default-stub" -> ret.defaultPolicy = FilterPolicy.Stub + + "--keep-all-classes" -> ret.keepAllClasses = true + "--no-keep-all-classes" -> ret.keepAllClasses = false + + "--stub-annotation" -> + ret.stubAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--keep-annotation" -> + ret.keepAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--stub-class-annotation" -> + ret.stubClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--keep-class-annotation" -> + ret.keepClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--throw-annotation" -> + ret.throwAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--remove-annotation" -> + ret.removeAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--substitute-annotation" -> + ret.substituteAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--native-substitute-annotation" -> + ret.nativeSubstituteAnnotations += + ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--class-load-hook-annotation" -> + ret.classLoadHookAnnotations += + ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--keep-static-initializer-annotation" -> + ret.keepStaticInitializerAnnotations += + ensureUniqueAnnotation(ai.nextArgRequired(arg)) + + "--package-redirect" -> + ret.packageRedirects += parsePackageRedirect(ai.nextArgRequired(arg)) + + "--annotation-allowed-classes-file" -> + ret.annotationAllowedClassesFile = ai.nextArgRequired(arg) + + "--default-class-load-hook" -> + ret.defaultClassLoadHook = ai.nextArgRequired(arg) + + "--default-method-call-hook" -> + ret.defaultMethodCallHook = ai.nextArgRequired(arg) + + "--intersect-stub-jar" -> + ret.intersectStubJars += ai.nextArgRequired(arg).ensureFileExists() + + "--gen-keep-all-file" -> + ret.inputJarAsKeepAllFile = ai.nextArgRequired(arg) + + // Following options are for debugging. + "--enable-class-checker" -> ret.enableClassChecker = true + "--no-class-checker" -> ret.enableClassChecker = false + + "--enable-pre-trace" -> ret.enablePreTrace = true + "--no-pre-trace" -> ret.enablePreTrace = false + + "--enable-post-trace" -> ret.enablePostTrace = true + "--no-post-trace" -> ret.enablePostTrace = false + + "--enable-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = true + "--no-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = false + + "--gen-input-dump-file" -> ret.inputJarDumpFile = ai.nextArgRequired(arg) + + else -> throw ArgumentsException("Unknown option: $arg") + } + } + if (ret.inJar.isEmpty()) { + throw ArgumentsException("Required option missing: --in-jar") + } + if (ret.outStubJar == null && ret.outImplJar == null) { + log.w("Neither --out-stub-jar nor --out-impl-jar is set." + + " $COMMAND_NAME will not generate jar files.") + } + + if (ret.enableNonStubMethodCallDetection) { + log.w("--enable-non-stub-method-check is not fully implemented yet." + + " See the todo in doesMethodNeedNonStubCallCheck().") + } + + return ret + } + + /** + * Scan the arguments, and if any of them starts with an `@`, then load from the file + * and use its content as arguments. + * + * In this file, each line is treated as a single argument. + * + * The file can contain '#' as comments. + */ + private fun expandAtFiles(args: Array<String>): List<String> { + val ret = mutableListOf<String>() + + args.forEach { arg -> + if (!arg.startsWith('@')) { + ret += arg + return@forEach + } + // Read from the file, and add each line to the result. + val filename = arg.substring(1).ensureFileExists() + + log.v("Expanding options file $filename") + + BufferedReader(FileReader(filename)).use { reader -> + while (true) { + var line = reader.readLine() + if (line == null) { + break // EOF + } + + line = normalizeTextLine(line) + if (line.isNotEmpty()) { + ret += line + } + } + } + } + return ret + } + } + + open class ArgumentsException(message: String?) : Exception(message), UserErrorException + + /** Thrown when the same annotation is used with different annotation arguments. */ + class DuplicateAnnotationException(annotationName: String?) : + ArgumentsException("Duplicate annotation specified: '$annotationName'") + + /** Thrown when an input file does not exist. */ + class InputFileNotFoundException(filename: String) : + ArgumentsException("File '$filename' not found") + + private class ArgIterator( + private val args: List<String>, + private var currentIndex: Int = -1 + ) { + val current: String + get() = args.get(currentIndex) + + /** + * Get the next argument, or [null] if there's no more arguments. + */ + fun nextArgOptional(): String? { + if ((currentIndex + 1) >= args.size) { + return null + } + return args.get(++currentIndex) + } + + /** + * Get the next argument, or throw if + */ + fun nextArgRequired(argName: String): String { + nextArgOptional().let { + if (it == null) { + throw ArgumentsException("Missing parameter for option $argName") + } + if (it.isEmpty()) { + throw ArgumentsException("Parameter can't be empty for option $argName") + } + return it + } + } + } + + override fun toString(): String { + return """ + HostStubGenOptions{ + inJar='$inJar', + outStubJar='$outStubJar', + outImplJar='$outImplJar', + inputJarDumpFile=$inputJarDumpFile, + inputJarAsKeepAllFile=$inputJarAsKeepAllFile, + stubAnnotations=$stubAnnotations, + keepAnnotations=$keepAnnotations, + throwAnnotations=$throwAnnotations, + removeAnnotations=$removeAnnotations, + stubClassAnnotations=$stubClassAnnotations, + keepClassAnnotations=$keepClassAnnotations, + substituteAnnotations=$substituteAnnotations, + nativeSubstituteAnnotations=$nativeSubstituteAnnotations, + classLoadHookAnnotations=$classLoadHookAnnotations, + keepStaticInitializerAnnotations=$keepStaticInitializerAnnotations, + packageRedirects=$packageRedirects, + $annotationAllowedClassesFile=$annotationAllowedClassesFile, + defaultClassLoadHook=$defaultClassLoadHook, + defaultMethodCallHook=$defaultMethodCallHook, + intersectStubJars=$intersectStubJars, + policyOverrideFile=$policyOverrideFile, + defaultPolicy=$defaultPolicy, + keepAllClasses=$keepAllClasses, + logLevel=$logLevel, + cleanUpOnError=$cleanUpOnError, + enableClassChecker=$enableClassChecker, + enablePreTrace=$enablePreTrace, + enablePostTrace=$enablePostTrace, + enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection, + } + """.trimIndent() + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt new file mode 100644 index 000000000000..0321d9db03ed --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@file:JvmName("Main") + +package com.android.hoststubgen + +const val COMMAND_NAME = "HostStubGen" + +/** + * Entry point. + */ +fun main(args: Array<String>) { + var success = false + var clanupOnError = false + try { + // Parse the command line arguments. + val options = HostStubGenOptions.parseArgs(args) + clanupOnError = options.cleanUpOnError + + log.level = options.logLevel + + log.v("HostStubGen started") + log.v("Options: $options") + + // Run. + HostStubGen(options).run() + + success = true + } catch (e: Exception) { + log.e("$COMMAND_NAME: Error: ${e.message}") + if (e !is UserErrorException) { + e.printStackTrace(log.getErrorPrintStream()) + } + if (clanupOnError) { + TODO("clanupOnError is not implemented yet") + } + } + + log.v("HostStubGen finished") + + System.exit(if (success) 0 else 1 ) +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt new file mode 100644 index 000000000000..937e56c2cbb5 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen + +/** + * A regex that maches whitespate. + */ +val whitespaceRegex = """\s+""".toRegex() + +/** + * Remove the comment ('#' and following) and surrounding whitespace from a line. + */ +fun normalizeTextLine(s: String): String { + // Remove # and after. (comment) + val pos = s.indexOf('#') + val uncommented = if (pos < 0) s else s.substring(0, pos) + + // Remove surrounding whitespace. + return uncommented.trim() +} + +/** + * Concatenate list [a] and [b] and return it. As an optimization, it returns an input + * [List] as-is if the other [List] is empty, so do not modify input [List]'s. + */ +fun <T> addLists(a: List<T>, b: List<T>): List<T> { + if (a.isEmpty()) { + return b + } + if (b.isEmpty()) { + return a + } + return a + b +} + +/** + * Add element [b] to list [a] if [b] is not null. Otherwise, just return [a]. + * (because the method may return [a] as-is, do not modify it after passing it.) + */ +fun <T> addNonNullElement(a: List<T>, b: T?): List<T> { + if (b == null) { + return a + } + if (a.isEmpty()) { + return listOf(b) + } + return a + b +} + + +/** + * Exception for a parse error in a file + */ +class ParseException : Exception, UserErrorException { + val hasSourceInfo: Boolean + + constructor(message: String) : super(message) { + hasSourceInfo = false + } + + constructor(message: String, file: String, line: Int) : + super("$message in file $file line $line") { + hasSourceInfo = true + } + + fun withSourceInfo(filename: String, lineNo: Int): ParseException { + if (hasSourceInfo) { + return this // Already has source information. + } else { + return ParseException(this.message ?: "", filename, lineNo) + } + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt new file mode 100644 index 000000000000..d7aa0af13ce2 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.asm + +import com.android.hoststubgen.ClassParseException +import com.android.hoststubgen.HostStubGenInternalException +import org.objectweb.asm.MethodVisitor +import org.objectweb.asm.Opcodes +import org.objectweb.asm.Type +import org.objectweb.asm.tree.AnnotationNode +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.FieldNode +import org.objectweb.asm.tree.MethodNode + + +/** Name of the class initializer method. */ +val CLASS_INITIALIZER_NAME = "<clinit>" + +/** Descriptor of the class initializer method. */ +val CLASS_INITIALIZER_DESC = "()V" + +/** + * Find any of [anyAnnotations] from the list of visible / invisible annotations. + */ +fun findAnyAnnotation( + anyAnnotations: Set<String>, + visibleAnnotations: List<AnnotationNode>?, + invisibleAnnotations: List<AnnotationNode>?, + ): AnnotationNode? { + for (an in visibleAnnotations ?: emptyList()) { + if (anyAnnotations.contains(an.desc)) { + return an + } + } + for (an in invisibleAnnotations ?: emptyList()) { + if (anyAnnotations.contains(an.desc)) { + return an + } + } + return null +} + +fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? { + for (i in 0..(an.values?.size ?: 0) - 2 step 2) { + val name = an.values[i] + + if (name != propertyName) { + continue + } + val value = an.values[i + 1] + if (value is String) { + return value + } + throw ClassParseException( + "The type of '$name' in annotation \"${an.desc}\" must be String" + + ", but is ${value?.javaClass?.canonicalName}") + } + return null +} + +private val removeLastElement = """[./][^./]*$""".toRegex() + +fun getPackageNameFromClassName(className: String): String { + return className.replace(removeLastElement, "") +} + +fun resolveClassName(className: String, packageName: String): String { + if (className.contains('.') || className.contains('/')) { + return className + } + return "$packageName.$className" +} + +fun String.toJvmClassName(): String { + return this.replace('.', '/') +} + +fun String.toHumanReadableClassName(): String { + return this.replace('/', '.') +} + +fun String.toHumanReadableMethodName(): String { + return this.replace('/', '.') +} + +private val numericalInnerClassName = """.*\$\d+$""".toRegex() + +fun isAnonymousInnerClass(cn: ClassNode): Boolean { + // TODO: Is there a better way? + return cn.name.matches(numericalInnerClassName) +} + +/** + * Take a class name. If it's a nested class, then return the name of its direct outer class name. + * Otherwise, return null. + */ +fun getDirectOuterClassName(className: String): String? { + val pos = className.indexOf('$') + if (pos < 0) { + return null + } + return className.substring(0, pos) +} + +/** + * Write bytecode to push all the method arguments to the stack. + * The number of arguments and their type are taken from [methodDescriptor]. + */ +fun writeByteCodeToPushArguments( + methodDescriptor: String, + writer: MethodVisitor, + argOffset: Int = 0, + ) { + var i = argOffset - 1 + Type.getArgumentTypes(methodDescriptor).forEach { type -> + i++ + + // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions + + // Note, long and double will consume two local variable spaces, so the extra `i++`. + when (type) { + Type.VOID_TYPE -> throw HostStubGenInternalException("VOID_TYPE not expected") + Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE + -> writer.visitVarInsn(Opcodes.ILOAD, i) + Type.LONG_TYPE -> writer.visitVarInsn(Opcodes.LLOAD, i++) + Type.FLOAT_TYPE -> writer.visitVarInsn(Opcodes.FLOAD, i) + Type.DOUBLE_TYPE -> writer.visitVarInsn(Opcodes.DLOAD, i++) + else -> writer.visitVarInsn(Opcodes.ALOAD, i) + } + } +} + +/** + * Write bytecode to "RETURN" that matches the method's return type, according to + * [methodDescriptor]. + */ +fun writeByteCodeToReturn(methodDescriptor: String, writer: MethodVisitor) { + Type.getReturnType(methodDescriptor).let { type -> + // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions + when (type) { + Type.VOID_TYPE -> writer.visitInsn(Opcodes.RETURN) + Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE + -> writer.visitInsn(Opcodes.IRETURN) + Type.LONG_TYPE -> writer.visitInsn(Opcodes.LRETURN) + Type.FLOAT_TYPE -> writer.visitInsn(Opcodes.FRETURN) + Type.DOUBLE_TYPE -> writer.visitInsn(Opcodes.DRETURN) + else -> writer.visitInsn(Opcodes.ARETURN) + } + } +} + +/** + * Given a method descriptor, insert an [argType] as the first argument to it. + */ +fun prependArgTypeToMethodDescriptor(methodDescriptor: String, argType: Type): String { + val returnType = Type.getReturnType(methodDescriptor) + val argTypes = Type.getArgumentTypes(methodDescriptor).toMutableList() + + argTypes.add(0, argType) + + return Type.getMethodDescriptor(returnType, *argTypes.toTypedArray()) +} + +/** + * Return the "visibility" modifier from an `access` integer. + * + * (see https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1) + */ +fun getVisibilityModifier(access: Int): Int { + return access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED) +} + +/** + * Return true if an `access` integer is "private" or "package private". + */ +fun isVisibilityPrivateOrPackagePrivate(access: Int): Boolean { + return when (getVisibilityModifier(access)) { + 0 -> true // Package private. + Opcodes.ACC_PRIVATE -> true + else -> false + } +} + +fun ClassNode.isEnum(): Boolean { + return (this.access and Opcodes.ACC_ENUM) != 0 +} + +fun ClassNode.isAnnotation(): Boolean { + return (this.access and Opcodes.ACC_ANNOTATION) != 0 +} + +fun ClassNode.isSynthetic(): Boolean { + return (this.access and Opcodes.ACC_SYNTHETIC) != 0 +} + +fun MethodNode.isSynthetic(): Boolean { + return (this.access and Opcodes.ACC_SYNTHETIC) != 0 +} + +fun FieldNode.isEnum(): Boolean { + return (this.access and Opcodes.ACC_ENUM) != 0 +} + +fun FieldNode.isSynthetic(): Boolean { + return (this.access and Opcodes.ACC_SYNTHETIC) != 0 +} + +/* + +Dump of the members of TinyFrameworkEnumSimple: + +class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple keep + field Cat keep (ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM) + field Dog keep + field $VALUES keep (ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC) + + method values ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; keep + ^- NOT synthetic (ACC_PUBLIC, ACC_STATIC) + method valueOf (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; keep + ^- NOT synthetic (ACC_PUBLIC, ACC_STATIC) + method <init> (Ljava/lang/String;I)V keep + ^- NOT synthetic (ACC_PRIVATE) + + method $values ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; keep + (ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC) + method <clinit> ()V keep + +Dump of the members of TinyFrameworkEnumSimple: + +class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex keep + field RED keep + field BLUE keep + field GREEN keep + field mLongName keep + field mShortName keep + field $VALUES keep + method values ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; keep + method valueOf (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; keep + method <init> (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V keep + method getLongName ()Ljava/lang/String; keep + method getShortName ()Ljava/lang/String; keep + method $values ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; keep + method <clinit> ()V keep + + */ + +fun isAutoGeneratedEnumMember(mn: MethodNode): Boolean { + if (mn.isSynthetic()) { + return true + } + if (mn.name == "<init>" && mn.desc == "(Ljava/lang/String;I)V") { + return true + } + if (mn.name == "<clinit>" && mn.desc == "()V") { + return true + } + if (mn.name == "values" && mn.desc.startsWith("()")) { + return true + } + if (mn.name == "valueOf" && mn.desc.startsWith("(Ljava/lang/String;)")) { + return true + } + + return false +} + +fun isAutoGeneratedEnumMember(fn: FieldNode): Boolean { + if (fn.isSynthetic() || fn.isEnum()) { + return true + } + return false +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt new file mode 100644 index 000000000000..4df0bfc4a8d1 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt @@ -0,0 +1,149 @@ +package com.android.hoststubgen.asm + +import com.android.hoststubgen.ClassParseException +import org.objectweb.asm.tree.AnnotationNode +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.FieldNode +import org.objectweb.asm.tree.MethodNode +import org.objectweb.asm.tree.TypeAnnotationNode +import java.io.PrintWriter +import java.util.Arrays + +/** + * Stores all classes loaded from a jar file, in a form of [ClassNode] + */ +class ClassNodes { + val mAllClasses: MutableMap<String, ClassNode> = HashMap() + + /** + * Total number of classes registered. + */ + val size: Int + get() = mAllClasses.size + + /** Add a [ClassNode] */ + fun addClass(cn: ClassNode): Boolean { + if (mAllClasses.containsKey(cn.name)) { + return false + } + mAllClasses[cn.name.toJvmClassName()] = cn + return true + } + + /** Get a class's [ClassNodes] (which may not exist) */ + fun findClass(name: String): ClassNode? { + return mAllClasses[name.toJvmClassName()] + } + + /** Get a class's [ClassNodes] (which must exists) */ + fun getClass(name: String): ClassNode { + return findClass(name) ?: throw ClassParseException("Class $name not found") + } + + /** Find a field, which may not exist. */ + fun findField( + className: String, + fieldName: String, + ): FieldNode? { + return findClass(className)?.fields?.firstOrNull { it.name == fieldName }?.let { fn -> + return fn + } + } + + /** Find a method, which may not exist. */ + fun findMethod( + className: String, + methodName: String, + descriptor: String, + ): MethodNode? { + return findClass(className)?.methods + ?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn -> + return mn + } + } + + /** @return true if a class has a class initializer. */ + fun hasClassInitializer(className: String): Boolean { + return findMethod(className, CLASS_INITIALIZER_NAME, CLASS_INITIALIZER_DESC) != null + } + + /** Run the lambda on each class in alphabetical order. */ + fun forEach(consumer: (classNode: ClassNode) -> Unit) { + val keys = mAllClasses.keys.toTypedArray() + Arrays.sort(keys) + + for (name in keys) { + consumer(mAllClasses[name]!!) + } + } + + /** + * Dump all classes. + */ + fun dump(pw: PrintWriter) { + forEach { classNode -> dumpClass(pw, classNode) } + } + + private fun dumpClass(pw: PrintWriter, cn: ClassNode) { + pw.printf("Class: %s [access: %x]\n", cn.name, cn.access) + dumpAnnotations(pw, " ", + cn.visibleTypeAnnotations, cn.invisibleTypeAnnotations, + cn.visibleAnnotations, cn.invisibleAnnotations, + ) + + for (f in cn.fields ?: emptyList()) { + pw.printf(" Field: %s [sig: %s] [desc: %s] [access: %x]\n", + f.name, f.signature, f.desc, f.access) + dumpAnnotations(pw, " ", + f.visibleTypeAnnotations, f.invisibleTypeAnnotations, + f.visibleAnnotations, f.invisibleAnnotations, + ) + } + for (m in cn.methods ?: emptyList()) { + pw.printf(" Method: %s [sig: %s] [desc: %s] [access: %x]\n", + m.name, m.signature, m.desc, m.access) + dumpAnnotations(pw, " ", + m.visibleTypeAnnotations, m.invisibleTypeAnnotations, + m.visibleAnnotations, m.invisibleAnnotations, + ) + } + } + + private fun dumpAnnotations( + pw: PrintWriter, + prefix: String, + visibleTypeAnnotations: List<TypeAnnotationNode>?, + invisibleTypeAnnotations: List<TypeAnnotationNode>?, + visibleAnnotations: List<AnnotationNode>?, + invisibleAnnotations: List<AnnotationNode>?, + ) { + for (an in visibleTypeAnnotations ?: emptyList()) { + pw.printf("%sTypeAnnotation(vis): %s\n", prefix, an.desc) + } + for (an in invisibleTypeAnnotations ?: emptyList()) { + pw.printf("%sTypeAnnotation(inv): %s\n", prefix, an.desc) + } + for (an in visibleAnnotations ?: emptyList()) { + pw.printf("%sAnnotation(vis): %s\n", prefix, an.desc) + if (an.values == null) { + continue + } + var i = 0 + while (i < an.values.size - 1) { + pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1]) + i += 2 + } + } + for (an in invisibleAnnotations ?: emptyList()) { + pw.printf("%sAnnotation(inv): %s\n", prefix, an.desc) + if (an.values == null) { + continue + } + var i = 0 + while (i < an.values.size - 1) { + pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1]) + i += 2 + } + } + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt new file mode 100644 index 000000000000..248121c63d78 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.ClassParseException +import com.android.hoststubgen.HostStubGenErrors +import com.android.hoststubgen.HostStubGenInternalException +import com.android.hoststubgen.InvalidAnnotationException +import com.android.hoststubgen.addNonNullElement +import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC +import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.asm.findAnnotationValueAsString +import com.android.hoststubgen.asm.findAnyAnnotation +import com.android.hoststubgen.asm.toHumanReadableClassName +import com.android.hoststubgen.asm.toHumanReadableMethodName +import com.android.hoststubgen.asm.toJvmClassName +import com.android.hoststubgen.log +import com.android.hoststubgen.utils.ClassFilter +import org.objectweb.asm.tree.AnnotationNode +import org.objectweb.asm.tree.ClassNode + +// TODO: Detect invalid cases, such as... +// - Class's visibility is lower than the members'. +// - HostSideTestSubstituteWith is set, but it doesn't have @Stub or @Keep + +/** + * [OutputFilter] using Java annotations. + */ +class AnnotationBasedFilter( + private val errors: HostStubGenErrors, + private val classes: ClassNodes, + stubAnnotations_: Set<String>, + keepAnnotations_: Set<String>, + stubClassAnnotations_: Set<String>, + keepClassAnnotations_: Set<String>, + throwAnnotations_: Set<String>, + removeAnnotations_: Set<String>, + substituteAnnotations_: Set<String>, + nativeSubstituteAnnotations_: Set<String>, + classLoadHookAnnotations_: Set<String>, + keepStaticInitializerAnnotations_: Set<String>, + private val annotationAllowedClassesFilter: ClassFilter, + fallback: OutputFilter, +) : DelegatingFilter(fallback) { + private var stubAnnotations = convertToInternalNames(stubAnnotations_) + private var keepAnnotations = convertToInternalNames(keepAnnotations_) + private var stubClassAnnotations = convertToInternalNames(stubClassAnnotations_) + private var keepClassAnnotations = convertToInternalNames(keepClassAnnotations_) + private var throwAnnotations = convertToInternalNames(throwAnnotations_) + private var removeAnnotations = convertToInternalNames(removeAnnotations_) + private var substituteAnnotations = convertToInternalNames(substituteAnnotations_) + private var nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_) + private var classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_) + private var keepStaticInitializerAnnotations = + convertToInternalNames(keepStaticInitializerAnnotations_) + + /** Annotations that control API visibility. */ + private var visibilityAnnotations: Set<String> = convertToInternalNames( + stubAnnotations_ + + keepAnnotations_ + + stubClassAnnotations_ + + keepClassAnnotations_ + + throwAnnotations_ + + removeAnnotations_) + + /** + * All the annotations we use. Note, this one is in a [convertToJvmNames] format unlike + * other ones, because of how it's used. + */ + private var allAnnotations: Set<String> = convertToJvmNames( + stubAnnotations_ + + keepAnnotations_ + + stubClassAnnotations_ + + keepClassAnnotations_ + + throwAnnotations_ + + removeAnnotations_ + + substituteAnnotations_ + + nativeSubstituteAnnotations_ + + classLoadHookAnnotations_) + + private val substitutionHelper = SubstitutionHelper() + + private val reasonAnnotation = "annotation" + private val reasonClassAnnotation = "class-annotation" + + /** + * Throw if an item has more than one visibility annotations. + * + * name1 - 4 are only used in exception messages. We take them as separate strings + * to avoid unnecessary string concatenations. + */ + private fun detectInvalidAnnotations( + visibles: List<AnnotationNode>?, + invisibles: List<AnnotationNode>?, + type: String, + name1: String, + name2: String, + name3: String, + ) { + var count = 0 + for (an in visibles ?: emptyList()) { + if (visibilityAnnotations.contains(an.desc)) { + count++ + } + } + for (an in invisibles ?: emptyList()) { + if (visibilityAnnotations.contains(an.desc)) { + count++ + } + } + if (count > 1) { + val description = if (name2 == "" && name3 == "") { + "$type $name1" + } else { + "$type $name1.$name2$name3" + } + throw InvalidAnnotationException( + "Found more than one visibility annotations on $description") + } + } + + fun findAnyAnnotation( + className: String, + anyAnnotations: Set<String>, + visibleAnnotations: List<AnnotationNode>?, + invisibleAnnotations: List<AnnotationNode>?, + ): AnnotationNode? { + val ret = findAnyAnnotation(anyAnnotations, visibleAnnotations, invisibleAnnotations) + + if (ret != null) { + if (!annotationAllowedClassesFilter.matches(className)) { + throw InvalidAnnotationException( + "Class ${className.toHumanReadableClassName()} is not allowed to have " + + "Ravenwood annotations. Contact g/ravenwood for more details.") + } + } + + return ret + } + + /** + * Find a visibility annotation. + * + * name1 - 4 are only used in exception messages. + */ + private fun findAnnotation( + className: String, + visibles: List<AnnotationNode>?, + invisibles: List<AnnotationNode>?, + type: String, + name1: String, + name2: String = "", + name3: String = "", + ): FilterPolicyWithReason? { + detectInvalidAnnotations(visibles, invisibles, type, name1, name2, name3) + + findAnyAnnotation(className, stubAnnotations, visibles, invisibles)?.let { + return FilterPolicy.Stub.withReason(reasonAnnotation) + } + findAnyAnnotation(className, stubClassAnnotations, visibles, invisibles)?.let { + return FilterPolicy.StubClass.withReason(reasonClassAnnotation) + } + findAnyAnnotation(className, keepAnnotations, visibles, invisibles)?.let { + return FilterPolicy.Keep.withReason(reasonAnnotation) + } + findAnyAnnotation(className, keepClassAnnotations, visibles, invisibles)?.let { + return FilterPolicy.KeepClass.withReason(reasonClassAnnotation) + } + findAnyAnnotation(className, throwAnnotations, visibles, invisibles)?.let { + return FilterPolicy.Throw.withReason(reasonAnnotation) + } + findAnyAnnotation(className, removeAnnotations, visibles, invisibles)?.let { + return FilterPolicy.Remove.withReason(reasonAnnotation) + } + + return null + } + + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + val cn = classes.getClass(className) + + findAnnotation( + cn.name, + cn.visibleAnnotations, + cn.invisibleAnnotations, + "class", + className)?.let { + return it + } + + // If it's any of the annotations, then always keep it. + if (allAnnotations.contains(className)) { + return FilterPolicy.KeepClass.withReason("HostStubGen Annotation") + } + + return super.getPolicyForClass(className) + } + + override fun getPolicyForField( + className: String, + fieldName: String + ): FilterPolicyWithReason { + val cn = classes.getClass(className) + + cn.fields?.firstOrNull { it.name == fieldName }?.let {fn -> + findAnnotation( + cn.name, + fn.visibleAnnotations, + fn.invisibleAnnotations, + "field", + className, + fieldName + )?.let { policy -> + // If the item has an annotation, then use it. + return policy + } + } + return super.getPolicyForField(className, fieldName) + } + + override fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String + ): FilterPolicyWithReason { + val cn = classes.getClass(className) + + if (methodName == CLASS_INITIALIZER_NAME && descriptor == CLASS_INITIALIZER_DESC) { + findAnyAnnotation(cn.name, keepStaticInitializerAnnotations, + cn.visibleAnnotations, cn.invisibleAnnotations)?.let { + return FilterPolicy.Keep.withReason(reasonAnnotation) + } + } + + cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn -> + // @SubstituteWith is going to complicate the policy here, so we ask helper + // what to do. + substitutionHelper.getPolicyFromSubstitution(cn, mn.name, mn.desc)?.let { + return it + } + + // If there's no substitution, then we check the annotation. + findAnnotation( + cn.name, + mn.visibleAnnotations, + mn.invisibleAnnotations, + "method", + className, + methodName, + descriptor + )?.let { policy -> + return policy + } + } + return super.getPolicyForMethod(className, methodName, descriptor) + } + + override fun getRenameTo( + className: String, + methodName: String, + descriptor: String + ): String? { + val cn = classes.getClass(className) + + // If the method has a "substitute with" annotation, then return its "value" parameter. + cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn -> + return substitutionHelper.getRenameTo(cn, mn.name, mn.desc) + } + return null + } + + override fun getNativeSubstitutionClass(className: String): String? { + classes.getClass(className).let { cn -> + findAnyAnnotation(nativeSubstituteAnnotations, + cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an -> + return getAnnotationField(an, "value")?.toJvmClassName() + } + } + return null + } + + override fun getClassLoadHooks(className: String): List<String> { + val e = classes.getClass(className).let { cn -> + findAnyAnnotation(classLoadHookAnnotations, + cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an -> + getAnnotationField(an, "value")?.toHumanReadableMethodName() + } + } + return addNonNullElement(super.getClassLoadHooks(className), e) + } + + private data class MethodKey(val name: String, val desc: String) + + /** + * In order to handle substitution, we need to build a reverse mapping of substitution + * methods. + * + * This class automatically builds such a map internally that the above methods can + * take advantage of. + */ + private inner class SubstitutionHelper { + private var currentClass: ClassNode? = null + + private var policiesFromSubstitution = mutableMapOf<MethodKey, FilterPolicyWithReason>() + private var substituteToMethods = mutableMapOf<MethodKey, String>() + + fun getPolicyFromSubstitution(cn: ClassNode, methodName: String, descriptor: String): + FilterPolicyWithReason? { + setClass(cn) + return policiesFromSubstitution[MethodKey(methodName, descriptor)] + } + + fun getRenameTo(cn: ClassNode, methodName: String, descriptor: String): String? { + setClass(cn) + return substituteToMethods[MethodKey(methodName, descriptor)] + } + + /** + * Every time we see a different class, we scan all its methods for substitution attributes, + * and compute (implicit) policies caused by them. + * + * For example, for the following methods: + * + * @Stub + * @Substitute(suffix = "_host") + * private void foo() { + * // This isn't supported on the host side. + * } + * private void foo_host() { + * // Host side implementation + * } + * + * We internally handle them as: + * + * foo() -> Remove + * foo_host() -> Stub, and then rename it to foo(). + */ + private fun setClass(cn: ClassNode) { + if (currentClass == cn) { + return + } + // If the class is changing, we'll rebuild the internal structure. + currentClass = cn + + policiesFromSubstitution.clear() + substituteToMethods.clear() + + for (mn in cn.methods ?: emptyList()) { + findAnyAnnotation(substituteAnnotations, + mn.visibleAnnotations, + mn.invisibleAnnotations)?.let { an -> + + // Find the policy for this method. + val policy = outermostFilter.getPolicyForMethod(cn.name, mn.name, mn.desc) + .policy.resolveClassWidePolicy() + // Make sure it's either Stub or Keep. + if (!(policy.needsInStub || policy.needsInImpl)) { + // TODO: Use the real annotation names in the message + errors.onErrorFound("@SubstituteWith must have either @Stub or @Keep") + return@let + } + if (!policy.isUsableWithMethods) { + throw HostStubGenInternalException("Policy $policy shouldn't show up here") + } + + val suffix = getAnnotationField(an, "suffix", false) ?: "\$ravenwood" + val renameFrom = mn.name + suffix + val renameTo = mn.name + + if (renameFrom == renameTo) { + errors.onErrorFound("@SubstituteWith have a different name") + return@let + } + + // This mn has "SubstituteWith". This means, + // 1. Re move the "rename-to" method, so add it to substitutedMethods. + policiesFromSubstitution[MethodKey(renameTo, mn.desc)] = + FilterPolicy.Remove.withReason("substitute-to") + + // If the policy is "stub", use "stub". + // Otherwise, it must be "keep" or "throw", but there's no point in using + // "throw", so let's use "keep". + val newPolicy = if (policy.needsInStub) policy else FilterPolicy.Keep + // 2. We also keep the from-to in the map. + policiesFromSubstitution[MethodKey(renameFrom, mn.desc)] = + newPolicy.withReason("substitute-from") + substituteToMethods[MethodKey(renameFrom, mn.desc)] = renameTo + + log.v("Substitution found: %s%s -> %s", renameFrom, mn.desc, renameTo) + } + } + } + } + + /** + * Return the (String) value of 'value' parameter from an annotation. + */ + private fun getAnnotationField(an: AnnotationNode, name: String, + required: Boolean = true): String? { + try { + val suffix = findAnnotationValueAsString(an, name) + if (suffix == null && required) { + errors.onErrorFound("Annotation \"${an.desc}\" must have field $name") + } + return suffix + } catch (e: ClassParseException) { + errors.onErrorFound(e.message!!) + return null + } + } + + companion object { + /** + * Convert from human-readable type names (e.g. "com.android.TypeName") to the internal type + * names (e.g. "Lcom/android/TypeName). + */ + private fun convertToInternalNames(input: Set<String>): Set<String> { + val ret = mutableSetOf<String>() + input.forEach { ret.add("L" + it.toJvmClassName() + ";") } + return ret + } + + /** + * Convert from human-readable type names to JVM type names. + */ + private fun convertToJvmNames(input: Set<String>): Set<String> { + val ret = mutableSetOf<String>() + input.forEach { ret.add(it.toJvmClassName()) } + return ret + } + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt new file mode 100644 index 000000000000..6aac3d88b8b1 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.asm.getDirectOuterClassName + +/** + * This is used as the second last fallback filter. This filter propagates the class-wide policy + * (obtained from [outermostFilter]) to the fields and methods. + */ +class ClassWidePolicyPropagatingFilter( + fallback: OutputFilter, + ) : DelegatingFilter(fallback) { + + private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? { + var currentClass = className + + while (true) { + outermostFilter.getPolicyForClass(className).let { policy -> + if (policy.policy.isClassWidePolicy) { + val p = if (resolve) policy.policy.resolveClassWidePolicy() else policy.policy + + return p.withReason(policy.reason).wrapReason("class-wide in $currentClass") + } + // If the class's policy is remove, then remove it. + if (policy.policy == FilterPolicy.Remove) { + return FilterPolicy.Remove.withReason("class-wide in $currentClass") + } + } + + // Next, look at the outer class... + val outer = getDirectOuterClassName(currentClass) + if (outer == null) { + return null + } + currentClass = outer + } + } + + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + // If it's a nested class, use the outer class's policy. + getDirectOuterClassName(className)?.let { outerName -> + getClassWidePolicy(outerName, resolve = false)?.let { policy -> + return policy + } + } + + return super.getPolicyForClass(className) + } + + override fun getPolicyForField( + className: String, + fieldName: String + ): FilterPolicyWithReason { + return getClassWidePolicy(className, resolve = true) + ?: super.getPolicyForField(className, fieldName) + } + + override fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String + ): FilterPolicyWithReason { + return getClassWidePolicy(className, resolve = true) + ?: super.getPolicyForMethod(className, methodName, descriptor) + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt new file mode 100644 index 000000000000..678e6eae0be6 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.HostStubGenInternalException + + +/** + * [OutputFilter] with a given policy. Used to represent the default policy. + * + * This is used as the last fallback filter. + * + * @param policy the policy. Cannot be a "substitute" policy. + */ +class ConstantFilter( + policy: FilterPolicy, + val reason: String +) : OutputFilter() { + val classPolicy: FilterPolicy + val fieldPolicy: FilterPolicy + val methodPolicy: FilterPolicy + + init { + if (policy.isSubstitute) { + throw HostStubGenInternalException( + "ConstantFilter doesn't allow substitution policies.") + } + if (policy.isClassWidePolicy) { + // We prevent it, because there's no point in using class-wide policies because + // all members get othe same policy too anyway. + throw HostStubGenInternalException( + "ConstantFilter doesn't allow class-wide policies.") + } + methodPolicy = policy + + // If the default policy is "throw", we convert it to "keep" for classes and fields. + classPolicy = when (policy) { + FilterPolicy.Throw -> FilterPolicy.Keep + else -> policy + } + fieldPolicy = classPolicy + } + + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + return classPolicy.withReason(reason) + } + + override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason { + return fieldPolicy.withReason(reason) + } + + override fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String, + ): FilterPolicyWithReason { + return methodPolicy.withReason(reason) + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DefaultHookInjectingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DefaultHookInjectingFilter.kt new file mode 100644 index 000000000000..d771003a955d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DefaultHookInjectingFilter.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.addLists + +class DefaultHookInjectingFilter( + defaultClassLoadHook: String?, + defaultMethodCallHook: String?, + fallback: OutputFilter +) : DelegatingFilter(fallback) { + /** + * Create a List containing a single element [e], if e != null. Otherwise, returns + * an empty list. + */ + private fun toSingleList(e: String?): List<String> { + if (e == null) { + return emptyList() + } + return listOf(e) + } + + private val defaultClassLoadHookAsList: List<String> = toSingleList(defaultClassLoadHook) + private val defaultMethodCallHookAsList: List<String> = toSingleList(defaultMethodCallHook) + + override fun getClassLoadHooks(className: String): List<String> { + return addLists(super.getClassLoadHooks(className), defaultClassLoadHookAsList) + } + + override fun getMethodCallHooks( + className: String, + methodName: String, + descriptor: String + ): List<String> { + return addLists( + super.getMethodCallHooks(className, methodName, descriptor), + defaultMethodCallHookAsList, + ) + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt new file mode 100644 index 000000000000..45f61c5b2c22 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +/** + * Base class for an [OutputFilter] that uses another filter as a fallback. + */ +abstract class DelegatingFilter( + // fallback shouldn't be used by subclasses, so make it private. + // They should instead be calling into `super` or `outermostFilter`. + private val fallback: OutputFilter +) : OutputFilter() { + init { + fallback.outermostFilter = this + } + + override var outermostFilter: OutputFilter = this + get() = field + set(value) { + field = value + // Propagate the inner filters. + fallback.outermostFilter = value + } + + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + return fallback.getPolicyForClass(className) + } + + override fun getPolicyForField( + className: String, + fieldName: String + ): FilterPolicyWithReason { + return fallback.getPolicyForField(className, fieldName) + } + + override fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String + ): FilterPolicyWithReason { + return fallback.getPolicyForMethod(className, methodName, descriptor) + } + + override fun getRenameTo( + className: String, + methodName: String, + descriptor: String + ): String? { + return fallback.getRenameTo(className, methodName, descriptor) + } + + override fun getNativeSubstitutionClass(className: String): String? { + return fallback.getNativeSubstitutionClass(className) + } + + override fun getClassLoadHooks(className: String): List<String> { + return fallback.getClassLoadHooks(className) + } + + override fun getMethodCallHooks( + className: String, + methodName: String, + descriptor: String + ): List<String> { + return fallback.getMethodCallHooks(className, methodName, descriptor) + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt new file mode 100644 index 000000000000..93179969e968 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +enum class FilterPolicy { + /** + * Keep the item in the stub jar file, so tests can use it. + */ + Stub, + + /** + * Keep the item in the impl jar file, but not in the stub file. Tests cannot use it directly, + * but indirectly. + */ + Keep, + + /** + * Only used for types. Keep the class in the stub, and also all its members. + * But each member can have another annotations to override it. + */ + StubClass, + + /** + * Only used for types. Keep the class in the impl, not in the stub, and also all its members. + * But each member can have another annotations to override it. + */ + KeepClass, + + /** + * Same as [Stub], but replace it with a "substitution" method. Only usable with methods. + */ + SubstituteAndStub, + + /** + * Same as [Keep], but replace it with a "substitution" method. Only usable with methods. + */ + SubstituteAndKeep, + + /** + * Only usable with methods. The item will be kept in the impl jar file, but when called, + * it'll throw. + */ + Throw, + + /** + * Only usable with methods. The item will be kept in the impl jar file, but when called, + * it'll no-op. Currently only supported for methods returning `void`. + */ + Ignore, + + /** + * Remove the item completely. + */ + Remove; + + val isSubstitute: Boolean + get() = this == SubstituteAndStub || this == SubstituteAndKeep + + val needsInStub: Boolean + get() = this == Stub || this == StubClass || this == SubstituteAndStub + + val needsInImpl: Boolean + get() = this != Remove + + /** Returns whether a policy can be used with classes */ + val isUsableWithClasses: Boolean + get() { + return when (this) { + Stub, StubClass, Keep, KeepClass, Remove -> true + else -> false + } + } + + /** Returns whether a policy can be used with fields. */ + val isUsableWithFields: Boolean + get() { + return when (this) { + Stub, Keep, Remove -> true + else -> false + } + } + + /** Returns whether a policy can be used with methods */ + val isUsableWithMethods: Boolean + get() { + return when (this) { + StubClass, KeepClass -> false + else -> true + } + } + + /** Returns whether a policy is a class-wide one. */ + val isClassWidePolicy: Boolean + get() { + return when (this) { + StubClass, KeepClass -> true + else -> false + } + } + + fun getSubstitutionBasePolicy(): FilterPolicy { + return when (this) { + SubstituteAndKeep -> Keep + SubstituteAndStub -> Stub + else -> this + } + } + + /** + * Convert {Stub,Keep}Class to the corresponding Stub or Keep. + */ + fun resolveClassWidePolicy(): FilterPolicy { + return when (this) { + StubClass -> Stub + KeepClass -> Keep + else -> this + } + } + + /** + * Create a [FilterPolicyWithReason] with a given reason. + */ + fun withReason(reason: String): FilterPolicyWithReason { + return FilterPolicyWithReason(this, reason) + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt new file mode 100644 index 000000000000..b64a2f5fd8a5 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +/** + * Captures a [FilterPolicy] with a human-readable reason. + */ +data class FilterPolicyWithReason ( + val policy: FilterPolicy, + val reason: String = "", +) { + /** + * Return a new [FilterPolicy] with an updated reason, while keeping the original reason + * as an "inner-reason". + */ + fun wrapReason(reason: String): FilterPolicyWithReason { + return FilterPolicyWithReason(policy, "$reason [inner-reason: ${this.reason}]") + } + + /** + * If the visibility is lower than "Keep" (meaning if it's "remove"), + * then return a new [FilterPolicy] with "Keep". + * Otherwise, return itself + */ + fun promoteToKeep(promotionReason: String): FilterPolicyWithReason { + if (policy.needsInImpl) { + return this + } + val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep + + return FilterPolicyWithReason(newPolicy, + "$promotionReason [original remove reason: ${this.reason}]") + } + + /** + * If the visibility is above "Keep" (meaning if it's "stub"), + * then return a new [FilterPolicy] with "Keep". + * Otherwise, return itself + */ + fun demoteToKeep(promotionReason: String): FilterPolicyWithReason { + if (!policy.needsInStub) { + return this + } + val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep + + return FilterPolicyWithReason(newPolicy, + "$promotionReason [original stub reason: ${this.reason}]") + } + + override fun toString(): String { + return "[$policy - reason: $reason]" + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt new file mode 100644 index 000000000000..84856aca84cc --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.HostStubGenErrors +import com.android.hoststubgen.HostStubGenInternalException +import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC +import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME +import com.android.hoststubgen.asm.isAnonymousInnerClass +import com.android.hoststubgen.log +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.asm.isAnnotation +import com.android.hoststubgen.asm.isAutoGeneratedEnumMember +import com.android.hoststubgen.asm.isEnum +import com.android.hoststubgen.asm.isSynthetic +import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate +import org.objectweb.asm.tree.ClassNode + +/** + * Filter implementing "implicit" rules, such as: + * - "keep all anonymous inner classes if the outer class is keep". + * (But anonymous inner classes should never be in "stub") + * - For classes in stub, make sure private parameterless constructors are also in stub, if any. + * + * TODO: Do we need a way to make anonymous class methods and lambdas "throw"? + */ +class ImplicitOutputFilter( + private val errors: HostStubGenErrors, + private val classes: ClassNodes, + fallback: OutputFilter +) : DelegatingFilter(fallback) { + private fun getClassImplicitPolicy(className: String, cn: ClassNode): FilterPolicyWithReason? { + if (isAnonymousInnerClass(cn)) { + log.forDebug { +// log.d(" anon-inner class: ${className} outer: ${cn.outerClass} ") + } + if (cn.outerClass == null) { + throw HostStubGenInternalException( + "outerClass is null for anonymous inner class") + } + // If the outer class needs to be in impl, it should be in impl too. + val outerPolicy = outermostFilter.getPolicyForClass(cn.outerClass) + if (outerPolicy.policy.needsInImpl) { + return FilterPolicy.KeepClass.withReason("anonymous-inner-class") + } + } + return null + } + + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + val fallback = super.getPolicyForClass(className) + + val cn = classes.getClass(className) + + // Use the implicit policy, if any. + getClassImplicitPolicy(className, cn)?.let { return it } + + return fallback + } + + override fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String + ): FilterPolicyWithReason { + val fallback = super.getPolicyForMethod(className, methodName, descriptor) + val classPolicy = outermostFilter.getPolicyForClass(className) + + // If the class is in the stub, then we need to put the private constructor in the stub too, + // to prevent the class from getting instantiated. + if (classPolicy.policy.needsInStub && + !fallback.policy.needsInStub && + (methodName == "<init>") && // Constructor? + (descriptor == "()V")) { // Has zero parameters? + classes.findMethod(className, methodName, descriptor)?.let { mn -> + if (isVisibilityPrivateOrPackagePrivate(mn.access)) { + return FilterPolicy.Stub.withReason("private constructor in stub class") + } + } + } + + val cn = classes.getClass(className) + + // If we throw from the static initializer, the class would be useless, so we convert it + // "keep" instead. + // Unless it's an enum -- in that case, the below code would handle it. + if (!cn.isEnum() && + fallback.policy == FilterPolicy.Throw && + methodName == CLASS_INITIALIZER_NAME && descriptor == CLASS_INITIALIZER_DESC) { + // TODO Maybe show a warning?? But that'd be too noisy with --default-throw. + return FilterPolicy.Ignore.withReason( + "'throw' on static initializer is handled as 'ignore'" + + " [original throw reason: ${fallback.reason}]") + } + + log.d("Class ${cn.name} Class policy: $classPolicy") + if (classPolicy.policy.needsInImpl) { + // Do it only when the class needs to be kept... + + // Member policy should be "keep" or "stub". + val memberPolicy = classPolicy.policy.resolveClassWidePolicy() + + val mn = classes.findMethod(className, methodName, descriptor) + + // Keep (or stub) the generated enum members. + if (cn.isEnum()) { + mn?.let { mn -> + if (isAutoGeneratedEnumMember(mn)) { + return memberPolicy.withReason(classPolicy.reason).wrapReason("enum") + } + } + } + + // Keep (or stub) all members of annotations. + if (cn.isAnnotation()) { + return memberPolicy.withReason(classPolicy.reason).wrapReason("annotation") + } + + mn?.let { + if (mn.isSynthetic()) { + // For synthetic methods (such as lambdas), let's just inherit the class's + // policy. + return memberPolicy.withReason(classPolicy.reason).wrapReason( + "synthetic method") + } + } + } + + return fallback + } + + override fun getPolicyForField( + className: String, + fieldName: String + ): FilterPolicyWithReason { + val fallback = super.getPolicyForField(className, fieldName) + + val cn = classes.getClass(className) + val classPolicy = super.getPolicyForClass(className) + + log.d("Class ${cn.name} Class policy: $classPolicy") + if (classPolicy.policy.needsInImpl) { + // Do it only when the class needs to be kept... + + // Member policy should be "keep" or "stub". + val memberPolicy = classPolicy.policy.resolveClassWidePolicy() + + // Keep (or stub) the generated enum members. + if (cn.isEnum()) { + classes.findField(className, fieldName)?.let { fn -> + if (isAutoGeneratedEnumMember(fn)) { + return memberPolicy.withReason(classPolicy.reason).wrapReason("enum") + } + } + } + + // Keep (or stub) all members of annotations. + if (cn.isAnnotation()) { + return memberPolicy.withReason(classPolicy.reason).wrapReason("annotation") + } + } + + return fallback + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt new file mode 100644 index 000000000000..5659a35170c1 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.UnknownApiException +import com.android.hoststubgen.addNonNullElement +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.asm.toHumanReadableClassName +import com.android.hoststubgen.asm.toHumanReadableMethodName + +// TODO: Validate all input names. + +class InMemoryOutputFilter( + private val classes: ClassNodes, + fallback: OutputFilter, +) : DelegatingFilter(fallback) { + private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf() + private val mRenames: MutableMap<String, String> = mutableMapOf() + private val mNativeSubstitutionClasses: MutableMap<String, String> = mutableMapOf() + private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf() + + private fun getClassKey(className: String): String { + return className.toHumanReadableClassName() + } + + private fun getFieldKey(className: String, fieldName: String): String { + return getClassKey(className) + "." + fieldName + } + + private fun getMethodKey(className: String, methodName: String, signature: String): String { + return getClassKey(className) + "." + methodName + ";" + signature + } + + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className) + } + + private fun ensureClassExists(className: String) { + if (classes.findClass(className) == null) { + throw UnknownApiException("Unknown class $className") + } + } + + private fun ensureFieldExists(className: String, fieldName: String) { + if (classes.findField(className, fieldName) == null) { + throw UnknownApiException("Unknown field $className.$fieldName") + } + } + + private fun ensureMethodExists( + className: String, + methodName: String, + descriptor: String + ) { + if (classes.findMethod(className, methodName, descriptor) == null) { + throw UnknownApiException("Unknown method $className.$methodName$descriptor") + } + } + + fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) { + ensureClassExists(className) + mPolicies[getClassKey(className)] = policy + } + + override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason { + return mPolicies[getFieldKey(className, fieldName)] + ?: super.getPolicyForField(className, fieldName) + } + + fun setPolicyForField(className: String, fieldName: String, policy: FilterPolicyWithReason) { + ensureFieldExists(className, fieldName) + mPolicies[getFieldKey(className, fieldName)] = policy + } + + override fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String, + ): FilterPolicyWithReason { + return mPolicies[getMethodKey(className, methodName, descriptor)] + ?: super.getPolicyForMethod(className, methodName, descriptor) + } + + fun setPolicyForMethod( + className: String, + methodName: String, + descriptor: String, + policy: FilterPolicyWithReason, + ) { + ensureMethodExists(className, methodName, descriptor) + mPolicies[getMethodKey(className, methodName, descriptor)] = policy + } + + override fun getRenameTo(className: String, methodName: String, descriptor: String): String? { + return mRenames[getMethodKey(className, methodName, descriptor)] + ?: super.getRenameTo(className, methodName, descriptor) + } + + fun setRenameTo(className: String, methodName: String, descriptor: String, toName: String) { + ensureMethodExists(className, methodName, descriptor) + ensureMethodExists(className, toName, descriptor) + mRenames[getMethodKey(className, methodName, descriptor)] = toName + } + + override fun getNativeSubstitutionClass(className: String): String? { + return mNativeSubstitutionClasses[getClassKey(className)] + ?: super.getNativeSubstitutionClass(className) + } + + fun setNativeSubstitutionClass(from: String, to: String) { + ensureClassExists(from) + + // Native substitute classes may be provided from other jars, so we can't do this check. + // ensureClassExists(to) + mNativeSubstitutionClasses[getClassKey(from)] = to.toHumanReadableClassName() + } + + override fun getClassLoadHooks(className: String): List<String> { + return addNonNullElement(super.getClassLoadHooks(className), + mClassLoadHooks[getClassKey(className)]) + } + + fun setClassLoadHook(className: String, methodName: String) { + mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName() + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt new file mode 100644 index 000000000000..45dd38d10ef5 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +/** + * An [OutputFilter] that keeps all classes by default. (but none of its members) + * + * We're not currently using it, but using it *might* make certain things easier. For example, with + * this, all classes would at least be loadable. + */ +class KeepAllClassesFilter(fallback: OutputFilter) : DelegatingFilter(fallback) { + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + // If the default visibility wouldn't keep it, change it to "keep". + val f = super.getPolicyForClass(className) + return f.promoteToKeep("keep-all-classes") + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt new file mode 100644 index 000000000000..3df16ffa99b3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +/** + * Base class for "filters", which decides what APIs should go to the stub / impl jars. + */ +abstract class OutputFilter { + /** + * Filters are stacked over one another. This fields contains the "outermost" filter in a + * filter stack chain. + * + * Subclasses must use this filter to get a policy, when they need to infer a policy + * from the policy of another API. + * + * For example, [ClassWidePolicyPropagatingFilter] needs to check the policy of the enclosing + * class to propagate "class-wide" policies, but when it does so, it can't just use + * `this.getPolicyForClass()` because that wouldn't return policies decided by "outer" + * filters. Instead, it uses [outermostFilter.getPolicyForClass()]. + * + * Note, [outermostFilter] can be itself, so make sure not to cause infinity recursions when + * using it. + */ + open var outermostFilter: OutputFilter = this + get() = field + set(value) { + field = value + } + + abstract fun getPolicyForClass(className: String): FilterPolicyWithReason + + abstract fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason + + abstract fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String, + ): FilterPolicyWithReason + + /** + * If a given method is a substitute-from method, return the substitute-to method name. + * + * The substitute-to and from methods must have the same signature, in the same class. + */ + open fun getRenameTo(className: String, methodName: String, descriptor: String): String? { + return null + } + + /** + * Return a "native substitution class" name for a given class. + * + * The result will be in a "human readable" form. (e.g. uses '.'s instead of '/'s) + * + * (which corresponds to @HostSideTestNativeSubstitutionClass of the standard annotations.) + */ + open fun getNativeSubstitutionClass(className: String): String? { + return null + } + + /** + * Return a "class load hook" class name for a given class. + * + * (which corresponds to @HostSideTestClassLoadHook of the standard annotations.) + */ + open fun getClassLoadHooks(className: String): List<String> { + return emptyList() + } + + /** + * Return the "method call hook" class name. + * + * The class has to have a function with the following signature: + * `public static void onMethodCalled(Class<?> clazz, String name, String descriptor)`. + */ + open fun getMethodCallHooks(className: String, methodName: String, descriptor: String): + List<String> { + return emptyList() + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt new file mode 100644 index 000000000000..f92a0271d7c7 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.HostStubGenErrors +import com.android.hoststubgen.asm.ClassNodes + +private const val REASON = "demoted, not in intersect jars" + +/** + * An [OutputFilter] that will restrict what to put in stub to only what shows up in "intersecting + * jar" files. + * + * For example, if the Android public API stub jar is provided, then the HostStubGen's output + * stub will be restricted to public APIs. + */ +class StubIntersectingFilter( + private val errors: HostStubGenErrors, + /** + * If a class / field / method is not in any of these jars, then we will not put it in + * stub. + */ + private val intersectingJars: Map<String, ClassNodes>, + fallback: OutputFilter, +) : DelegatingFilter(fallback) { + private inline fun exists(predicate: (ClassNodes) -> Boolean): Boolean { + intersectingJars.forEach { entry -> + if (predicate(entry.value)) { + return true + } + } + return false + } + + /** + * If [origPolicy] is less than "Stub", then return it as-is. + * + * Otherwise, call [inStubChecker] to see if the API is in any of [intersectingJars]. + * If yes, then return [origPolicy] as-is. Otherwise, demote to "Keep". + */ + private fun intersectWithStub( + origPolicy: FilterPolicyWithReason, + inStubChecker: () -> Boolean, + ): FilterPolicyWithReason { + if (origPolicy.policy.needsInStub) { + // Only check the stub jars, when the class is supposed to be in stub otherwise. + if (!inStubChecker()) { + return origPolicy.demoteToKeep(REASON) + } + } + return origPolicy + } + + override fun getPolicyForClass(className: String): FilterPolicyWithReason { + return intersectWithStub(super.getPolicyForClass(className)) { + exists { classes -> classes.findClass(className) != null } + } + } + + override fun getPolicyForField( + className: String, + fieldName: String + ): FilterPolicyWithReason { + return intersectWithStub(super.getPolicyForField(className, fieldName)) { + exists { classes -> classes.findField(className, fieldName) != null } + } + } + + override fun getPolicyForMethod( + className: String, + methodName: String, + descriptor: String + ): FilterPolicyWithReason { + return intersectWithStub(super.getPolicyForMethod(className, methodName, descriptor)) { + exists { classes -> classes.findMethod(className, methodName, descriptor) != null } + } + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt new file mode 100644 index 000000000000..416f08505867 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.ParseException +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.log +import com.android.hoststubgen.normalizeTextLine +import com.android.hoststubgen.whitespaceRegex +import org.objectweb.asm.Opcodes +import org.objectweb.asm.tree.ClassNode +import java.io.BufferedReader +import java.io.FileReader +import java.io.PrintWriter +import java.util.Objects + +/** + * Print a class node as a "keep" policy. + */ +fun printAsTextPolicy(pw: PrintWriter, cn: ClassNode) { + pw.printf("class %s\t%s\n", cn.name, "keep") + + for (f in cn.fields ?: emptyList()) { + pw.printf(" field %s\t%s\n", f.name, "keep") + } + for (m in cn.methods ?: emptyList()) { + pw.printf(" method %s\t%s\t%s\n", m.name, m.desc, "keep") + } +} + +/** Return true if [access] is either public or protected. */ +private fun isVisible(access: Int): Boolean { + return (access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PROTECTED)) != 0 +} + +private const val FILTER_REASON = "file-override" + +/** + * Read a given "policy" file and return as an [OutputFilter] + */ +fun createFilterFromTextPolicyFile( + filename: String, + classes: ClassNodes, + fallback: OutputFilter, + ): OutputFilter { + log.i("Loading offloaded annotations from $filename ...") + log.withIndent { + val ret = InMemoryOutputFilter(classes, fallback) + + var lineNo = 0 + + try { + BufferedReader(FileReader(filename)).use { reader -> + var className = "" + + while (true) { + var line = reader.readLine() + if (line == null) { + break + } + lineNo++ + + line = normalizeTextLine(line) + + if (line.isEmpty()) { + continue // skip empty lines. + } + + val fields = line.split(whitespaceRegex).toTypedArray() + when (fields[0].lowercase()) { + "c", "class" -> { + if (fields.size < 3) { + throw ParseException("Class ('c') expects 2 fields.") + } + className = fields[1] + if (fields[2].startsWith("!")) { + // It's a native-substitution. + val toClass = fields[2].substring(1) + ret.setNativeSubstitutionClass(className, toClass) + } else if (fields[2].startsWith("~")) { + // It's a class-load hook + val callback = fields[2].substring(1) + ret.setClassLoadHook(className, callback) + } else { + val policy = parsePolicy(fields[2]) + if (!policy.isUsableWithClasses) { + throw ParseException("Class can't have policy '$policy'") + } + Objects.requireNonNull(className) + + // TODO: Duplicate check, etc + ret.setPolicyForClass(className, policy.withReason(FILTER_REASON)) + } + } + + "f", "field" -> { + if (fields.size < 3) { + throw ParseException("Field ('f') expects 2 fields.") + } + val name = fields[1] + val policy = parsePolicy(fields[2]) + if (!policy.isUsableWithFields) { + throw ParseException("Field can't have policy '$policy'") + } + Objects.requireNonNull(className) + + // TODO: Duplicate check, etc + ret.setPolicyForField(className, name, policy.withReason(FILTER_REASON)) + } + + "m", "method" -> { + if (fields.size < 4) { + throw ParseException("Method ('m') expects 3 fields.") + } + val name = fields[1] + val signature = fields[2] + val policy = parsePolicy(fields[3]) + + if (!policy.isUsableWithMethods) { + throw ParseException("Method can't have policy '$policy'") + } + + Objects.requireNonNull(className) + + ret.setPolicyForMethod(className, name, signature, + policy.withReason(FILTER_REASON)) + if (policy.isSubstitute) { + val fromName = fields[3].substring(1) + + if (fromName == name) { + throw ParseException( + "Substitution must have a different name") + } + + // Set the policy for the "from" method. + ret.setPolicyForMethod(className, fromName, signature, + policy.getSubstitutionBasePolicy() + .withReason(FILTER_REASON)) + + // Keep "from" -> "to" mapping. + ret.setRenameTo(className, fromName, signature, name) + } + } + + else -> { + throw ParseException("Unknown directive \"${fields[0]}\"") + } + } + } + } + } catch (e: ParseException) { + throw e.withSourceInfo(filename, lineNo) + } + return ret + } +} + +private fun parsePolicy(s: String): FilterPolicy { + return when (s.lowercase()) { + "s", "stub" -> FilterPolicy.Stub + "k", "keep" -> FilterPolicy.Keep + "t", "throw" -> FilterPolicy.Throw + "r", "remove" -> FilterPolicy.Remove + "sc", "stubclass" -> FilterPolicy.StubClass + "kc", "keepclass" -> FilterPolicy.KeepClass + else -> { + if (s.startsWith("@")) { + FilterPolicy.SubstituteAndStub + } else if (s.startsWith("%")) { + FilterPolicy.SubstituteAndKeep + } else { + throw ParseException("Invalid policy \"$s\"") + } + } + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt new file mode 100644 index 000000000000..01a7ab3eacfa --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.utils + +import com.android.hoststubgen.ParseException +import com.android.hoststubgen.asm.toHumanReadableClassName +import com.android.hoststubgen.asm.toJvmClassName +import com.android.hoststubgen.normalizeTextLine +import java.io.File + +/** + * General purpose filter for class names. + */ +class ClassFilter private constructor ( + val defaultResult: Boolean, +) { + private data class FilterElement( + val allowed: Boolean, + val internalName: String, + val isPrefix: Boolean, + ) { + fun matches(classInternalName: String): Boolean { + if (isPrefix) { + return classInternalName.startsWith(internalName) + } else { + return classInternalName == internalName + } + } + } + + private val elements: MutableList<FilterElement> = mutableListOf() + + private val cache: MutableMap<String, Boolean> = mutableMapOf() + + /** + * Takes an internal class name (e.g. "com/android/hoststubgen/ClassName") and returns if + * matches the filter or not. + */ + fun matches(classInternalName: String): Boolean { + cache[classInternalName]?.let { + return it + } + + var result = defaultResult + run outer@{ + elements.forEach { e -> + if (e.matches(classInternalName)) { + result = e.allowed + return@outer // break equivalent. + } + } + } + cache[classInternalName] = result + + return result + } + + fun getCacheSizeForTest(): Int { + return cache.size + } + + companion object { + /** + * Return a filter that alawys returns true or false. + */ + fun newNullFilter(defaultResult: Boolean): ClassFilter { + return ClassFilter(defaultResult) + } + + /** Build a filter from a file. */ + fun loadFromFile(filename: String, defaultResult: Boolean): ClassFilter { + return buildFromString(File(filename).readText(), defaultResult, filename) + } + + /** Build a filter from a string (for unit tests). */ + fun buildFromString( + filterString: String, + defaultResult: Boolean, + filenameForErrorMessage: String + ): ClassFilter { + val ret = ClassFilter(defaultResult) + + var lineNo = 0 + filterString.split('\n').forEach { s -> + lineNo++ + + var line = normalizeTextLine(s) + + if (line.isEmpty()) { + return@forEach // skip empty lines. + } + + line = line.toHumanReadableClassName() // Convert all the slashes to periods. + + var allow = true + if (line.startsWith("!")) { + allow = false + line = line.substring(1).trimStart() + } + + // Special case -- matches any class names. + if (line == "*") { + ret.elements.add(FilterElement(allow, "", true)) + return@forEach + } + + // Handle wildcard -- e.g. "package.name.*" + if (line.endsWith(".*")) { + ret.elements.add(FilterElement( + allow, line.substring(0, line.length - 2).toJvmClassName(), true)) + return@forEach + } + + // Any other uses of "*" would be an error. + if (line.contains('*')) { + throw ParseException( + "Wildcard (*) can only show up as the last element", + filenameForErrorMessage, + lineNo + ) + } + ret.elements.add(FilterElement(allow, line.toJvmClassName(), false)) + } + + return ret + } + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt new file mode 100644 index 000000000000..f25e862d6095 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.visitors + +import com.android.hoststubgen.HostStubGenErrors +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.asm.getPackageNameFromClassName +import com.android.hoststubgen.asm.resolveClassName +import com.android.hoststubgen.asm.toJvmClassName +import com.android.hoststubgen.filters.FilterPolicy +import com.android.hoststubgen.filters.FilterPolicyWithReason +import com.android.hoststubgen.filters.OutputFilter +import com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +import com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass +import com.android.hoststubgen.log +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.FieldVisitor +import org.objectweb.asm.MethodVisitor +import org.objectweb.asm.Opcodes +import org.objectweb.asm.commons.ClassRemapper +import org.objectweb.asm.util.TraceClassVisitor +import java.io.PrintWriter + +val OPCODE_VERSION = Opcodes.ASM9 + +abstract class BaseAdapter ( + protected val classes: ClassNodes, + nextVisitor: ClassVisitor, + protected val filter: OutputFilter, + protected val options: Options, +) : ClassVisitor(OPCODE_VERSION, nextVisitor) { + + /** + * Options to control the behavior. + */ + data class Options ( + val errors: HostStubGenErrors, + val enablePreTrace: Boolean, + val enablePostTrace: Boolean, + val enableNonStubMethodCallDetection: Boolean, + ) + + protected lateinit var currentPackageName: String + protected lateinit var currentClassName: String + protected var nativeSubstitutionClass: String? = null + protected lateinit var classPolicy: FilterPolicyWithReason + + /** + * Return whether an item with a given policy should be included in the output. + */ + protected abstract fun shouldEmit(policy: FilterPolicy): Boolean + + override fun visit( + version: Int, + access: Int, + name: String, + signature: String?, + superName: String?, + interfaces: Array<String>, + ) { + super.visit(version, access, name, signature, superName, interfaces) + currentClassName = name + currentPackageName = getPackageNameFromClassName(name) + classPolicy = filter.getPolicyForClass(currentClassName) + + log.d("[%s] visit: %s (package: %s)", this.javaClass.simpleName, name, currentPackageName) + log.indent() + log.v("Emitting class: %s", name) + log.indent() + + filter.getNativeSubstitutionClass(currentClassName)?.let { className -> + val fullClassName = resolveClassName(className, currentPackageName).toJvmClassName() + log.d(" NativeSubstitutionClass: $fullClassName") + if (classes.findClass(fullClassName) == null) { + log.w("Native substitution class $fullClassName not found. Class must be " + + "available at runtime.") + } else { + // If the class exists, it must have a KeepClass policy. + if (filter.getPolicyForClass(fullClassName).policy != FilterPolicy.KeepClass) { + // TODO: Use real annotation name. + options.errors.onErrorFound( + "Native substitution class $fullClassName should have @Keep.") + } + } + + nativeSubstitutionClass = fullClassName + } + // Inject annotations to generated classes. + if (classPolicy.policy.needsInStub) { + visitAnnotation(HostStubGenProcessedStubClass.CLASS_DESCRIPTOR, true) + } + if (classPolicy.policy.needsInImpl) { + visitAnnotation(HostStubGenProcessedKeepClass.CLASS_DESCRIPTOR, true) + } + } + + override fun visitEnd() { + log.unindent() + log.unindent() + super.visitEnd() + } + + var skipMemberModificationNestCount = 0 + + /** + * This method allows writing class members without any modifications. + */ + protected inline fun writeRawMembers(callback: () -> Unit) { + skipMemberModificationNestCount++ + try { + callback() + } finally { + skipMemberModificationNestCount-- + } + } + + override fun visitField( + access: Int, + name: String, + descriptor: String, + signature: String?, + value: Any?, + ): FieldVisitor? { + if (skipMemberModificationNestCount > 0) { + return super.visitField(access, name, descriptor, signature, value) + } + val policy = filter.getPolicyForField(currentClassName, name) + log.d("visitField: %s %s [%x] Policy: %s", name, descriptor, access, policy) + + log.withIndent { + if (!shouldEmit(policy.policy)) { + log.d("Removing %s %s", name, policy) + return null + } + + log.v("Emitting field: %s %s %s", name, descriptor, policy) + return super.visitField(access, name, descriptor, signature, value) + } + } + + override fun visitMethod( + access: Int, + name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + ): MethodVisitor? { + if (skipMemberModificationNestCount > 0) { + return super.visitMethod(access, name, descriptor, signature, exceptions) + } + val p = filter.getPolicyForMethod(currentClassName, name, descriptor) + log.d("visitMethod: %s%s [%x] [%s] Policy: %s", name, descriptor, access, signature, p) + + log.withIndent { + // If it's a substitute-to method, then skip. + val policy = filter.getPolicyForMethod(currentClassName, name, descriptor) + if (policy.policy.isSubstitute) { + log.d("Skipping %s%s %s", name, descriptor, policy) + return null + } + if (!shouldEmit(p.policy)) { + log.d("Removing %s%s %s", name, descriptor, policy) + return null + } + + // Maybe rename the method. + val newName: String + val substituteTo = filter.getRenameTo(currentClassName, name, descriptor) + if (substituteTo != null) { + newName = substituteTo + log.v("Emitting %s.%s%s as %s %s", currentClassName, name, descriptor, + newName, policy) + } else { + log.v("Emitting method: %s%s %s", name, descriptor, policy) + newName = name + } + + // Let subclass update the flag. + // But note, we only use it when calling the super's method, + // but not for visitMethodInner(), beucase when subclass wants to change access, + // it can do so inside visitMethodInner(). + val newAccess = updateAccessFlags(access, name, descriptor) + + return visitMethodInner(access, newName, descriptor, signature, exceptions, policy, + super.visitMethod(newAccess, newName, descriptor, signature, exceptions)) + } + } + + open fun updateAccessFlags( + access: Int, + name: String, + descriptor: String, + ): Int { + return access + } + + abstract fun visitMethodInner( + access: Int, + name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + policy: FilterPolicyWithReason, + superVisitor: MethodVisitor?, + ): MethodVisitor? + + companion object { + fun getVisitor( + classInternalName: String, + classes: ClassNodes, + nextVisitor: ClassVisitor, + filter: OutputFilter, + packageRedirector: PackageRedirectRemapper, + forImpl: Boolean, + options: Options, + ): ClassVisitor { + var next = nextVisitor + + val verbosePrinter = PrintWriter(log.getVerbosePrintStream()) + + // Inject TraceClassVisitor for debugging. + if (options.enablePostTrace) { + next = TraceClassVisitor(next, verbosePrinter) + } + + // Handle --package-redirect + if (!packageRedirector.isEmpty) { + // Don't apply the remapper on redirect-from classes. + // Otherwise, if the target jar actually contains the "from" classes (which + // may or may not be the case) they'd be renamed. + // But we update all references in other places, so, a method call to a "from" class + // would be replaced with the "to" class. All type references (e.g. variable types) + // will be updated too. + if (!packageRedirector.isTarget(classInternalName)) { + next = ClassRemapper(next, packageRedirector) + } else { + log.v("Class $classInternalName is a redirect-from class, not applying" + + " --package-redirect") + } + } + + var ret: ClassVisitor + if (forImpl) { + ret = ImplGeneratingAdapter(classes, next, filter, options) + } else { + ret = StubGeneratingAdapter(classes, next, filter, options) + } + + // Inject TraceClassVisitor for debugging. + if (options.enablePreTrace) { + ret = TraceClassVisitor(ret, verbosePrinter) + } + return ret + } + } +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt new file mode 100644 index 000000000000..8250412b3717 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.visitors + +import org.objectweb.asm.AnnotationVisitor +import org.objectweb.asm.Attribute +import org.objectweb.asm.Handle +import org.objectweb.asm.Label +import org.objectweb.asm.MethodVisitor +import org.objectweb.asm.Opcodes +import org.objectweb.asm.TypePath + +/** + * A method visitor that removes everything from method body. + * + * To inject a method body, override [visitCode] and create the opcodes there. + */ +abstract class BodyReplacingMethodVisitor( + access: Int, + name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor?, +) : MethodVisitor(OPCODE_VERSION, next) { + val isVoid: Boolean + val isStatic: Boolean + + init { + isVoid = descriptor.endsWith(")V") + isStatic = access and Opcodes.ACC_STATIC != 0 + } + + // Following methods are for things that we need to keep. + // Since they're all calling the super method, we can just remove them, but we keep them + // just to clarify what we're keeping. + + final override fun visitParameter( + name: String?, + access: Int + ) { + super.visitParameter(name, access) + } + + final override fun visitAnnotationDefault(): AnnotationVisitor? { + return super.visitAnnotationDefault() + } + + final override fun visitAnnotation( + descriptor: String?, + visible: Boolean + ): AnnotationVisitor? { + return super.visitAnnotation(descriptor, visible) + } + + final override fun visitTypeAnnotation( + typeRef: Int, + typePath: TypePath?, + descriptor: String?, + visible: Boolean + ): AnnotationVisitor? { + return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible) + } + + final override fun visitAnnotableParameterCount( + parameterCount: Int, + visible: Boolean + ) { + super.visitAnnotableParameterCount(parameterCount, visible) + } + + final override fun visitParameterAnnotation( + parameter: Int, + descriptor: String?, + visible: Boolean + ): AnnotationVisitor? { + return super.visitParameterAnnotation(parameter, descriptor, visible) + } + + final override fun visitAttribute(attribute: Attribute?) { + super.visitAttribute(attribute) + } + + override fun visitEnd() { + super.visitEnd() + } + + /** + * Control when to emit the code. We use this to ignore all visitXxx method calls caused by + * the original method, so we'll remove all the original code. + * + * Only when visitXxx methods are called from [emitNewCode], we pass-through to the base class, + * so the body will be generated. + * + * (See also https://asm.ow2.io/asm4-guide.pdf section 3.2.1 about the MethovVisitor + * call order.) + */ + var emitCode = false + + final override fun visitCode() { + super.visitCode() + + try { + emitCode = true + + emitNewCode() + } finally { + emitCode = false + } + } + + /** + * Subclass must implement it and emit code, and call [visitMaxs] at the end. + */ + abstract fun emitNewCode() + + final override fun visitMaxs( + maxStack: Int, + maxLocals: Int + ) { + if (emitCode) { + super.visitMaxs(maxStack, maxLocals) + } + } + + // Following methods are called inside a method body, and we don't want to + // emit any of them, so they are all no-op. + + final override fun visitFrame( + type: Int, + numLocal: Int, + local: Array<out Any>?, + numStack: Int, + stack: Array<out Any>? + ) { + if (emitCode) { + super.visitFrame(type, numLocal, local, numStack, stack) + } + } + + final override fun visitInsn(opcode: Int) { + if (emitCode) { + super.visitInsn(opcode) + } + } + + final override fun visitIntInsn( + opcode: Int, + operand: Int + ) { + if (emitCode) { + super.visitIntInsn(opcode, operand) + } + } + + final override fun visitVarInsn( + opcode: Int, + varIndex: Int + ) { + if (emitCode) { + super.visitVarInsn(opcode, varIndex) + } + } + + final override fun visitTypeInsn( + opcode: Int, + type: String? + ) { + if (emitCode) { + super.visitTypeInsn(opcode, type) + } + } + + final override fun visitFieldInsn( + opcode: Int, + owner: String?, + name: String?, + descriptor: String? + ) { + if (emitCode) { + super.visitFieldInsn(opcode, owner, name, descriptor) + } + } + + final override fun visitMethodInsn( + opcode: Int, + owner: String?, + name: String?, + descriptor: String?, + isInterface: Boolean + ) { + if (emitCode) { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) + } + } + + final override fun visitInvokeDynamicInsn( + name: String?, + descriptor: String?, + bootstrapMethodHandle: Handle?, + vararg bootstrapMethodArguments: Any? + ) { + if (emitCode) { + super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, + *bootstrapMethodArguments) + } + } + + final override fun visitJumpInsn( + opcode: Int, + label: Label? + ) { + if (emitCode) { + super.visitJumpInsn(opcode, label) + } + } + + final override fun visitLabel(label: Label?) { + if (emitCode) { + super.visitLabel(label) + } + } + + final override fun visitLdcInsn(value: Any?) { + if (emitCode) { + super.visitLdcInsn(value) + } + } + + final override fun visitIincInsn( + varIndex: Int, + increment: Int + ) { + if (emitCode) { + super.visitIincInsn(varIndex, increment) + } + } + + final override fun visitTableSwitchInsn( + min: Int, + max: Int, + dflt: Label?, + vararg labels: Label? + ) { + if (emitCode) { + super.visitTableSwitchInsn(min, max, dflt, *labels) + } + } + + final override fun visitLookupSwitchInsn( + dflt: Label?, + keys: IntArray?, + labels: Array<out Label>? + ) { + if (emitCode) { + super.visitLookupSwitchInsn(dflt, keys, labels) + } + } + + final override fun visitMultiANewArrayInsn( + descriptor: String?, + numDimensions: Int + ) { + if (emitCode) { + super.visitMultiANewArrayInsn(descriptor, numDimensions) + } + } + + final override fun visitInsnAnnotation( + typeRef: Int, + typePath: TypePath?, + descriptor: String?, + visible: Boolean + ): AnnotationVisitor? { + if (emitCode) { + return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible) + } + return null + } + + final override fun visitTryCatchBlock( + start: Label?, + end: Label?, + handler: Label?, + type: String? + ) { + if (emitCode) { + super.visitTryCatchBlock(start, end, handler, type) + } + } + + final override fun visitTryCatchAnnotation( + typeRef: Int, + typePath: TypePath?, + descriptor: String?, + visible: Boolean + ): AnnotationVisitor? { + if (emitCode) { + return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible) + } + return null + } + + final override fun visitLocalVariable( + name: String?, + descriptor: String?, + signature: String?, + start: Label?, + end: Label?, + index: Int + ) { + if (emitCode) { + super.visitLocalVariable(name, descriptor, signature, start, end, index) + } + } + + final override fun visitLocalVariableAnnotation( + typeRef: Int, + typePath: TypePath?, + start: Array<out Label>?, + end: Array<out Label>?, + index: IntArray?, + descriptor: String?, + visible: Boolean + ): AnnotationVisitor? { + if (emitCode) { + return super.visitLocalVariableAnnotation( + typeRef, typePath, start, end, index, descriptor, visible) + } + return null + } + + final override fun visitLineNumber( + line: Int, + start: Label? + ) { + if (emitCode) { + super.visitLineNumber(line, start) + } + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt new file mode 100644 index 000000000000..88db15b86143 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.visitors + +import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC +import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate +import com.android.hoststubgen.asm.prependArgTypeToMethodDescriptor +import com.android.hoststubgen.asm.writeByteCodeToPushArguments +import com.android.hoststubgen.asm.writeByteCodeToReturn +import com.android.hoststubgen.filters.FilterPolicy +import com.android.hoststubgen.filters.FilterPolicyWithReason +import com.android.hoststubgen.filters.OutputFilter +import com.android.hoststubgen.hosthelper.HostTestUtils +import com.android.hoststubgen.log +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.MethodVisitor +import org.objectweb.asm.Opcodes +import org.objectweb.asm.Type + +/** + * An adapter that generates the "impl" class file from an input class file. + */ +class ImplGeneratingAdapter( + classes: ClassNodes, + nextVisitor: ClassVisitor, + filter: OutputFilter, + options: Options, +) : BaseAdapter(classes, nextVisitor, filter, options) { + + override fun shouldEmit(policy: FilterPolicy): Boolean { + return policy.needsInImpl + } + + private var classLoadHooks: List<String> = emptyList() + + override fun visit( + version: Int, + access: Int, + name: String, + signature: String?, + superName: String?, + interfaces: Array<String> + ) { + super.visit(version, access, name, signature, superName, interfaces) + + classLoadHooks = filter.getClassLoadHooks(currentClassName) + + // classLoadHookMethod is non-null, then we need to inject code to call it + // in the class initializer. + // If the target class already has a class initializer, then we need to inject code to it. + // Otherwise, we need to create one. + + if (classLoadHooks.isNotEmpty()) { + log.d(" ClassLoadHooks: $classLoadHooks") + if (!classes.hasClassInitializer(currentClassName)) { + injectClassLoadHook() + } + } + } + + private fun injectClassLoadHook() { + writeRawMembers { + // Create a class initializer to call onClassLoaded(). + // Each class can only have at most one class initializer, but the base class + // StaticInitMerger will merge it with the existing one, if any. + visitMethod( + Opcodes.ACC_PRIVATE or Opcodes.ACC_STATIC, + CLASS_INITIALIZER_NAME, + "()V", + null, + null + )!!.let { mv -> + // Method prologue + mv.visitCode() + + writeClassLoadHookCalls(mv) + mv.visitInsn(Opcodes.RETURN) + + // Method epilogue + mv.visitMaxs(0, 0) + mv.visitEnd() + } + } + } + + private fun writeClassLoadHookCalls(mv: MethodVisitor) { + classLoadHooks.forEach { classLoadHook -> + // First argument: the class type. + mv.visitLdcInsn(Type.getType("L" + currentClassName + ";")) + + // Second argument: method name + mv.visitLdcInsn(classLoadHook) + + // Call HostTestUtils.onClassLoaded(). + mv.visitMethodInsn( + Opcodes.INVOKESTATIC, + HostTestUtils.CLASS_INTERNAL_NAME, + "onClassLoaded", + "(Ljava/lang/Class;Ljava/lang/String;)V", + false + ) + } + } + + override fun updateAccessFlags( + access: Int, + name: String, + descriptor: String, + ): Int { + if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) { + return access and Opcodes.ACC_NATIVE.inv() + } + return access + } + + override fun visitMethodInner( + access: Int, + name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + policy: FilterPolicyWithReason, + superVisitor: MethodVisitor?, + ): MethodVisitor? { + // Inject method log, if needed. + var innerVisitor = superVisitor + + // If method logging is enabled, inject call to the logging method. + val methodCallHooks = filter.getMethodCallHooks(currentClassName, name, descriptor) + if (methodCallHooks.isNotEmpty()) { + innerVisitor = MethodCallHookInjectingAdapter( + access, + name, + descriptor, + signature, + exceptions, + innerVisitor, + methodCallHooks, + ) + } + + // If this class already has a class initializer and a class load hook is needed, then + // we inject code. + if (classLoadHooks.isNotEmpty() && + name == CLASS_INITIALIZER_NAME && + descriptor == CLASS_INITIALIZER_DESC) { + innerVisitor = ClassLoadHookInjectingMethodAdapter( + access, + name, + descriptor, + signature, + exceptions, + innerVisitor, + ) + } + + // If non-stub method call detection is enabled, then inject a call to the checker. + if (options.enableNonStubMethodCallDetection && doesMethodNeedNonStubCallCheck( + access, name, descriptor, policy) ) { + innerVisitor = NonStubMethodCallDetectingAdapter( + access, + name, + descriptor, + signature, + exceptions, + innerVisitor, + ) + } + + log.withIndent { + if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) { + log.v("Rewriting native method...") + return NativeSubstitutingMethodAdapter( + access, name, descriptor, signature, exceptions, innerVisitor) + } + if (policy.policy == FilterPolicy.Throw) { + log.v("Making method throw...") + return ThrowingMethodAdapter( + access, name, descriptor, signature, exceptions, innerVisitor) + } + if (policy.policy == FilterPolicy.Ignore) { + when (Type.getReturnType(descriptor)) { + Type.VOID_TYPE -> { + log.v("Making method ignored...") + return IgnoreMethodAdapter( + access, name, descriptor, signature, exceptions, innerVisitor) + } + else -> { + throw RuntimeException("Ignored policy only allowed for void methods") + } + } + } + } + + return innerVisitor + } + + fun doesMethodNeedNonStubCallCheck( + access: Int, + name: String, + descriptor: String, + policy: FilterPolicyWithReason, + ): Boolean { + // If a method is in the stub, then no need to check. + if (policy.policy.needsInStub) { + return false + } + // If a method is private or package-private, no need to check. + // Technically test code can use framework package name, so it's a bit too lenient. + if (isVisibilityPrivateOrPackagePrivate(access)) { + return false + } + // TODO: If the method overrides a method that's accessible by tests, then we shouldn't + // do the check. (e.g. overrides a stub method or java standard method.) + + return true + } + + /** + * A method adapter that replaces the method body with a HostTestUtils.onThrowMethodCalled() + * call. + */ + private inner class ThrowingMethodAdapter( + access: Int, + val name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor? + ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) { + override fun emitNewCode() { + visitMethodInsn(Opcodes.INVOKESTATIC, + HostTestUtils.CLASS_INTERNAL_NAME, + "onThrowMethodCalled", + "()V", + false) + + // We still need a RETURN opcode for the return type. + // For now, let's just inject a `throw`. + visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException") + visitInsn(Opcodes.DUP) + visitLdcInsn("Unreachable") + visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException", + "<init>", "(Ljava/lang/String;)V", false) + visitInsn(Opcodes.ATHROW) + + // visitMaxs(3, if (isStatic) 0 else 1) + visitMaxs(0, 0) // We let ASM figure them out. + } + } + + /** + * A method adapter that replaces the method body with a no-op return. + */ + private inner class IgnoreMethodAdapter( + access: Int, + val name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor? + ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) { + override fun emitNewCode() { + visitInsn(Opcodes.RETURN) + visitMaxs(0, 0) // We let ASM figure them out. + } + } + + /** + * A method adapter that replaces a native method call with a call to the "native substitution" + * class. + */ + private inner class NativeSubstitutingMethodAdapter( + val access: Int, + private val name: String, + private val descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor? + ) : MethodVisitor(OPCODE_VERSION, next) { + override fun visitCode() { + super.visitCode() + + throw RuntimeException("NativeSubstitutingMethodVisitor should be called on " + + " native method, where visitCode() shouldn't be called.") + } + + override fun visitEnd() { + var targetDescriptor = descriptor + var argOffset = 0 + + // For non-static native method, we need to tweak it a bit. + if ((access and Opcodes.ACC_STATIC) == 0) { + // Push `this` as the first argument. + this.visitVarInsn(Opcodes.ALOAD, 0) + + // Update the descriptor -- add this class's type as the first argument + // to the method descriptor. + val thisType = Type.getType("L" + currentClassName + ";") + + targetDescriptor = prependArgTypeToMethodDescriptor( + descriptor, + thisType, + ) + + // Shift the original arguments by one. + argOffset = 1 + } + + writeByteCodeToPushArguments(descriptor, this, argOffset) + + visitMethodInsn(Opcodes.INVOKESTATIC, + nativeSubstitutionClass, + name, + targetDescriptor, + false) + + writeByteCodeToReturn(descriptor, this) + + visitMaxs(99, 0) // We let ASM figure them out. + super.visitEnd() + } + } + + /** + * Inject calls to the method call hooks. + * + * Note, when the target method is a constructor, it may contain calls to `super(...)` or + * `this(...)`. The logging code will be injected *before* such calls. + */ + private inner class MethodCallHookInjectingAdapter( + access: Int, + val name: String, + val descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor?, + val hooks: List<String>, + ) : MethodVisitor(OPCODE_VERSION, next) { + override fun visitCode() { + super.visitCode() + + hooks.forEach { hook -> + mv.visitLdcInsn(Type.getType("L" + currentClassName + ";")) + visitLdcInsn(name) + visitLdcInsn(descriptor) + visitLdcInsn(hook) + + visitMethodInsn( + Opcodes.INVOKESTATIC, + HostTestUtils.CLASS_INTERNAL_NAME, + "callMethodCallHook", + "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", + false + ) + } + } + } + + /** + * Inject a class load hook call. + */ + private inner class ClassLoadHookInjectingMethodAdapter( + access: Int, + val name: String, + val descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor? + ) : MethodVisitor(OPCODE_VERSION, next) { + override fun visitCode() { + super.visitCode() + + writeClassLoadHookCalls(this) + } + } + + /** + * A method adapter that detects calls to non-stub methods. + */ + private inner class NonStubMethodCallDetectingAdapter( + access: Int, + val name: String, + val descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor? + ) : MethodVisitor(OPCODE_VERSION, next) { + override fun visitCode() { + super.visitCode() + + // First three arguments to HostTestUtils.onNonStubMethodCalled(). + visitLdcInsn(currentClassName) + visitLdcInsn(name) + visitLdcInsn(descriptor) + + // Call: HostTestUtils.getStackWalker().getCallerClass(). + // This push the caller Class in the stack. + visitMethodInsn(Opcodes.INVOKESTATIC, + HostTestUtils.CLASS_INTERNAL_NAME, + "getStackWalker", + "()Ljava/lang/StackWalker;", + false) + visitMethodInsn(Opcodes.INVOKEVIRTUAL, + "java/lang/StackWalker", + "getCallerClass", + "()Ljava/lang/Class;", + false) + + // Then call onNonStubMethodCalled(). + visitMethodInsn(Opcodes.INVOKESTATIC, + HostTestUtils.CLASS_INTERNAL_NAME, + "onNonStubMethodCalled", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V", + false) + } + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/PackageRedirectRemapper.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/PackageRedirectRemapper.kt new file mode 100644 index 000000000000..b3790e12a111 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/PackageRedirectRemapper.kt @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.visitors + +import com.android.hoststubgen.asm.toJvmClassName +import org.objectweb.asm.commons.Remapper + +/** + * A [Remapper] for `--package-redirect` + */ +class PackageRedirectRemapper( + packageRedirects: List<Pair<String, String>>, + ) : Remapper() { + + /** + * Example: `dalvik/` -> `com/android/hostsubgen/substitution/dalvik/` + */ + private val packageRedirectsWithSlash: List<Pair<String, String>> = packageRedirects.map { + p -> Pair(p.first.toJvmClassName() + "/", p.second.toJvmClassName() + "/") + } + + /** + * Cache. + * If a class is a redirect-from class, then the "to" class name will be stored as the value. + * Otherwise, "" will be stored. + */ + private val cache = mutableMapOf<String, String>() + + /** + * Return whether any redirect is defined. + */ + val isEmpty get() = packageRedirectsWithSlash.isEmpty() + + override fun map(internalName: String?): String? { + if (internalName == null) { + return null + } + val to = mapInner(internalName) + return to ?: internalName + } + + /** + * Internal "map" function. Unlike [map(String)], this method will return null + * if a class is not a redirect-from class. + */ + private fun mapInner(internalName: String): String? { + cache[internalName]?.let { + return if (it.isEmpty()) null else it + } + + var ret = "" + packageRedirectsWithSlash.forEach { fromTo -> + if (internalName.startsWith(fromTo.first)) { + ret = fromTo.second + internalName.substring(fromTo.first.length) + } + } + cache.set(internalName, ret) + + return if (ret.isEmpty()) null else ret + } + + /** + * Return true if a class is a redirect-from class. + */ + fun isTarget(internalName: String): Boolean { + return mapInner(internalName) != null + } +} + diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt new file mode 100644 index 000000000000..37e2a888969d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.visitors + +import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.filters.FilterPolicy +import com.android.hoststubgen.filters.FilterPolicyWithReason +import com.android.hoststubgen.filters.OutputFilter +import com.android.hoststubgen.log +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.MethodVisitor +import org.objectweb.asm.Opcodes + +/** + * An adapter that generates the "impl" class file from an input class file. + */ +class StubGeneratingAdapter( + classes: ClassNodes, + nextVisitor: ClassVisitor, + filter: OutputFilter, + options: Options, +) : BaseAdapter(classes, nextVisitor, filter, options) { + + override fun shouldEmit(policy: FilterPolicy): Boolean { + return policy.needsInStub + } + + override fun visitMethodInner( + access: Int, + name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + policy: FilterPolicyWithReason, + superVisitor: MethodVisitor?, + ): MethodVisitor? { + return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor) + } + + private inner class StubMethodVisitor( + access: Int, + val name: String, + descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor? + ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) { + override fun emitNewCode() { + log.d(" Generating stub method for $currentClassName.$name") + + // Inject the following code: + // throw new RuntimeException("Stub!"); + + /* + NEW java/lang/RuntimeException + DUP + LDC "not supported on host side" + INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V + ATHROW + MAXSTACK = 3 + MAXLOCALS = 2 <- 1 for this, 1 for return value. + */ + visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException") + visitInsn(Opcodes.DUP) + visitLdcInsn("Stub!") + visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException", + "<init>", "(Ljava/lang/String;)V", false) + visitInsn(Opcodes.ATHROW) + visitMaxs(0, 0) // We let ASM figure them out. + } + } +} diff --git a/tools/hoststubgen/hoststubgen/test-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-framework/Android.bp new file mode 100644 index 000000000000..2b91cc161b7f --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-framework/Android.bp @@ -0,0 +1,19 @@ +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +build = ["AndroidHostTest.bp"] diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp new file mode 100644 index 000000000000..1f8382ad468d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp @@ -0,0 +1,57 @@ +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Add `build = ["AndroidHostTest.bp"]` to Android.bp to include this file. + +// Compile the test jar, using 2 rules. +// 1. Build the test against the stub. +java_library_host { + name: "HostStubGenTest-framework-test-host-test-lib", + defaults: ["hosttest-with-framework-all-hidden-api-test-lib-defaults"], + srcs: [ + "src/**/*.java", + ], + static_libs: [ + "junit", + "truth", + "mockito", + + // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/ + "platform-test-annotations", + "hoststubgen-annotations", + ], +} + +// 2. Link the above module with necessary runtime dependencies, so it can be executed stand-alone. +java_test_host { + name: "HostStubGenTest-framework-all-test-host-test", + defaults: ["hosttest-with-framework-all-hidden-api-test-defaults"], + static_libs: [ + "HostStubGenTest-framework-test-host-test-lib", + ], + test_suites: ["general-tests"], +} + +// "Productionized" build rule. +android_ravenwood_test { + name: "HostStubGenTest-framework-test", + srcs: [ + "src/**/*.java", + ], + static_libs: [ + "junit", + "truth", + "mockito", + ], +} diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml new file mode 100644 index 000000000000..f35dcf69ecc9 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml --> +<configuration description="CtsContentTestCases host-side test"> + <option name="test-suite-tag" value="ravenwood" /> + <option name="config-descriptor:metadata" key="component" value="framework" /> + <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" /> + <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> + <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" /> + <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" /> + + <test class="com.android.tradefed.testtype.IsolatedHostTest" > + <option name="jar" value="HostStubGenTest-framework-all-test-host-test.jar" /> + </test> +</configuration> diff --git a/tools/hoststubgen/hoststubgen/test-framework/README.md b/tools/hoststubgen/hoststubgen/test-framework/README.md new file mode 100644 index 000000000000..f616ad61d219 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-framework/README.md @@ -0,0 +1,21 @@ +# HostStubGen: real framework test + +This directory contains tests against the actual framework.jar code. The tests were +copied from somewhere else in the android tree. We use this directory to quickly run existing +tests. + +## How to run + +- With `atest`. This is the proper way to run it, but it may fail due to atest's known problems. + + See the top level README.md on why `--no-bazel-mode` is needed (for now). + +``` +$ atest --no-bazel-mode HostStubGenTest-framework-test-host-test +``` + +- Advanced option: `run-test-without-atest.sh` runs the test without using `atest` or `run-ravenwood-test` + +``` +$ ./run-test-without-atest.sh +```
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh new file mode 100755 index 000000000000..cfc06a12e881 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Run HostStubGenTest-framework-test-host-test directly with JUnit. +# (without using atest.) + +source "${0%/*}"/../../common.sh + + +# Options: +# -v enable verbose log +# -d enable debugger + +verbose=0 +debug=0 +while getopts "vd" opt; do + case "$opt" in + v) verbose=1 ;; + d) debug=1 ;; + esac +done +shift $(($OPTIND - 1)) + + +if (( $verbose )) ; then + JAVA_OPTS="$JAVA_OPTS -verbose:class" +fi + +if (( $debug )) ; then + JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700" +fi + +#======================================= +module=HostStubGenTest-framework-all-test-host-test +module_jar=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/$module/$module.jar +run m $module + +out=out + +rm -fr $out +mkdir -p $out + + +# Copy and extract the relevant jar files so we can look into them. +run cp \ + $module_jar \ + $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/*.jar \ + $out + +run extract $out/*.jar + +# Result is the number of failed tests. +result=0 + + +# This suite runs all tests in the JAR. +tests=(com.android.hoststubgen.hosthelper.HostTestSuite) + +# Uncomment this to run a specific test. +# tests=(com.android.hoststubgen.frameworktest.LogTest) + + +for class in ${tests[@]} ; do + echo "Running $class ..." + + run cd "${module_jar%/*}" + run $JAVA $JAVA_OPTS \ + -cp $module_jar \ + org.junit.runner.JUnitCore \ + $class || result=$(( $result + 1 )) +done + +exit $result diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java new file mode 100644 index 000000000000..2c5949c1c630 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.frameworktest; + +// [ravewnwood] Copied from cts/, and commented out unsupported stuff. + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import android.util.ArrayMap; +import android.util.Log; + +import org.junit.Test; + +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.BiFunction; + +/** + * Some basic tests for {@link android.util.ArrayMap}. + */ +public class ArrayMapTest { + static final boolean DEBUG = false; + + private static boolean compare(Object v1, Object v2) { + if (v1 == null) { + return v2 == null; + } + if (v2 == null) { + return false; + } + return v1.equals(v2); + } + + private static void compareMaps(HashMap map, ArrayMap array) { + if (map.size() != array.size()) { + fail("Bad size: expected " + map.size() + ", got " + array.size()); + } + + Set<Entry> mapSet = map.entrySet(); + for (Map.Entry entry : mapSet) { + Object expValue = entry.getValue(); + Object gotValue = array.get(entry.getKey()); + if (!compare(expValue, gotValue)) { + fail("Bad value: expected " + expValue + ", got " + gotValue + + " at key " + entry.getKey()); + } + } + + for (int i = 0; i < array.size(); i++) { + Object gotValue = array.valueAt(i); + Object key = array.keyAt(i); + Object expValue = map.get(key); + if (!compare(expValue, gotValue)) { + fail("Bad value: expected " + expValue + ", got " + gotValue + + " at key " + key); + } + } + + if (map.entrySet().hashCode() != array.entrySet().hashCode()) { + fail("Entry set hash codes differ: map=0x" + + Integer.toHexString(map.entrySet().hashCode()) + " array=0x" + + Integer.toHexString(array.entrySet().hashCode())); + } + + if (!map.entrySet().equals(array.entrySet())) { + fail("Failed calling equals on map entry set against array set"); + } + + if (!array.entrySet().equals(map.entrySet())) { + fail("Failed calling equals on array entry set against map set"); + } + + if (map.keySet().hashCode() != array.keySet().hashCode()) { + fail("Key set hash codes differ: map=0x" + + Integer.toHexString(map.keySet().hashCode()) + " array=0x" + + Integer.toHexString(array.keySet().hashCode())); + } + + if (!map.keySet().equals(array.keySet())) { + fail("Failed calling equals on map key set against array set"); + } + + if (!array.keySet().equals(map.keySet())) { + fail("Failed calling equals on array key set against map set"); + } + + if (!map.keySet().containsAll(array.keySet())) { + fail("Failed map key set contains all of array key set"); + } + + if (!array.keySet().containsAll(map.keySet())) { + fail("Failed array key set contains all of map key set"); + } + + if (!array.containsAll(map.keySet())) { + fail("Failed array contains all of map key set"); + } + + if (!map.entrySet().containsAll(array.entrySet())) { + fail("Failed map entry set contains all of array entry set"); + } + + if (!array.entrySet().containsAll(map.entrySet())) { + fail("Failed array entry set contains all of map entry set"); + } + } + + private static void validateArrayMap(ArrayMap array) { + Set<Map.Entry> entrySet = array.entrySet(); + int index = 0; + Iterator<Entry> entryIt = entrySet.iterator(); + while (entryIt.hasNext()) { + Map.Entry entry = entryIt.next(); + Object value = entry.getKey(); + Object realValue = array.keyAt(index); + if (!compare(realValue, value)) { + fail("Bad array map entry set: expected key " + realValue + + ", got " + value + " at index " + index); + } + value = entry.getValue(); + realValue = array.valueAt(index); + if (!compare(realValue, value)) { + fail("Bad array map entry set: expected value " + realValue + + ", got " + value + " at index " + index); + } + index++; + } + + index = 0; + Set keySet = array.keySet(); + Iterator keyIt = keySet.iterator(); + while (keyIt.hasNext()) { + Object value = keyIt.next(); + Object realValue = array.keyAt(index); + if (!compare(realValue, value)) { + fail("Bad array map key set: expected key " + realValue + + ", got " + value + " at index " + index); + } + index++; + } + + index = 0; + Collection valueCol = array.values(); + Iterator valueIt = valueCol.iterator(); + while (valueIt.hasNext()) { + Object value = valueIt.next(); + Object realValue = array.valueAt(index); + if (!compare(realValue, value)) { + fail("Bad array map value col: expected value " + realValue + + ", got " + value + " at index " + index); + } + index++; + } + } + + private static void dump(Map map, ArrayMap array) { + Log.e("test", "HashMap of " + map.size() + " entries:"); + Set<Map.Entry> mapSet = map.entrySet(); + for (Map.Entry entry : mapSet) { + Log.e("test", " " + entry.getKey() + " -> " + entry.getValue()); + } + Log.e("test", "ArrayMap of " + array.size() + " entries:"); + for (int i = 0; i < array.size(); i++) { + Log.e("test", " " + array.keyAt(i) + " -> " + array.valueAt(i)); + } + } + + private static void dump(ArrayMap map1, ArrayMap map2) { + Log.e("test", "ArrayMap of " + map1.size() + " entries:"); + for (int i = 0; i < map1.size(); i++) { + Log.e("test", " " + map1.keyAt(i) + " -> " + map1.valueAt(i)); + } + Log.e("test", "ArrayMap of " + map2.size() + " entries:"); + for (int i = 0; i < map2.size(); i++) { + Log.e("test", " " + map2.keyAt(i) + " -> " + map2.valueAt(i)); + } + } + + @Test + public void testCopyArrayMap() { + // map copy constructor test + ArrayMap newMap = new ArrayMap<Integer, String>(); + for (int i = 0; i < 10; ++i) { + newMap.put(i, String.valueOf(i)); + } + ArrayMap mapCopy = new ArrayMap(newMap); + if (!compare(mapCopy, newMap)) { + String msg = "ArrayMap copy constructor failure: expected " + + newMap + ", got " + mapCopy; + Log.e("test", msg); + dump(newMap, mapCopy); + fail(msg); + return; + } + } + + @Test + public void testEqualsArrayMap() { + ArrayMap<Integer, String> map1 = new ArrayMap<>(); + ArrayMap<Integer, String> map2 = new ArrayMap<>(); + HashMap<Integer, String> map3 = new HashMap<>(); + if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) { + fail("ArrayMap equals failure for empty maps " + map1 + ", " + + map2 + ", " + map3); + } + + for (int i = 0; i < 10; ++i) { + String value = String.valueOf(i); + map1.put(i, value); + map2.put(i, value); + map3.put(i, value); + } + if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) { + fail("ArrayMap equals failure for populated maps " + map1 + ", " + + map2 + ", " + map3); + } + + map1.remove(0); + if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) { + fail("ArrayMap equals failure for map size " + map1 + ", " + + map2 + ", " + map3); + } + + map1.put(0, "-1"); + if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) { + fail("ArrayMap equals failure for map contents " + map1 + ", " + + map2 + ", " + map3); + } + } + + private static void checkEntrySetToArray(ArrayMap<?, ?> testMap) { + try { + testMap.entrySet().toArray(); + fail(); + } catch (UnsupportedOperationException expected) { + } + + try { + Map.Entry<?, ?>[] entries = new Map.Entry[20]; + testMap.entrySet().toArray(entries); + fail(); + } catch (UnsupportedOperationException expected) { + } + } + + // http://b/32294038, Test ArrayMap.entrySet().toArray() + @Test + public void testEntrySetArray() { + // Create + ArrayMap<Integer, String> testMap = new ArrayMap<>(); + + // Test empty + checkEntrySetToArray(testMap); + + // Test non-empty + for (int i = 0; i < 10; ++i) { + testMap.put(i, String.valueOf(i)); + } + checkEntrySetToArray(testMap); + } + + @Test + public void testCanNotIteratePastEnd_entrySetIterator() { + Map<String, String> map = new ArrayMap<>(); + map.put("key 1", "value 1"); + map.put("key 2", "value 2"); + Set<Map.Entry<String, String>> expectedEntriesToIterate = new HashSet<>(Arrays.asList( + entryOf("key 1", "value 1"), + entryOf("key 2", "value 2") + )); + Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); + + // Assert iteration over the expected two entries in any order + assertTrue(iterator.hasNext()); + Map.Entry<String, String> firstEntry = copyOf(iterator.next()); + assertTrue(expectedEntriesToIterate.remove(firstEntry)); + + assertTrue(iterator.hasNext()); + Map.Entry<String, String> secondEntry = copyOf(iterator.next()); + assertTrue(expectedEntriesToIterate.remove(secondEntry)); + + assertFalse(iterator.hasNext()); + + try { + iterator.next(); + fail(); + } catch (NoSuchElementException expected) { + } + } + + private static <K, V> Map.Entry<K, V> entryOf(K key, V value) { + return new AbstractMap.SimpleEntry<>(key, value); + } + + private static <K, V> Map.Entry<K, V> copyOf(Map.Entry<K, V> entry) { + return entryOf(entry.getKey(), entry.getValue()); + } + + @Test + public void testCanNotIteratePastEnd_keySetIterator() { + Map<String, String> map = new ArrayMap<>(); + map.put("key 1", "value 1"); + map.put("key 2", "value 2"); + Set<String> expectedKeysToIterate = new HashSet<>(Arrays.asList("key 1", "key 2")); + Iterator<String> iterator = map.keySet().iterator(); + + // Assert iteration over the expected two keys in any order + assertTrue(iterator.hasNext()); + String firstKey = iterator.next(); + assertTrue(expectedKeysToIterate.remove(firstKey)); + + assertTrue(iterator.hasNext()); + String secondKey = iterator.next(); + assertTrue(expectedKeysToIterate.remove(secondKey)); + + assertFalse(iterator.hasNext()); + + try { + iterator.next(); + fail(); + } catch (NoSuchElementException expected) { + } + } + + @Test + public void testCanNotIteratePastEnd_valuesIterator() { + Map<String, String> map = new ArrayMap<>(); + map.put("key 1", "value 1"); + map.put("key 2", "value 2"); + Set<String> expectedValuesToIterate = new HashSet<>(Arrays.asList("value 1", "value 2")); + Iterator<String> iterator = map.values().iterator(); + + // Assert iteration over the expected two values in any order + assertTrue(iterator.hasNext()); + String firstValue = iterator.next(); + assertTrue(expectedValuesToIterate.remove(firstValue)); + + assertTrue(iterator.hasNext()); + String secondValue = iterator.next(); + assertTrue(expectedValuesToIterate.remove(secondValue)); + + assertFalse(iterator.hasNext()); + + try { + iterator.next(); + fail(); + } catch (NoSuchElementException expected) { + } + } + + @Test + public void testForEach() { + ArrayMap<String, Integer> map = new ArrayMap<>(); + + for (int i = 0; i < 50; ++i) { + map.put(Integer.toString(i), i * 10); + } + + // Make sure forEach goes through all of the elements. + HashMap<String, Integer> seen = new HashMap<>(); + map.forEach(seen::put); + compareMaps(seen, map); + } + + /** + * The entrySet Iterator returns itself from each call to {@code next()}. This is unusual + * behavior for {@link Iterator#next()}; this test ensures that any future change to this + * behavior is deliberate. + */ + @Test + public void testUnusualBehavior_eachEntryIsSameAsIterator_entrySetIterator() { + Map<String, String> map = new ArrayMap<>(); + map.put("key 1", "value 1"); + map.put("key 2", "value 2"); + Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); + + assertSame(iterator, iterator.next()); + assertSame(iterator, iterator.next()); + } + + @SuppressWarnings("SelfEquals") + @Test + public void testUnusualBehavior_equalsThrowsAfterRemove_entrySetIterator() { + Map<String, String> map = new ArrayMap<>(); + map.put("key 1", "value 1"); + map.put("key 2", "value 2"); + Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); + iterator.next(); + iterator.remove(); + try { + iterator.equals(iterator); + fail(); + } catch (IllegalStateException expected) { + } + } + + private static <T> void assertEqualsBothWays(T a, T b) { + assertEquals(a, b); + assertEquals(b, a); + assertEquals(a.hashCode(), b.hashCode()); + } + + @Test + public void testRemoveAll() { + final ArrayMap<Integer, String> map = new ArrayMap<>(); + for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) { + map.put(i, i.toString()); + } + + final ArrayMap<Integer, String> expectedMap = new ArrayMap<>(); + for (Integer i : Arrays.asList(2, 4)) { + expectedMap.put(i, String.valueOf(i)); + } + map.removeAll(Arrays.asList(0, 1, 3, 5, 6)); + if (!compare(map, expectedMap)) { + fail("ArrayMap removeAll failure, expect " + expectedMap + ", but " + map); + } + + map.removeAll(Collections.emptyList()); + if (!compare(map, expectedMap)) { + fail("ArrayMap removeAll failure for empty maps, expect " + expectedMap + ", but " + + map); + } + + map.removeAll(Arrays.asList(2, 4)); + if (!map.isEmpty()) { + fail("ArrayMap removeAll failure, expect empty, but " + map); + } + } + + @Test + public void testReplaceAll() { + final ArrayMap<Integer, Integer> map = new ArrayMap<>(); + final ArrayMap<Integer, Integer> expectedMap = new ArrayMap<>(); + final BiFunction<Integer, Integer, Integer> function = (k, v) -> 2 * v; + for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) { + map.put(i, i); + expectedMap.put(i, 2 * i); + } + + map.replaceAll(function); + if (!compare(map, expectedMap)) { + fail("ArrayMap replaceAll failure, expect " + expectedMap + ", but " + map); + } + } +} diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java new file mode 100644 index 000000000000..3e33b54bb9f9 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.frameworktest; + +import static com.google.common.truth.Truth.assertThat; + +import android.util.Log; + +import org.junit.Test; + +/** + * Some basic tests for {@link android.util.Log}. + */ +public class LogTest { + @Test + public void testBasicLogging() { + Log.v("TAG", "Test v log"); + Log.d("TAG", "Test d log"); + Log.i("TAG", "Test i log"); + Log.w("TAG", "Test w log"); + Log.e("TAG", "Test e log"); + } + + @Test + public void testNativeMethods() { + assertThat(Log.isLoggable("mytag", Log.INFO)).isTrue(); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp new file mode 100644 index 000000000000..e7873d6eecc3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp @@ -0,0 +1,216 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +// A library that simulates framework-all.jar +java_library { + name: "hoststubgen-test-tiny-framework", + installable: true, + host_supported: true, + srcs: ["tiny-framework/src/**/*.java"], + static_libs: [ + "hoststubgen-annotations", + ], + visibility: ["//frameworks/base/tools/hoststubgen:__subpackages__"], +} + +// Create stub/impl jars from "hoststubgen-test-tiny-framework", using the following 3 rules. +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host", + defaults: ["hoststubgen-command-defaults"], + cmd: hoststubgen_common_options + + "--in-jar $(location :hoststubgen-test-tiny-framework) " + + "--policy-override-file $(location policy-override-tiny-framework.txt) " + + "--package-redirect com.unsupported:com.supported ", + srcs: [ + ":hoststubgen-test-tiny-framework", + "policy-override-tiny-framework.txt", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-stub", + cmd: "cp $(in) $(out)", + srcs: [ + ":hoststubgen-test-tiny-framework-host{host_stub.jar}", + ], + out: [ + "host_stub.jar", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-impl", + cmd: "cp $(in) $(out)", + srcs: [ + ":hoststubgen-test-tiny-framework-host{host_impl.jar}", + ], + out: [ + "host_impl.jar", + ], + visibility: ["//visibility:private"], +} + +// Same as "hoststubgen-test-tiny-framework-host", but with more options, to test more hoststubgen +// features. +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-ext", + defaults: ["hoststubgen-command-defaults"], + cmd: hoststubgen_common_options + + "--in-jar $(location :hoststubgen-test-tiny-framework) " + + "--policy-override-file $(location policy-override-tiny-framework.txt) " + + "--package-redirect com.unsupported:com.supported " + + + // More options. + "--default-method-call-hook com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall " + + "--default-class-load-hook com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded ", + srcs: [ + ":hoststubgen-test-tiny-framework", + "policy-override-tiny-framework.txt", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-ext-stub", + cmd: "cp $(in) $(out)", + srcs: [ + ":hoststubgen-test-tiny-framework-host-ext{host_stub.jar}", + ], + out: [ + "host_stub.jar", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-ext-impl", + cmd: "cp $(in) $(out)", + srcs: [ + ":hoststubgen-test-tiny-framework-host-ext{host_impl.jar}", + ], + out: [ + "host_impl.jar", + ], + visibility: ["//visibility:private"], +} + +// Compile the test jar, using 2 rules. +// 1. Build the test against the stub. +java_library_host { + name: "hoststubgen-test-tiny-test-lib", + srcs: ["tiny-test/src/**/*.java"], + + libs: [ + "hoststubgen-test-tiny-framework-host-stub", + ], + static_libs: [ + "junit", + "truth", + + // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/ + "platform-test-annotations", + ], + visibility: ["//visibility:private"], +} + +// 2. Link "hoststubgen-test-tiny-test-lib" with necessary runtime dependencies, so it can be +// executed stand-alone. +java_test_host { + name: "hoststubgen-test-tiny-test", + test_config: "AndroidTest-host.xml", + static_libs: [ + "hoststubgen-test-tiny-test-lib", + "hoststubgen-helper-runtime", + "hoststubgen-test-tiny-framework-host-impl", + ], + test_suites: ["general-tests"], +} + +// Dump the original, stub and impl jars as text files. +// We use them in test-and-update-golden.sh. +java_genrule_host { + name: "hoststubgen-test-tiny-framework-orig-dump", + defaults: ["hoststubgen-jar-dump-defaults"], + srcs: [ + ":hoststubgen-test-tiny-framework", + ], + out: [ + "01-hoststubgen-test-tiny-framework-orig-dump.txt", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-stub-dump", + defaults: ["hoststubgen-jar-dump-defaults"], + srcs: [ + ":hoststubgen-test-tiny-framework-host-stub", + ], + out: [ + "02-hoststubgen-test-tiny-framework-host-stub-dump.txt", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-impl-dump", + defaults: ["hoststubgen-jar-dump-defaults"], + srcs: [ + ":hoststubgen-test-tiny-framework-host-impl", + ], + out: [ + "03-hoststubgen-test-tiny-framework-host-impl-dump.txt", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-ext-stub-dump", + defaults: ["hoststubgen-jar-dump-defaults"], + srcs: [ + ":hoststubgen-test-tiny-framework-host-ext-stub", + ], + out: [ + "12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt", + ], + visibility: ["//visibility:private"], +} + +java_genrule_host { + name: "hoststubgen-test-tiny-framework-host-ext-impl-dump", + defaults: ["hoststubgen-jar-dump-defaults"], + srcs: [ + ":hoststubgen-test-tiny-framework-host-ext-impl", + ], + out: [ + "13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt", + ], + visibility: ["//visibility:private"], +} + +// Run it with `atest`. Compare the dump of the jar files to the golden output. +python_test_host { + name: "tiny-framework-dump-test", + srcs: [ + "tiny-framework-dump-test.py", + ], + data: [ + "golden-output/*.txt", + ], + java_data: [ + "hoststubgen-test-tiny-framework-host-stub-dump", + "hoststubgen-test-tiny-framework-host-impl-dump", + "hoststubgen-test-tiny-framework-orig-dump", + "hoststubgen-test-tiny-framework-host-ext-stub-dump", + "hoststubgen-test-tiny-framework-host-ext-impl-dump", + ], + test_suites: ["general-tests"], +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml new file mode 100644 index 000000000000..84aad69c33bc --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml --> +<configuration description="HostStubGen sample test"> + <option name="test-suite-tag" value="ravenwood" /> + <option name="config-descriptor:metadata" key="component" value="framework" /> + <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" /> + <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> + <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" /> + <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" /> + + <test class="com.android.tradefed.testtype.IsolatedHostTest" > + <option name="jar" value="hoststubgen-test-tiny-test.jar" /> + </test> +</configuration> diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md new file mode 100644 index 000000000000..3bfad9bd673b --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md @@ -0,0 +1,21 @@ +# HostStubGen: tiny-framework test + +This directory contains a small classes that "simulates" framework.jar, and tests against it. + +This test doesn't use the actual android framework code. + +## How to run + +- With `atest`. This is the proper way to run it, but `atest` has known problems that may + affect the result. If you see weird problems, try the next `run-ravenwood-test` command. + +``` +$ atest hoststubgen-test-tiny-test +``` + +- `run-test-manually.sh` also run the test, but it builds the stub/impl jars and the test without + using the build system. This is useful for debugging the tool. + +``` +$ ./run-test-manually.sh +```
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/annotation-allowed-classes-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/annotation-allowed-classes-tiny-framework.txt new file mode 100644 index 000000000000..bd9e85e17890 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/annotation-allowed-classes-tiny-framework.txt @@ -0,0 +1,29 @@ +# Only classes listed here can use the hoststubgen annotations. + +# For each class, we check each item in this file, and when a match is found, we +# either allow it if the line doesn't have a !, or disallow if the line has a !. +# All the lines after the matching line will be ignored. + + +# To allow a specific class to use annotations: +# com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations + +# To disallow a specific class to use annotations: +# !com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations + +# To allow a specific package to use annotations: +# com.android.hoststubgen.test.* + +# To disallow a specific package to use annotations: +# !com.android.hoststubgen.test.* + + +com.android.hoststubgen.test.tinyframework.* +com.supported.* +com.unsupported.* + +# Use this to allow all packages +# * + +# Use this to allow all packages +# !*
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh new file mode 100755 index 000000000000..00cbfe38e815 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh @@ -0,0 +1,134 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +help() { + cat <<'EOF' + + diff-and-update-golden.sh [OPTIONS] + + Compare the generated jar files from tiny-framework to the "golden" files. + + OPTIONS: + -u: Update the golden files. + + -3: Run `meld` to compare original, stub and impl jar files in 3-way diff. + This is useful to visualize the exact differences between 3 jar files. + + -2: Run `meld` to compare original <-> impl, and impl <-> stub as two different diffs. +EOF +} + +source "${0%/*}"/../../common.sh + +SCRIPT_NAME="${0##*/}" + +GOLDEN_DIR=golden-output +mkdir -p $GOLDEN_DIR + +DIFF_CMD=${DIFF:-diff -u --ignore-blank-lines --ignore-space-change} + +update=0 +three_way=0 +two_way=0 +while getopts "u32" opt; do +case "$opt" in + u) + update=1 + ;; + 3) + three_way=1 + ;; + 2) + two_way=1 + ;; + '?') + help + exit 1 + ;; +esac +done +shift $(($OPTIND - 1)) + + +# Build the dump files, which are the input of this test. +run m tiny-framework-dump-test + + +# Get the path to the generate text files. (not the golden files.) +# We get them from $OUT/module-info.json + +files=( +$(python3 -c ' +import sys +import os +import json + +with open(sys.argv[1], "r") as f: + data = json.load(f) + + # Equivalent to: jq -r '.["tiny-framework-dump-test"]["installed"][]' + for path in data["tiny-framework-dump-test"]["installed"]: + + if "golden-output" in path: + continue + if path.endswith(".txt"): + print(os.getenv("ANDROID_BUILD_TOP") + "/" + path) +' $OUT/module-info.json) +) + +# Next, compare each file and update them in $GOLDEN_DIR + +any_file_changed=0 + +for file in ${files[*]} ; do + name=$(basename $file) + echo "# Checking $name ..." + + file_changed=0 + if run $DIFF_CMD $GOLDEN_DIR/$name $file; then + : # No diff + else + file_changed=1 + any_file_changed=1 + fi + + if (( $update && $file_changed )) ; then + echo "# Updating $name ..." + run cp $file $GOLDEN_DIR/$name + fi +done + +if (( $three_way )) ; then + echo "# Running 3-way diff with meld..." + run meld ${files[0]} ${files[1]} ${files[2]} & +fi + +if (( $two_way )) ; then + echo "# Running meld..." + run meld --diff ${files[0]} ${files[1]} --diff ${files[1]} ${files[2]} --diff ${files[0]} ${files[2]} +fi + +if (( $any_file_changed == 0 )) ; then + echo "$SCRIPT_NAME: Success: no changes detected." + exit 0 +else + if (( $update )) ; then + echo "$SCRIPT_NAME: Warning: golden files have been updated." + exit 2 + else + echo "$SCRIPT_NAME: Failure: changes detected. See above diff for the details." + exit 3 + fi +fi diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt new file mode 100644 index 000000000000..673d3e8e25e9 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt @@ -0,0 +1,2567 @@ +## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class + Compiled from "HostSideTestClassLoadHook.java" +public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestKeep.class + Compiled from "HostSideTestKeep.java" +public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestKeep.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class + Compiled from "HostSideTestNativeSubstitutionClass.java" +public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestNativeSubstitutionClass.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRemove.class + Compiled from "HostSideTestRemove.java" +public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRemove + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestRemove.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class + Compiled from "HostSideTestStaticInitializerKeep.java" +public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestStaticInitializerKeep.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestStub.class + Compiled from "HostSideTestStub.java" +public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestStub + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestStub.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestSubstitute.class + Compiled from "HostSideTestSubstitute.java" +public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestSubstitute + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + public abstract java.lang.String suffix(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestSubstitute.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestThrow.class + Compiled from "HostSideTestThrow.java" +public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestThrow + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestThrow.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class + Compiled from "HostSideTestWholeClassKeep.java" +public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestWholeClassKeep.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class + Compiled from "HostSideTestWholeClassStub.java" +public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestWholeClassStub.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/tests/HostSideTestSuppress.class + Compiled from "HostSideTestSuppress.java" +public interface android.hosttest.annotation.tests.HostSideTestSuppress extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/tests/HostSideTestSuppress + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestSuppress.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD] + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class + Compiled from "TinyFrameworkCallerCheck.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl; + + public static int getOneKeep(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_1 + x: ireturn + LineNumberTable: + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static int getOneStub(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_1 + x: ireturn + LineNumberTable: + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +SourceFile: "TinyFrameworkCallerCheck.java" +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class + Compiled from "TinyFrameworkCallerCheck.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck; + + public static int getOne_withCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I + x: ireturn + LineNumberTable: + + public static int getOne_noCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I + x: ireturn + LineNumberTable: +} +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class + Compiled from "TinyFrameworkClassAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 3, methods: 10, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 0 6 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 0 4 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public void toBeRemoved(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 0 8 1 foo Ljava/lang/String; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRemove + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String not supported on host side + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 0 10 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestSubstitute( + suffix="_host" + ) + + public int addTwo_host(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 0 4 1 value I + + public static native int nativeAddThree(int); + descriptor: (I)I + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestSubstitute( + suffix="_host" + ) + + public static int nativeAddThree_host(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +SourceFile: "TinyFrameworkClassAnnotations.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class + Compiled from "TinyFrameworkClassClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 3, methods: 10, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 6 1 value I + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 4 1 value I + + public void toBeRemoved(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 8 1 foo Ljava/lang/String; + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String not supported on host side + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 10 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestSubstitute( + suffix="_host" + ) + + public int addTwo_host(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 4 1 value I + + public static native int nativeAddThree(int); + descriptor: (I)I + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestSubstitute( + suffix="_host" + ) + + public static int nativeAddThree_host(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; +} +SourceFile: "TinyFrameworkClassClassWideAnnotations.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class + Compiled from "TinyFrameworkClassLoadHook.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 2 + public static final java.util.Set<java.lang.Class<?>> sLoadedClasses; + descriptor: Ljava/util/Set; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook; + + public static void onClassLoaded(java.lang.Class<?>); + descriptor: (Ljava/lang/Class;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: getstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: aload_0 + x: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z + x: pop + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 clazz Ljava/lang/Class; + LocalVariableTypeTable: + Start Length Slot Name Signature + 0 11 0 clazz Ljava/lang/Class<*>; + Signature: #x // (Ljava/lang/Class<*>;)V + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class java/util/HashSet + x: dup + x: invokespecial #x // Method java/util/HashSet."<init>":()V + x: putstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 2, attributes: 2 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 2, attributes: 2 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 6, methods: 7, attributes: 3 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private final java.lang.String mLongName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mShortName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=5, args_size=5 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: aload_0 + x: aload_3 + x: putfield #x // Field mLongName:Ljava/lang/String; + x: aload_0 + x: aload 4 + x: putfield #x // Field mShortName:Ljava/lang/String; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 18 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + 0 18 3 longName Ljava/lang/String; + 0 18 4 shortName Ljava/lang/String; + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mLongName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mShortName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_3 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: iconst_0 + x: getstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_2 + x: getstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=6, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String RED + x: iconst_0 + x: ldc #x // String Red + x: ldc #x // String R + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String GREEN + x: iconst_1 + x: ldc #x // String Green + x: ldc #x // String G + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String BLUE + x: iconst_2 + x: ldc #x // String Blue + x: ldc #x // String B + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 3 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=3, args_size=3 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + Signature: #x // ()V + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_2 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: iconst_0 + x: getstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String CAT + x: iconst_0 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String DOG + x: iconst_1 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class + Compiled from "TinyFrameworkExceptionTester.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 2 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester; + + public static int testException(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=0 + x: new #x // class java/lang/IllegalStateException + x: dup + x: ldc #x // String Inner exception + x: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V + x: athrow + x: astore_0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Outer exception + x: aload_0 + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V + x: athrow + Exception table: + from to target type + 0 10 10 Class java/lang/Exception + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 e Ljava/lang/Exception; + StackMapTable: number_of_entries = 1 + frame_type = 74 /* same_locals_1_stack_item */ + stack = [ class java/lang/Exception ] +} +SourceFile: "TinyFrameworkExceptionTester.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class + Compiled from "TinyFrameworkForTextPolicy.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + super_class: #x // java/lang/Object + interfaces: 0, fields: 3, methods: 10, attributes: 1 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 6 1 value I + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 4 1 value I + + public void toBeRemoved(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 8 1 foo Ljava/lang/String; + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String not supported on host side + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 10 1 value I + + public int addTwo_host(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 4 1 value I + + public static native int nativeAddThree(int); + descriptor: (I)I + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static int addThree_host(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; +} +SourceFile: "TinyFrameworkForTextPolicy.java" +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 8 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 6 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_5 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkLambdas.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkLambdas.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class + Compiled from "TinyFrameworkNative.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 8, attributes: 2 + int value; + descriptor: I + flags: (0x0000) + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + + public static native int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static int nativeAddTwo_should_be_like_this(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=1, args_size=1 + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 arg I + + public static native long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static long nativeLongPlus_should_be_like_this(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 arg1 J + 0 6 2 arg2 J + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 v I + + public native int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0101) ACC_PUBLIC, ACC_NATIVE + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 arg I +} +SourceFile: "TinyFrameworkNative.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestNativeSubstitutionClass( + value="TinyFrameworkNative_host" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class + Compiled from "TinyFrameworkNative_host.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 2 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host; + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 arg I + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: lload_0 + x: lload_2 + x: ladd + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 arg1 J + 0 4 2 arg2 J + + public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 7 1 arg I +} +SourceFile: "TinyFrameworkNative_host.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 1, methods: 3, attributes: 5 + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0000) + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; +} +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 5 + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2(); + descriptor: ()V + flags: (0x0000) + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; +} +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 1, methods: 3, attributes: 5 + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0000) + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; +} +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 5 + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4(); + descriptor: ()V + flags: (0x0000) + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; +} +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 1, attributes: 3 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass; + 0 10 1 x I +} +SourceFile: "TinyFrameworkNestedClasses.java" +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_5 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass; + 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; +} +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 5 + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1(); + descriptor: ()V + flags: (0x0000) + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; +} +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 6 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; +} +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + interfaces: 0, fields: 0, methods: 1, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass; + 0 6 1 x I +} +SourceFile: "TinyFrameworkNestedClasses.java" +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 4, attributes: 4 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 2 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect; + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class com/unsupported/UnsupportedClass + x: dup + x: iload_0 + x: invokespecial #x // Method com/unsupported/UnsupportedClass."<init>":(I)V + x: invokevirtual #x // Method com/unsupported/UnsupportedClass.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 12 0 value I +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/supported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.supported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/supported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 2 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + + public com.supported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/supported/UnsupportedClass; + 0 10 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/supported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 2 + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/unsupported/UnsupportedClass; + 0 14 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/unsupported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt new file mode 100644 index 000000000000..d12588ae4ce2 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt @@ -0,0 +1,1452 @@ +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class + Compiled from "TinyFrameworkCallerCheck.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 4 + private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int getOneStub(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class + Compiled from "TinyFrameworkCallerCheck.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 5 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int getOne_withCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int getOne_noCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class + Compiled from "TinyFrameworkClassAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 5, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +SourceFile: "TinyFrameworkClassAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class + Compiled from "TinyFrameworkClassClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 3, methods: 8, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public void toBeRemoved(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkClassClassWideAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class + Compiled from "TinyFrameworkClassLoadHook.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 3 + public static final java.util.Set<java.lang.Class<?>> sLoadedClasses; + descriptor: Ljava/util/Set; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static void onClassLoaded(java.lang.Class<?>); + descriptor: (Ljava/lang/Class;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // (Ljava/lang/Class<*>;)V + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 4, methods: 7, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=5, args_size=5 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=3, args_size=3 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()V + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class + Compiled from "TinyFrameworkExceptionTester.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int testException(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkExceptionTester.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class + Compiled from "TinyFrameworkForTextPolicy.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 5, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkForTextPolicy.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 7, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 7, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class + Compiled from "TinyFrameworkNative.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 8, attributes: 3 + int value; + descriptor: I + flags: (0x0000) + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static native int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static int nativeAddTwo_should_be_like_this(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static native long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static long nativeLongPlus_should_be_like_this(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=4, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public native int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0101) ACC_PUBLIC, ACC_NATIVE + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkNative.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestNativeSubstitutionClass( + value="TinyFrameworkNative_host" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 1, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + interfaces: 0, fields: 0, methods: 1, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 4, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt new file mode 100644 index 000000000000..97fb64f38b2d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt @@ -0,0 +1,2673 @@ +## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class + Compiled from "HostSideTestClassLoadHook.java" +public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestKeep.class + Compiled from "HostSideTestKeep.java" +public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class + Compiled from "HostSideTestNativeSubstitutionClass.java" +public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestNativeSubstitutionClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRemove.class + Compiled from "HostSideTestRemove.java" +public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRemove + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestRemove.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestStub.class + Compiled from "HostSideTestStub.java" +public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestStub + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestSubstitute.class + Compiled from "HostSideTestSubstitute.java" +public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestSubstitute + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + public abstract java.lang.String suffix(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestSubstitute.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestThrow.class + Compiled from "HostSideTestThrow.java" +public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestThrow + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestThrow.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class + Compiled from "HostSideTestWholeClassKeep.java" +public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestWholeClassKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class + Compiled from "HostSideTestWholeClassStub.java" +public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestWholeClassStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class + Compiled from "TinyFrameworkCallerCheck.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl; + + public static int getOneKeep(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + x: ldc #x // String getOneKeep + x: ldc #x // String ()I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_1 + x: ireturn + LineNumberTable: + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static int getOneStub(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_1 + x: ireturn + LineNumberTable: + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class + Compiled from "TinyFrameworkCallerCheck.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 5 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck; + + public static int getOne_withCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I + x: ireturn + LineNumberTable: + + public static int getOne_noCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I + x: ireturn + LineNumberTable: +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class + Compiled from "TinyFrameworkClassAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 0 6 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String addOneInner + x: ldc #x // String (I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 15 4 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 0 4 1 value I + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +SourceFile: "TinyFrameworkClassAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class + Compiled from "TinyFrameworkClassClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 3, methods: 8, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 6 1 value I + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 4 1 value I + + public void toBeRemoved(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 8 1 foo Ljava/lang/String; + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 0 4 1 value I + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; +} +SourceFile: "TinyFrameworkClassClassWideAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class + Compiled from "TinyFrameworkClassLoadHook.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 3 + public static final java.util.Set<java.lang.Class<?>> sLoadedClasses; + descriptor: Ljava/util/Set; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook; + + public static void onClassLoaded(java.lang.Class<?>); + descriptor: (Ljava/lang/Class;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: getstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: aload_0 + x: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z + x: pop + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 clazz Ljava/lang/Class; + LocalVariableTypeTable: + Start Length Slot Name Signature + 0 11 0 clazz Ljava/lang/Class<*>; + Signature: #x // (Ljava/lang/Class<*>;)V + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class java/util/HashSet + x: dup + x: invokespecial #x // Method java/util/HashSet."<init>":()V + x: putstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 6, methods: 7, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private final java.lang.String mLongName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mShortName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=5, args_size=5 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: aload_0 + x: aload_3 + x: putfield #x // Field mLongName:Ljava/lang/String; + x: aload_0 + x: aload 4 + x: putfield #x // Field mShortName:Ljava/lang/String; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 18 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + 0 18 3 longName Ljava/lang/String; + 0 18 4 shortName Ljava/lang/String; + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mLongName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mShortName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_3 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: iconst_0 + x: getstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_2 + x: getstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=6, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String RED + x: iconst_0 + x: ldc #x // String Red + x: ldc #x // String R + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String GREEN + x: iconst_1 + x: ldc #x // String Green + x: ldc #x // String G + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String BLUE + x: iconst_2 + x: ldc #x // String Blue + x: ldc #x // String B + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=3, args_size=3 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + Signature: #x // ()V + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_2 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: iconst_0 + x: getstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String CAT + x: iconst_0 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String DOG + x: iconst_1 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class + Compiled from "TinyFrameworkExceptionTester.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester; + + public static int testException(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=0 + x: new #x // class java/lang/IllegalStateException + x: dup + x: ldc #x // String Inner exception + x: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V + x: athrow + x: astore_0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Outer exception + x: aload_0 + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V + x: athrow + Exception table: + from to target type + 0 10 10 Class java/lang/Exception + StackMapTable: number_of_entries = 1 + frame_type = 74 /* same_locals_1_stack_item */ + stack = [ class java/lang/Exception ] + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 e Ljava/lang/Exception; +} +SourceFile: "TinyFrameworkExceptionTester.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class + Compiled from "TinyFrameworkForTextPolicy.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 6 1 value I + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String addOneInner + x: ldc #x // String (I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 15 4 1 value I + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 4 1 value I + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; +} +SourceFile: "TinyFrameworkForTextPolicy.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 8 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 6 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_5 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class + Compiled from "TinyFrameworkNative.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 8, attributes: 3 + int value; + descriptor: I + flags: (0x0000) + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=1, args_size=1 + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + + public static int nativeAddTwo_should_be_like_this(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=1, args_size=1 + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 arg I + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + + public static long nativeLongPlus_should_be_like_this(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 arg1 J + 0 6 2 arg2 J + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 v I + + public int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 arg I +} +SourceFile: "TinyFrameworkNative.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestNativeSubstitutionClass( + value="TinyFrameworkNative_host" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class + Compiled from "TinyFrameworkNative_host.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String <init> + x: ldc #x // String ()V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host; + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeAddTwo + x: ldc #x // String (I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 4 0 arg I + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeLongPlus + x: ldc #x // String (JJ)J + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: lload_0 + x: lload_2 + x: ladd + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 4 0 arg1 J + 15 4 2 arg2 J + + public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeNonStaticAddToValue + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 15 7 1 arg I +} +SourceFile: "TinyFrameworkNative_host.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 1, methods: 3, attributes: 6 + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0000) + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 6 + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2(); + descriptor: ()V + flags: (0x0000) + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 1, methods: 3, attributes: 6 + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0000) + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 6 + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4(); + descriptor: ()V + flags: (0x0000) + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 1, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass; + 0 10 1 x I +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_5 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass; + 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; +} +InnerClasses: + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 6 + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1(); + descriptor: ()V + flags: (0x0000) + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 6 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + interfaces: 0, fields: 0, methods: 1, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass; + 0 6 1 x I +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 4, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect; + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class com/supported/UnsupportedClass + x: dup + x: iload_0 + x: invokespecial #x // Method com/supported/UnsupportedClass."<init>":(I)V + x: invokevirtual #x // Method com/supported/UnsupportedClass.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 12 0 value I +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/supported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.supported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/supported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 3 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + + public com.supported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // String com/supported/UnsupportedClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 10 0 this Lcom/supported/UnsupportedClass; + 15 10 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // String com/supported/UnsupportedClass + x: ldc #x // String getValue + x: ldc #x // String ()I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 15 5 0 this Lcom/supported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/unsupported/UnsupportedClass; + 0 14 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/unsupported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt new file mode 100644 index 000000000000..d12588ae4ce2 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt @@ -0,0 +1,1452 @@ +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class + Compiled from "TinyFrameworkCallerCheck.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 4 + private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int getOneStub(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class + Compiled from "TinyFrameworkCallerCheck.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 5 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int getOne_withCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int getOne_noCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class + Compiled from "TinyFrameworkClassAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 5, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +SourceFile: "TinyFrameworkClassAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class + Compiled from "TinyFrameworkClassClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 3, methods: 8, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public void toBeRemoved(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkClassClassWideAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class + Compiled from "TinyFrameworkClassLoadHook.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 3 + public static final java.util.Set<java.lang.Class<?>> sLoadedClasses; + descriptor: Ljava/util/Set; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static void onClassLoaded(java.lang.Class<?>); + descriptor: (Ljava/lang/Class;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // (Ljava/lang/Class<*>;)V + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 4, methods: 7, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=5, args_size=5 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=3, args_size=3 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()V + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class + Compiled from "TinyFrameworkExceptionTester.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int testException(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkExceptionTester.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class + Compiled from "TinyFrameworkForTextPolicy.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 5, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkForTextPolicy.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 7, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 7, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class + Compiled from "TinyFrameworkNative.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 8, attributes: 3 + int value; + descriptor: I + flags: (0x0000) + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static native int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static int nativeAddTwo_should_be_like_this(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static native long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static long nativeLongPlus_should_be_like_this(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=4, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public native int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0101) ACC_PUBLIC, ACC_NATIVE + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkNative.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestNativeSubstitutionClass( + value="TinyFrameworkNative_host" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 1, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + interfaces: 0, fields: 0, methods: 1, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 4, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt new file mode 100644 index 000000000000..8035189b50c9 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt @@ -0,0 +1,3469 @@ +## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class + Compiled from "HostSideTestClassLoadHook.java" +public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 2, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestClassLoadHook + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestKeep.class + Compiled from "HostSideTestKeep.java" +public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestKeep + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class + Compiled from "HostSideTestNativeSubstitutionClass.java" +public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 2, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestNativeSubstitutionClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestNativeSubstitutionClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRemove.class + Compiled from "HostSideTestRemove.java" +public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRemove + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestRemove + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestRemove.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestStub.class + Compiled from "HostSideTestStub.java" +public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestStub + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestStub + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestSubstitute.class + Compiled from "HostSideTestSubstitute.java" +public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestSubstitute + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 2, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestSubstitute + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public abstract java.lang.String suffix(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT +} +SourceFile: "HostSideTestSubstitute.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestThrow.class + Compiled from "HostSideTestThrow.java" +public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestThrow + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestThrow + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestThrow.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class + Compiled from "HostSideTestWholeClassKeep.java" +public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestWholeClassKeep + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestWholeClassKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class + Compiled from "HostSideTestWholeClassStub.java" +public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation + minor version: 0 + major version: 61 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestWholeClassStub + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestWholeClassStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class + Compiled from "TinyFrameworkCallerCheck.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl; + + public static int getOneKeep(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + x: ldc #x // String getOneKeep + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + x: ldc #x // String getOneKeep + x: ldc #x // String ()I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_1 + x: ireturn + LineNumberTable: + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static int getOneStub(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl + x: ldc #x // String getOneStub + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_1 + x: ireturn + LineNumberTable: + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class + Compiled from "TinyFrameworkCallerCheck.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 5 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck; + + public static int getOne_withCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + x: ldc #x // String getOne_withCheck + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I + x: ireturn + LineNumberTable: + + public static int getOne_noCheck(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck + x: ldc #x // String getOne_noCheck + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I + x: ireturn + LineNumberTable: +} +InnerClasses: + private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck +SourceFile: "TinyFrameworkCallerCheck.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class + Compiled from "TinyFrameworkClassAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String addOne + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 11 6 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String addOneInner + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String addOneInner + x: ldc #x // String (I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 26 4 1 value I + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String addTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + 11 4 1 value I + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String nativeAddThree + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations + x: ldc #x // String visibleButUsesUnsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +} +SourceFile: "TinyFrameworkClassAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class + Compiled from "TinyFrameworkClassClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 3, methods: 9, attributes: 3 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String addOne + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 11 6 1 value I + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String addOneInner + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 11 4 1 value I + + public void toBeRemoved(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String toBeRemoved + x: ldc #x // String (Ljava/lang/String;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 11 8 1 foo Ljava/lang/String; + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String addTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + 11 4 1 value I + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String nativeAddThree + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations + x: ldc #x // String visibleButUsesUnsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations; +} +SourceFile: "TinyFrameworkClassClassWideAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class + Compiled from "TinyFrameworkClassLoadHook.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 3 + public static final java.util.Set<java.lang.Class<?>> sLoadedClasses; + descriptor: Ljava/util/Set; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook; + + public static void onClassLoaded(java.lang.Class<?>); + descriptor: (Ljava/lang/Class;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String onClassLoaded + x: ldc #x // String (Ljava/lang/Class;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: getstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: aload_0 + x: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z + x: pop + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 clazz Ljava/lang/Class; + LocalVariableTypeTable: + Start Length Slot Name Signature + 11 11 0 clazz Ljava/lang/Class<*>; + Signature: #x // (Ljava/lang/Class<*>;)V + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class java/util/HashSet + x: dup + x: invokespecial #x // Method java/util/HashSet."<init>":()V + x: putstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 6, methods: 7, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private final java.lang.String mLongName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mShortName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String valueOf + x: ldc #x // String (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 name Ljava/lang/String; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=4, locals=5, args_size=5 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String <init> + x: ldc #x // String (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: aload_0 + x: aload_3 + x: putfield #x // Field mLongName:Ljava/lang/String; + x: aload_0 + x: aload 4 + x: putfield #x // Field mShortName:Ljava/lang/String; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 18 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + 11 18 3 longName Ljava/lang/String; + 11 18 4 shortName Ljava/lang/String; + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String getLongName + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: getfield #x // Field mLongName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String getShortName + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: getfield #x // Field mShortName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String $values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_3 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: iconst_0 + x: getstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_2 + x: getstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=6, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String RED + x: iconst_0 + x: ldc #x // String Red + x: ldc #x // String R + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String GREEN + x: iconst_1 + x: ldc #x // String Green + x: ldc #x // String G + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String BLUE + x: iconst_2 + x: ldc #x // String Blue + x: ldc #x // String B + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 61 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String valueOf + x: ldc #x // String (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 name Ljava/lang/String; + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=4, locals=3, args_size=3 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String <init> + x: ldc #x // String (Ljava/lang/String;I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + Signature: #x // ()V + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String $values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_2 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: iconst_0 + x: getstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String CAT + x: iconst_0 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String DOG + x: iconst_1 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class + Compiled from "TinyFrameworkExceptionTester.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester; + + public static int testException(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + x: ldc #x // String testException + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/lang/IllegalStateException + x: dup + x: ldc #x // String Inner exception + x: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V + x: athrow + x: astore_0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Outer exception + x: aload_0 + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V + x: athrow + Exception table: + from to target type + 11 21 21 Class java/lang/Exception + StackMapTable: number_of_entries = 1 + frame_type = 85 /* same_locals_1_stack_item */ + stack = [ class java/lang/Exception ] + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 22 11 0 e Ljava/lang/Exception; +} +SourceFile: "TinyFrameworkExceptionTester.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class + Compiled from "TinyFrameworkForTextPolicy.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: aload_0 + x: iconst_2 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String addOne + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokevirtual #x // Method addOneInner:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 11 6 1 value I + + public int addOneInner(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String addOneInner + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String addOneInner + x: ldc #x // String (I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 26 4 1 value I + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String addTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 11 4 1 value I + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String nativeAddThree + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 value I + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + + public java.lang.String visibleButUsesUnsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String visibleButUsesUnsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; +} +SourceFile: "TinyFrameworkForTextPolicy.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String getSupplier + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$getSupplier_static$3 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: bipush 8 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$getSupplier$2 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$static$1 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: bipush 6 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$new$0 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_5 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String getSupplier + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$getSupplier_static$3 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$getSupplier$2 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$static$1 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$new$0 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestStub + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class + Compiled from "TinyFrameworkNative.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 9, attributes: 3 + int value; + descriptor: I + flags: (0x0000) + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=1, args_size=1 + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + + public static int nativeAddTwo_should_be_like_this(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeAddTwo_should_be_like_this + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 arg I + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + + public static long nativeLongPlus_should_be_like_this(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeLongPlus_should_be_like_this + x: ldc #x // String (JJ)J + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 arg1 J + 11 6 2 arg2 J + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String setValue + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 11 6 1 v I + + public int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeNonStaticAddToValue_should_be_like_this + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 11 6 1 arg I +} +SourceFile: "TinyFrameworkNative.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestNativeSubstitutionClass( + value="TinyFrameworkNative_host" + ) +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class + Compiled from "TinyFrameworkNative_host.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 5, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String <init> + x: ldc #x // String ()V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host; + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeAddTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeAddTwo + x: ldc #x // String (I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 4 0 arg I + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeLongPlus + x: ldc #x // String (JJ)J + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeLongPlus + x: ldc #x // String (JJ)J + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: lload_0 + x: lload_2 + x: ladd + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 4 0 arg1 J + 26 4 2 arg2 J + + public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeNonStaticAddToValue + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeNonStaticAddToValue + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 26 7 1 arg I +} +SourceFile: "TinyFrameworkNative_host.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 1, methods: 4, attributes: 6 + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0000) + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String <init> + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + 11 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2(); + descriptor: ()V + flags: (0x0000) + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 1, methods: 4, attributes: 6 + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0000) + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String <init> + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + 11 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4(); + descriptor: ()V + flags: (0x0000) + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass; + 11 10 1 x I +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 2, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + x: ldc #x // String <init> + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: aload_1 + x: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_5 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass; + 11 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; +} +InnerClasses: + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class + Compiled from "TinyFrameworkNestedClasses.java" +class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer> + minor version: 0 + major version: 61 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1(); + descriptor: ()V + flags: (0x0000) + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + + public java.lang.Object get(); + descriptor: ()Ljava/lang/Object; + flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static +Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>; +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 5 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 6 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + interfaces: 0, fields: 0, methods: 2, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass; + 11 6 1 x I +} +InnerClasses: + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 4, attributes: 5 + public final java.util.function.Supplier<java.lang.Integer> mSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0011) ACC_PUBLIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static final java.util.function.Supplier<java.lang.Integer> sSupplier; + descriptor: Ljava/util/function/Supplier; + flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL + Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String getSupplier + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +InnerClasses: + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect; + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + x: ldc #x // String foo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/supported/UnsupportedClass + x: dup + x: iload_0 + x: invokespecial #x // Method com/supported/UnsupportedClass."<init>":(I)V + x: invokevirtual #x // Method com/supported/UnsupportedClass.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 12 0 value I +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +## Class: com/supported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.supported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/supported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 3 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/supported/UnsupportedClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.supported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/supported/UnsupportedClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/supported/UnsupportedClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 10 0 this Lcom/supported/UnsupportedClass; + 26 10 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/supported/UnsupportedClass + x: ldc #x // String getValue + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com/supported/UnsupportedClass + x: ldc #x // String getValue + x: ldc #x // String ()I + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; + x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 26 5 0 this Lcom/supported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/unsupported/UnsupportedClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/unsupported/UnsupportedClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 14 0 this Lcom/unsupported/UnsupportedClass; + 11 14 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/unsupported/UnsupportedClass + x: ldc #x // String getValue + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/unsupported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt new file mode 100644 index 000000000000..079d2a84e498 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt @@ -0,0 +1,17 @@ +class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy stub + field stub stub + field keep keep + # field remove remove # Implicitly remove + method <init> ()V stub + method addOne (I)I stub + method addOneInner (I)I keep + method toBeRemoved (Ljava/lang/String;)V remove + method addTwo (I)I @addTwo_host + # method addTwo_host (I)I # used as a substitute + method nativeAddThree (I)I @addThree_host + # method addThree_host (I)I # used as a substitute + method unsupportedMethod ()Ljava/lang/String; throw + method visibleButUsesUnsupportedMethod ()Ljava/lang/String; stub + +# Class load hook +class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy ~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh new file mode 100755 index 000000000000..872bbf878de4 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh @@ -0,0 +1,132 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +source "${0%/*}"/../../common.sh + +# This scripts run the "tiny-framework" test, but does most stuff from the command line, using +# the native java and javac commands. + +debug=0 +while getopts "d" opt; do +case "$opt" in + d) debug=1 ;; +esac +done +shift $(($OPTIND - 1)) + + +out=out + +rm -fr $out +mkdir -p $out + +HOSTSTUBGEN=hoststubgen + +# Rebuild the tool and the dependencies. These are the only things we build with the build system. +run m $HOSTSTUBGEN hoststubgen-annotations hoststubgen-helper-runtime truth junit + + +# Build tiny-framework + +tiny_framework_classes=$out/tiny-framework/classes/ +tiny_framework_jar=$out/tiny-framework.jar +tiny_framework_host_stub_jar=$out/tiny-framework_host_stub.jar +tiny_framework_host_impl_jar=$out/tiny-framework_host_impl.jar + +tiny_test_classes=$out/tiny-test/classes/ +tiny_test_jar=$out/tiny-test.jar + +framework_compile_classpaths=( + $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-annotations/android_common/javac/hoststubgen-annotations.jar +) + +test_compile_classpaths=( + $SOONG_INT/external/junit/junit/android_common/combined/junit.jar + $SOONG_INT/external/truth/truth/android_common/combined/truth.jar +) + +test_runtime_classpaths=( + $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-helper-runtime/linux_glibc_common/javac/hoststubgen-helper-runtime.jar +) + +# This suite runs all tests in the JAR. +test_classes=(com.android.hoststubgen.hosthelper.HostTestSuite) + +# Uncomment this to run a specific test. +# tests=(com.android.hoststubgen.test.tinyframework.TinyFrameworkBenchmark) + + +# Build tiny-framework.jar +echo "# Building tiny-framework..." +run $JAVAC \ + -cp $( \ + join : \ + ${framework_compile_classpaths[@]} \ + ) \ + -d $tiny_framework_classes \ + tiny-framework/src/**/*.java + +run $JAR cvf $tiny_framework_jar \ + -C $tiny_framework_classes . + +# Build stub/impl jars +echo "# Generating the stub and impl jars..." +run $HOSTSTUBGEN \ + @../hoststubgen-standard-options.txt \ + --in-jar $tiny_framework_jar \ + --out-stub-jar $tiny_framework_host_stub_jar \ + --out-impl-jar $tiny_framework_host_impl_jar \ + --policy-override-file policy-override-tiny-framework.txt \ + --gen-keep-all-file out/tiny-framework_keep_all.txt \ + --gen-input-dump-file out/tiny-framework_dump.txt \ + --package-redirect com.unsupported:com.supported \ + --annotation-allowed-classes-file annotation-allowed-classes-tiny-framework.txt \ + $HOSTSTUBGEN_OPTS + +# Extract the jar files, so we can look into them. +extract $tiny_framework_host_stub_jar $tiny_framework_host_impl_jar + +# Build the test +echo "# Building tiny-test..." +run $JAVAC \ + -cp $( \ + join : \ + $tiny_framework_host_stub_jar \ + "${test_compile_classpaths[@]}" \ + ) \ + -d $tiny_test_classes \ + tiny-test/src/**/*.java + +run $JAR cvf $tiny_test_jar \ + -C $tiny_test_classes . + +if (( $debug )) ; then + JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700" +fi + +# Run the test +echo "# Running tiny-test..." +run $JAVA \ + $JAVA_OPTS \ + -cp $( \ + join : \ + $tiny_test_jar \ + $tiny_framework_host_impl_jar \ + "${test_compile_classpaths[@]}" \ + "${test_runtime_classpaths[@]}" \ + ) \ + org.junit.runner.JUnitCore \ + ${test_classes[@]} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py new file mode 100755 index 000000000000..cee29dcd1d59 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py @@ -0,0 +1,64 @@ +#!/usr/bin/python3 +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Compare the tiny-framework JAR dumps to the golden files. + +import sys +import os +import unittest +import subprocess + +GOLDEN_DIR = 'golden-output' + +# Run diff. +def run_diff(file1, file2): + command = ['diff', '-u', '--ignore-blank-lines', '--ignore-space-change', file1, file2] + print(' '.join(command)) + result = subprocess.run(command, stderr = sys.stdout) + + success = result.returncode == 0 + + if success: + print(f'No diff found.') + else: + print(f'Fail: {file1} and {file2} are different.') + + return success + + +# Check one golden file. +def check_one_file(filename): + print(f'= Checking file: {filename}') + return run_diff(os.path.join(GOLDEN_DIR, filename), filename) + +class TestWithGoldenOutput(unittest.TestCase): + + # Test to check the generated jar files to the golden output. + def test_compare_to_golden(self): + files = os.listdir(GOLDEN_DIR) + files.sort() + + print(f"Golden files: {files}") + success = True + + for file in files: + if not check_one_file(file): + success = False + + if not success: + self.fail('Some files are different. See stdout log for more details.') + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java new file mode 100644 index 000000000000..f53020771cc3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestKeep; +import android.hosttest.annotation.HostSideTestStub; +import android.hosttest.annotation.HostSideTestWholeClassStub; + +/** + * Used by the benchmark. + */ +@HostSideTestWholeClassStub +public class TinyFrameworkCallerCheck { + + /** + * This method uses an inner method (which has the caller check). + * + * Benchmark result: 768ns + */ + public static int getOne_withCheck() { + return Impl.getOneKeep(); + } + + /** + * This method doesn't have any caller check. + * + * Benchmark result: 2ns + */ + public static int getOne_noCheck() { + return Impl.getOneStub(); + } + + private static class Impl { + @HostSideTestKeep + public static int getOneKeep() { + return 1; + } + + @HostSideTestStub + public static int getOneStub() { + return 1; + } + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java new file mode 100644 index 000000000000..ab387e0938c3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestClassLoadHook; +import android.hosttest.annotation.HostSideTestKeep; +import android.hosttest.annotation.HostSideTestRemove; +import android.hosttest.annotation.HostSideTestStub; +import android.hosttest.annotation.HostSideTestSubstitute; +import android.hosttest.annotation.HostSideTestThrow; + +/** + * Test without class-wide annotations. + */ +@HostSideTestStub +@HostSideTestClassLoadHook( + "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded") +public class TinyFrameworkClassAnnotations { + @HostSideTestStub + public TinyFrameworkClassAnnotations() { + } + + @HostSideTestStub + public int stub = 1; + + @HostSideTestKeep + public int keep = 2; + + // Members will be deleted by default. + // Deleted fields cannot have an initial value, because otherwise .ctor will fail to set it at + // runtime. + public int remove; + + @HostSideTestStub + public int addOne(int value) { + return addOneInner(value); + } + + @HostSideTestKeep + public int addOneInner(int value) { + return value + 1; + } + + @HostSideTestRemove // Explicitly remove + public void toBeRemoved(String foo) { + throw new RuntimeException(); + } + + @HostSideTestStub + @HostSideTestSubstitute(suffix = "_host") + public int addTwo(int value) { + throw new RuntimeException("not supported on host side"); + } + + public int addTwo_host(int value) { + return value + 2; + } + + @HostSideTestStub + @HostSideTestSubstitute(suffix = "_host") + public static native int nativeAddThree(int value); + + public static int nativeAddThree_host(int value) { + return value + 3; + } + + @HostSideTestThrow + public String unsupportedMethod() { + return "This value shouldn't be seen on the host side."; + } + + @HostSideTestStub + public String visibleButUsesUnsupportedMethod() { + return unsupportedMethod(); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java new file mode 100644 index 000000000000..145b65a98d7b --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestStub; +import android.hosttest.annotation.HostSideTestSubstitute; +import android.hosttest.annotation.HostSideTestWholeClassStub; + +@HostSideTestWholeClassStub +public class TinyFrameworkClassClassWideAnnotations { + public TinyFrameworkClassClassWideAnnotations() { + } + + public int stub = 1; + + public int keep = 2; + + // Cannot have an initial value, because otherwise .ctor will fail to set it at runtime. + public int remove; + + // @Stub + public int addOne(int value) { + return addOneInner(value); + } + + // @Keep + public int addOneInner(int value) { + return value + 1; + } + + // @Remove + public void toBeRemoved(String foo) { + throw new RuntimeException(); + } + + @HostSideTestStub + @HostSideTestSubstitute(suffix = "_host") + public int addTwo(int value) { + throw new RuntimeException("not supported on host side"); + } + + public int addTwo_host(int value) { + return value + 2; + } + + @HostSideTestStub + @HostSideTestSubstitute(suffix = "_host") + public static native int nativeAddThree(int value); + + public static int nativeAddThree_host(int value) { + return value + 3; + } + + public String unsupportedMethod() { + return "This value shouldn't be seen on the host side."; + } + + public String visibleButUsesUnsupportedMethod() { + return unsupportedMethod(); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java new file mode 100644 index 000000000000..98fc6349cdc9 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestWholeClassStub; + +import java.util.HashSet; +import java.util.Set; + +@HostSideTestWholeClassStub +public class TinyFrameworkClassLoadHook { + private TinyFrameworkClassLoadHook() { + } + + public static final Set<Class<?>> sLoadedClasses = new HashSet<>(); + + public static void onClassLoaded(Class<?> clazz) { + sLoadedClasses.add(clazz); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java new file mode 100644 index 000000000000..8324ed93bf26 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestClassLoadHook; +import android.hosttest.annotation.HostSideTestStub; +import android.hosttest.annotation.HostSideTestWholeClassStub; + +@HostSideTestStub +public class TinyFrameworkClassWithInitializerDefault { + static { + sInitialized = true; + } + + @HostSideTestStub + public static boolean sInitialized; + @HostSideTestStub + public static Object sObject = new Object(); +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java new file mode 100644 index 000000000000..ea1ad93b21b4 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestClassLoadHook; +import android.hosttest.annotation.HostSideTestStaticInitializerKeep; +import android.hosttest.annotation.HostSideTestStub; + +@HostSideTestClassLoadHook( + "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded") +@HostSideTestStub +@HostSideTestStaticInitializerKeep +public class TinyFrameworkClassWithInitializerStub { + static { + sInitialized = true; + } + + @HostSideTestStub + public static boolean sInitialized; + @HostSideTestStub + public static Object sObject = new Object(); +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java new file mode 100644 index 000000000000..51f48188fe74 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestKeep; +import android.hosttest.annotation.HostSideTestStub; + +@HostSideTestStub +public enum TinyFrameworkEnumComplex { + @HostSideTestStub + RED("Red", "R"), + @HostSideTestStub + GREEN("Green", "G"), + @HostSideTestStub + BLUE("Blue", "B"); + + @HostSideTestKeep + private final String mLongName; + + @HostSideTestKeep + private final String mShortName; + + @HostSideTestStub + TinyFrameworkEnumComplex(String longName, String shortName) { + mLongName = longName; + mShortName = shortName; + } + + @HostSideTestStub + public String getLongName() { + return mLongName; + } + + @HostSideTestStub + public String getShortName() { + return mShortName; + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java new file mode 100644 index 000000000000..f440d8667fb4 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestStub; + +@HostSideTestStub +public enum TinyFrameworkEnumSimple { + @HostSideTestStub + CAT, + @HostSideTestStub + DOG, +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java new file mode 100644 index 000000000000..909d3b440f50 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestWholeClassStub; + +@HostSideTestWholeClassStub +public class TinyFrameworkExceptionTester { + public static int testException() { + try { + throw new IllegalStateException("Inner exception"); + } catch (Exception e) { + throw new RuntimeException("Outer exception", e); + } + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java new file mode 100644 index 000000000000..bde7c35dc294 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +/** + * Class for testing the "text policy" file. + */ +public class TinyFrameworkForTextPolicy { + public TinyFrameworkForTextPolicy() { + } + + public int stub = 1; + + public int keep = 2; + + // Removed fields cannot have an initial value, because otherwise .ctor will fail to set it at + // runtime. + public int remove; + + public int addOne(int value) { + return addOneInner(value); + } + + public int addOneInner(int value) { + return value + 1; + } + + public void toBeRemoved(String foo) { + throw new RuntimeException(); + } + + public int addTwo(int value) { + throw new RuntimeException("not supported on host side"); + } + + public int addTwo_host(int value) { + return value + 2; + } + + public static native int nativeAddThree(int value); + + public static int addThree_host(int value) { + return value + 3; + } + + public String unsupportedMethod() { + return "This value shouldn't be seen on the host side."; + } + + public String visibleButUsesUnsupportedMethod() { + return unsupportedMethod(); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java new file mode 100644 index 000000000000..0d1203b0dedc --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestStaticInitializerKeep; +import android.hosttest.annotation.HostSideTestStub; + +import java.util.function.Supplier; + + +/** + * In this class, we explicitly mark each member as "stub". (rather than using WholeClassStub) + * + * This means the actual generated lambda functions would be removed by default. + * + * Implicit filter should take care of them. + */ +@HostSideTestStub +@HostSideTestStaticInitializerKeep +public class TinyFrameworkLambdas { + @HostSideTestStub + public TinyFrameworkLambdas() { + } + + @HostSideTestStub + public final Supplier<Integer> mSupplier = () -> 1; + + @HostSideTestStub + public static final Supplier<Integer> sSupplier = () -> 2; + + @HostSideTestStub + public Supplier<Integer> getSupplier() { + return () -> 3; + } + + @HostSideTestStub + public static Supplier<Integer> getSupplier_static() { + return () -> 4; + } + + @HostSideTestStub + @HostSideTestStaticInitializerKeep + public static class Nested { + @HostSideTestStub + public Nested() { + } + + @HostSideTestStub + public final Supplier<Integer> mSupplier = () -> 5; + + @HostSideTestStub + public static final Supplier<Integer> sSupplier = () -> 6; + + @HostSideTestStub + public Supplier<Integer> getSupplier() { + return () -> 7; + } + + @HostSideTestStub + public static Supplier<Integer> getSupplier_static() { + return () -> 8; + } + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java new file mode 100644 index 000000000000..e7b5d9fc2ece --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestNativeSubstitutionClass; +import android.hosttest.annotation.HostSideTestWholeClassStub; + +@HostSideTestWholeClassStub +@HostSideTestNativeSubstitutionClass("TinyFrameworkNative_host") +public class TinyFrameworkNative { + public static native int nativeAddTwo(int arg); + + public static int nativeAddTwo_should_be_like_this(int arg) { + return TinyFrameworkNative_host.nativeAddTwo(arg); + } + + public static native long nativeLongPlus(long arg1, long arg2); + + public static long nativeLongPlus_should_be_like_this(long arg1, long arg2) { + return TinyFrameworkNative_host.nativeLongPlus(arg1, arg2); + } + + int value; + + public void setValue(int v) { + this.value = v; + } + + public native int nativeNonStaticAddToValue(int arg); + + public int nativeNonStaticAddToValue_should_be_like_this(int arg) { + return TinyFrameworkNative_host.nativeNonStaticAddToValue(this, arg); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java new file mode 100644 index 000000000000..749ebaa378e3 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestWholeClassKeep; + +// TODO: This annotation shouldn't be needed. +// We should infer it from HostSideTestNativeSubstitutionClass. +@HostSideTestWholeClassKeep +public class TinyFrameworkNative_host { + public static int nativeAddTwo(int arg) { + return arg + 2; + } + + public static long nativeLongPlus(long arg1, long arg2) { + return arg1 + arg2; + } + + // Note, the method must be static even for a non-static native method, but instead it + // must take the "source" instance as the first argument. + public static int nativeNonStaticAddToValue(TinyFrameworkNative source, int arg) { + return source.value + arg; + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java new file mode 100644 index 000000000000..e1c48bb85563 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestWholeClassStub; + +import java.util.function.Supplier; + +@HostSideTestWholeClassStub +public class TinyFrameworkNestedClasses { + public final Supplier<Integer> mSupplier = new Supplier<Integer>() { + @Override + public Integer get() { + return 1; + } + }; + + public static final Supplier<Integer> sSupplier = new Supplier<Integer>() { + @Override + public Integer get() { + return 2; + } + }; + public Supplier<Integer> getSupplier() { + return new Supplier<Integer>() { + @Override + public Integer get() { + return 3; + } + }; + } + + public static Supplier<Integer> getSupplier_static() { + return new Supplier<Integer>() { + @Override + public Integer get() { + return 4; + } + }; + } + + @HostSideTestWholeClassStub + public class InnerClass { + public int value = 5; + } + + @HostSideTestWholeClassStub + public static class StaticNestedClass { + public int value = 6; + + // Double-nest + public static Supplier<Integer> getSupplier_static() { + return new Supplier<Integer>() { + @Override + public Integer get() { + return 7; + } + }; + } + } + + public static class BaseClass { + public int value; + public BaseClass(int x) { + value = x; + } + } + + public static class SubClass extends BaseClass { + public SubClass(int x) { + super(x); + } + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java new file mode 100644 index 000000000000..a82be5453b1e --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestWholeClassStub; + +@HostSideTestWholeClassStub +public class TinyFrameworkPackageRedirect { + /** + * A method that uses "unsupported" class. HostStubGen will redirect them to the "supported" + * one (because of --package-redirect), so this test will pass. + */ + public static int foo(int value) { + // This method throws, so it's not callable as-is. But HostStubGen + // will rewrite it, it will actually work. + return new com.unsupported.UnsupportedClass(value).getValue(); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/supported/UnsupportedClass.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/supported/UnsupportedClass.java new file mode 100644 index 000000000000..fa5866451e83 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/supported/UnsupportedClass.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.supported; + +import android.hosttest.annotation.HostSideTestWholeClassKeep; + +// Used for testing --package-redirect. +@HostSideTestWholeClassKeep +public class UnsupportedClass { + private final int mValue; + + public UnsupportedClass(int value) { + mValue = value; + } + + public int getValue() { + return mValue; + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java new file mode 100644 index 000000000000..0409b02b0f5d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.unsupported; + +import android.hosttest.annotation.HostSideTestWholeClassStub; + +// Used for testing --package-redirect. +@HostSideTestWholeClassStub +public class UnsupportedClass { + public UnsupportedClass(int value) { + throw new RuntimeException("This class is not supported"); + } + + public int getValue() { + throw new RuntimeException("This class is not supported"); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java new file mode 100644 index 000000000000..76bbcad2ab26 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * We don't want to use any android classes in this module, so we create our own copy of it here. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface LargeTest {} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java new file mode 100644 index 000000000000..d57735b1987c --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import org.junit.Test; + +import java.text.DecimalFormat; + +/** + * Contains simple micro-benchmarks. + */ +@LargeTest +public class TinyFrameworkBenchmark { + private static final int MINIMAL_ITERATION = 1000; + private static final int MEASURE_SECONDS = 1; + + private static final DecimalFormat sFormatter = new DecimalFormat("#,###"); + + private void doBenchmark(String name, Runnable r) { + // Worm up + for (int i = 0; i < MINIMAL_ITERATION; i++) { + r.run(); + } + + // Start measuring. + final long start = System.nanoTime(); + final long end = start + MEASURE_SECONDS * 1_000_000_000L; + + double iteration = 0; + while (System.nanoTime() <= end) { + for (int i = 0; i < MINIMAL_ITERATION; i++) { + r.run(); + } + iteration += MINIMAL_ITERATION; + } + + final long realEnd = System.nanoTime(); + + System.out.println(String.format("%s\t%s", name, + sFormatter.format((((double) realEnd - start)) / iteration))); + } + + /** + * Micro-benchmark for a method without a non-stub caller check. + */ + @Test + public void benchNoCallerCheck() { + doBenchmark("No caller check", TinyFrameworkCallerCheck::getOne_noCheck); + } + + /** + * Micro-benchmark for a method with a non-stub caller check. + */ + @Test + public void benchWithCallerCheck() { + doBenchmark("With caller check", TinyFrameworkCallerCheck::getOne_withCheck); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java new file mode 100644 index 000000000000..d04ca52a5682 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.SubClass; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.FileDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class TinyFrameworkClassTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testSimple() { + TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy(); + assertThat(tfc.addOne(1)).isEqualTo(2); + assertThat(tfc.stub).isEqualTo(1); + } + +// @Test +// public void testDoesntCompile() { +// TinyFrameworkClass tfc = new TinyFrameworkClass(); +// +// tfc.addOneInner(1); // Shouldn't compile. +// tfc.toBeRemoved("abc"); // Shouldn't compile. +// tfc.unsupportedMethod(); // Shouldn't compile. +// int a = tfc.keep; // Shouldn't compile +// int b = tfc.remove; // Shouldn't compile +// } + + @Test + public void testSubstitute() { + TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy(); + assertThat(tfc.addTwo(1)).isEqualTo(3); + } + + @Test + public void testSubstituteNative() { + TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy(); + assertThat(tfc.nativeAddThree(1)).isEqualTo(4); + } + + @Test + public void testVisibleButUsesUnsupportedMethod() { + TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy(); + + thrown.expect(RuntimeException.class); + thrown.expectMessage("This method is not supported on the host side"); + tfc.visibleButUsesUnsupportedMethod(); + } + + @Test + public void testNestedClass1() { + assertThat(new TinyFrameworkNestedClasses().mSupplier.get()).isEqualTo(1); + } + + @Test + public void testNestedClass2() { + assertThat(TinyFrameworkNestedClasses.sSupplier.get()).isEqualTo(2); + } + + @Test + public void testNestedClass3() { + assertThat(new TinyFrameworkNestedClasses().getSupplier().get()).isEqualTo(3); + } + + @Test + public void testNestedClass4() { + assertThat(TinyFrameworkNestedClasses.getSupplier_static().get()).isEqualTo(4); + } + + @Test + public void testNestedClass5() { + assertThat((new TinyFrameworkNestedClasses()).new InnerClass().value).isEqualTo(5); + } + + @Test + public void testNestedClass6() { + assertThat(new TinyFrameworkNestedClasses.StaticNestedClass().value).isEqualTo(6); + } + + @Test + public void testNestedClass7() { + assertThat(TinyFrameworkNestedClasses.StaticNestedClass.getSupplier_static().get()) + .isEqualTo(7); + } + + @Test + public void testLambda1() { + assertThat(new TinyFrameworkLambdas().mSupplier.get()).isEqualTo(1); + } + + @Test + public void testLambda2() { + assertThat(TinyFrameworkLambdas.sSupplier.get()).isEqualTo(2); + } + + @Test + public void testLambda3() { + assertThat(new TinyFrameworkLambdas().getSupplier().get()).isEqualTo(3); + } + + @Test + public void testLambda4() { + assertThat(TinyFrameworkLambdas.getSupplier_static().get()).isEqualTo(4); + } + + @Test + public void testLambda5() { + assertThat(new TinyFrameworkLambdas.Nested().mSupplier.get()).isEqualTo(5); + } + + @Test + public void testLambda6() { + assertThat(TinyFrameworkLambdas.Nested.sSupplier.get()).isEqualTo(6); + } + + @Test + public void testLambda7() { + assertThat(new TinyFrameworkLambdas.Nested().getSupplier().get()).isEqualTo(7); + } + + @Test + public void testLambda8() { + assertThat(TinyFrameworkLambdas.Nested.getSupplier_static().get()).isEqualTo(8); + } + + @Test + public void testNativeSubstitutionClass() { + assertThat(TinyFrameworkNative.nativeAddTwo(3)).isEqualTo(5); + } + + @Test + public void testNativeSubstitutionClass_nonStatic() { + TinyFrameworkNative instance = new TinyFrameworkNative(); + instance.setValue(5); + assertThat(instance.nativeNonStaticAddToValue(3)).isEqualTo(8); + } + + @Test + public void testExitLog() { + thrown.expect(RuntimeException.class); + thrown.expectMessage("Outer exception"); + + TinyFrameworkExceptionTester.testException(); + + } + + @Test + public void testMethodCallBeforeSuperCall() { + assertThat(new SubClass(3).value).isEqualTo(3); + } + + @Test + public void testClassLoadHook() { + assertThat(TinyFrameworkClassWithInitializerStub.sInitialized).isTrue(); + + // Having this line before assertThat() will ensure these class are already loaded. + var classes = new Class[]{ + TinyFrameworkClassWithInitializerStub.class, + TinyFrameworkClassAnnotations.class, + TinyFrameworkForTextPolicy.class, + }; + + // The following classes have a class load hook, so they should be registered. + assertThat(TinyFrameworkClassLoadHook.sLoadedClasses) + .containsAnyIn(classes); + + // This class doesn't have a class load hook, so shouldn't be included. + assertThat(TinyFrameworkClassLoadHook.sLoadedClasses) + .doesNotContain(TinyFrameworkNestedClasses.class); + } + + @Test + public void testStaticInitializer_Default() { + assertThat(TinyFrameworkClassWithInitializerDefault.sInitialized).isFalse(); + assertThat(TinyFrameworkClassWithInitializerDefault.sObject).isNull(); + } + + @Test + public void testStaticInitializer_Stub() { + assertThat(TinyFrameworkClassWithInitializerStub.sInitialized).isTrue(); + assertThat(TinyFrameworkClassWithInitializerStub.sObject).isNotNull(); + } + + /** + * Test to try accessing JDK private fields using reflections + setAccessible(true), + * which is now disallowed due to Java Modules, unless you run the javacommand with. + * --add-opens=java.base/java.io=ALL-UNNAMED + * + * You can try it from the command line, like: + * $ JAVA_OPTS="--add-opens=java.base/java.io=ALL-UNNAMED" ./run-test-manually.sh + * + * @throws Exception + */ + @Test + public void testFileDescriptor() throws Exception { + var fd = FileDescriptor.out; + + // Get the FD value directly from the private field. + // This is now prohibited due to Java Modules. + // It throws: + // java.lang.reflect.InaccessibleObjectException: Unable to make field private int java.io.FileDescriptor.fd accessible: module java.base does not "opens java.io" to unnamed module @3bb50eaa + + thrown.expect(java.lang.reflect.InaccessibleObjectException.class); + + // Access the private field. + final Field f = FileDescriptor.class.getDeclaredField("fd"); + final Method m = FileDescriptor.class.getDeclaredMethod("set", int.class); + f.setAccessible(true); + m.setAccessible(true); + + assertThat(f.get(fd)).isEqualTo(1); + + // Set + f.set(fd, 2); + assertThat(f.get(fd)).isEqualTo(2); + + // Call the package private method, set(int). + m.invoke(fd, 0); + assertThat(f.get(fd)).isEqualTo(0); + } + + @Test + public void testPackageRedirect() throws Exception { + assertThat(TinyFrameworkPackageRedirect.foo(1)).isEqualTo(1); + } + + @Test + public void testEnumSimple() throws Exception { + assertThat(TinyFrameworkEnumSimple.CAT.ordinal()).isEqualTo(0); + assertThat(TinyFrameworkEnumSimple.CAT.name()).isEqualTo("CAT"); + + assertThat(TinyFrameworkEnumSimple.DOG.ordinal()).isEqualTo(1); + assertThat(TinyFrameworkEnumSimple.DOG.name()).isEqualTo("DOG"); + + assertThat(TinyFrameworkEnumSimple.valueOf("DOG").ordinal()).isEqualTo(1); + + assertThat(TinyFrameworkEnumSimple.values()).isEqualTo( + new TinyFrameworkEnumSimple[] { + TinyFrameworkEnumSimple.CAT, + TinyFrameworkEnumSimple.DOG, + } + ); + } + + @Test + public void testEnumComplex() throws Exception { + assertThat(TinyFrameworkEnumComplex.RED.ordinal()).isEqualTo(0); + assertThat(TinyFrameworkEnumComplex.RED.name()).isEqualTo("RED"); + + assertThat(TinyFrameworkEnumComplex.RED.getShortName()).isEqualTo("R"); + + assertThat(TinyFrameworkEnumComplex.GREEN.ordinal()).isEqualTo(1); + assertThat(TinyFrameworkEnumComplex.GREEN.name()).isEqualTo("GREEN"); + + assertThat(TinyFrameworkEnumComplex.valueOf("BLUE").ordinal()).isEqualTo(2); + + assertThat(TinyFrameworkEnumComplex.values()).isEqualTo( + new TinyFrameworkEnumComplex[] { + TinyFrameworkEnumComplex.RED, + TinyFrameworkEnumComplex.GREEN, + TinyFrameworkEnumComplex.BLUE, + } + ); + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java new file mode 100644 index 000000000000..20cc2ec9d50d --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class TinyFrameworkClassWithAnnotTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testSimple() { + TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations(); + assertThat(tfc.addOne(1)).isEqualTo(2); + assertThat(tfc.stub).isEqualTo(1); + } + +// @Test +// public void testDoesntCompile() { +// TinyFrameworkClassWithAnnot tfc = new TinyFrameworkClassWithAnnot(); +// +// tfc.addOneInner(1); // Shouldn't compile. +// tfc.toBeRemoved("abc"); // Shouldn't compile. +// tfc.unsupportedMethod(); // Shouldn't compile. +// int a = tfc.keep; // Shouldn't compile +// int b = tfc.remove; // Shouldn't compile +// } + + @Test + public void testSubstitute() { + TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations(); + assertThat(tfc.addTwo(1)).isEqualTo(3); + } + + @Test + public void testSubstituteNative() { + TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations(); + assertThat(tfc.nativeAddThree(1)).isEqualTo(4); + } + + @Test + public void testVisibleButUsesUnsupportedMethod() { + TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations(); + + thrown.expect(RuntimeException.class); + thrown.expectMessage("This method is not supported on the host side"); + tfc.visibleButUsesUnsupportedMethod(); + } +} diff --git a/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt new file mode 100644 index 000000000000..f6515142ccdb --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.utils + +import com.android.hoststubgen.ParseException +import com.google.common.truth.Truth.assertThat +import org.junit.Assert.fail +import org.junit.Test + +class ClassFilterTest { + @Test + fun testDefaultTrue() { + val f = ClassFilter.newNullFilter(true) + assertThat(f.matches("a/b/c")).isEqualTo(true) + } + + @Test + fun testDefaultFalse() { + val f = ClassFilter.newNullFilter(false) + assertThat(f.matches("a/b/c")).isEqualTo(false) + } + + @Test + fun testComplex1() { + val f = ClassFilter.buildFromString(""" + # ** this is a comment ** + a.b.c # allow + !a.b.d # disallow + * # allow all + """.trimIndent(), false, "X") + assertThat(f.getCacheSizeForTest()).isEqualTo(0) + + assertThat(f.matches("a/b/c")).isEqualTo(true) + assertThat(f.getCacheSizeForTest()).isEqualTo(1) + + assertThat(f.matches("a/b/d")).isEqualTo(false) + assertThat(f.matches("x")).isEqualTo(true) + + assertThat(f.getCacheSizeForTest()).isEqualTo(3) + + // Make sure the cache is working + assertThat(f.matches("x")).isEqualTo(true) + } + + @Test + fun testComplex2() { + val f = ClassFilter.buildFromString(""" + a.b.c # allow + !a.* # disallow everything else in package "a". + !d.e.f # disallow d.e.f. + + # everything else is allowed by default + """.trimIndent(), true, "X") + assertThat(f.matches("a/b/c")).isEqualTo(true) + assertThat(f.matches("a/x")).isEqualTo(false) + assertThat(f.matches("d/e/f")).isEqualTo(false) + assertThat(f.matches("d/e/f/g")).isEqualTo(true) + assertThat(f.matches("x")).isEqualTo(true) + } + + @Test + fun testBadFilter1() { + try { + ClassFilter.buildFromString(""" + a* + """.trimIndent(), true, "FILENAME") + fail("ParseException didn't happen") + } catch (e: ParseException) { + assertThat(e.message).contains("Wildcard") + assertThat(e.message).contains("FILENAME") + assertThat(e.message).contains("line 1") + } + } +}
\ No newline at end of file diff --git a/tools/xmlpersistence/Android.bp b/tools/hoststubgen/scripts/Android.bp index 0b6dba626794..b1ba07ec540d 100644 --- a/tools/xmlpersistence/Android.bp +++ b/tools/hoststubgen/scripts/Android.bp @@ -7,14 +7,14 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -java_binary_host { - name: "xmlpersistence_cli", - manifest: "manifest.txt", - srcs: [ - "src/**/*.kt", - ], - static_libs: [ - "javaparser-symbol-solver", - "javapoet", - ], +sh_binary_host { + name: "dump-jar", + src: "dump-jar", + visibility: ["//visibility:public"], +} + +genrule_defaults { + name: "hoststubgen-jar-dump-defaults", + tools: ["dump-jar"], + cmd: "$(location dump-jar) -s -o $(out) $(in)", } diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh new file mode 100755 index 000000000000..72681234dad8 --- /dev/null +++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Script to build `framework-host-stub` and `framework-host-impl`, and copy the +# generated jars to $out, and unzip them. Useful for looking into the generated files. + +source "${0%/*}"/../common.sh + +out=framework-all-stub-out + +rm -fr $out +mkdir -p $out + +# Build the jars with `m`. +run m framework-all-hidden-api-host + +# Copy the jar to out/ and extract them. +run cp \ + $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/* \ + $out + +extract $out/*.jar diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh new file mode 100755 index 000000000000..c3605a9ffaa5 --- /dev/null +++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Script to build hoststubgen and run it directly (without using the build rules) +# on framework-all.jar. + + +echo "THIS SCRIPT IS BROKEN DUE TO CHANGES TO FILE PATHS TO DEPENDENT FILES. FIX IT WHEN YOU NEED TO USE IT." 1>&2 + +exit 99 + + +source "${0%/*}"/../common.sh + +out=out + +mkdir -p $out + +# Build the tool and target jar. +run m hoststubgen framework-all + +base_args=( + @../hoststubgen/hoststubgen-standard-options.txt + + --in-jar $ANDROID_BUILD_TOP/out/soong/.intermediates/frameworks/base/framework-all/android_common/combined/framework-all.jar + --policy-override-file ../hoststubgen/framework-policy-override.txt "${@}" + + # This file will contain all classes as an annotation file, with "keep all" policy. + --gen-keep-all-file $out/framework-all-keep-all-policy.txt + + # This file will contains dump of all classes in the input jar. + --gen-input-dump-file $out/framework-all-dump.txt +) + +do_it() { + local out_file_stem="$1" + shift + local extra_args=("${@}") + + run hoststubgen \ + "${base_args[@]}" \ + "${extra_args[@]}" \ + --out-stub-jar ${out_file_stem}_stub.jar \ + --out-impl-jar ${out_file_stem}_impl.jar \ + $HOSTSTUBGEN_OPTS + + # Extract the jar files, so we can look into them. + run extract ${out_file_stem}_*.jar +} + +#----------------------------------------------------------------------------- +# framework-all, with all hidden APIs. +#----------------------------------------------------------------------------- + +# No extra args. +do_it $out/framework-all_host + +#----------------------------------------------------------------------------- +# framework-test-api, only public/system/test-APIs in the stub. +#----------------------------------------------------------------------------- + +do_it $out/framework-test-api_host \ + --intersect-stub-jar $SOONG_INT/frameworks/base/api/android_test_stubs_current/android_common/combined/*.jar diff --git a/tools/hoststubgen/scripts/dump-jar b/tools/hoststubgen/scripts/dump-jar new file mode 100755 index 000000000000..992665ed58ee --- /dev/null +++ b/tools/hoststubgen/scripts/dump-jar @@ -0,0 +1,165 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + + +help() { + cat <<'EOF' + + dump-jar: Dump java classes in jar files + + Usage: + dump-jar [-v] CLASS-FILE [...] + + Dump a *.class file + + dump-jar [-v] [-s] [-o OUTPUT-FILENAME] JAR-FILE[: filename regex] [...] + + Dump a jar file. + + If a filename contains a ':', then the following part + will be used to filter files in the jar file. + + For example, "file.jar:/MyClass$" will only dump "MyClass" in file.jar. + + Options: + -v: Enable verbose output. + + -s: Simple output mode, used to check HostStubGen output jars. + + -o: Write the output to a specified file. +EOF +} + +# Parse the options. + +verbose=0 +simple=0 +output="" +while getopts "hvso:" opt; do +case "$opt" in + h) + help + exit 0 + ;; + v) + verbose=1 + ;; + s) + simple=1 + ;; + o) + output="$OPTARG" + ;; + '?') + help + exit 1 + ;; +esac +done +shift $(($OPTIND - 1)) + +JAVAP_OPTS="${JAVAP_OPTS:--v -p -s -sysinfo -constants}" + +if (( $simple )) ; then + JAVAP_OPTS="-p -c -v" +fi + + +# Normalize a java class name. +# Convert '.' to '/' +# Remove the *.class suffix. +normalize() { + local name="$1" + name="${name%.class}" # Remove the .class suffix. + echo "$name" | tr '.' '/' +} + +# Convert the output for `-s` as needed. +filter_output() { + if (( $simple )) ; then + # For "simple output" mode, + # - Normalize the constant numbers (replace with "#x") + # - Normalize byte code offsets and other similar numbers. (e.g. "0:" -> "x:") + # - Remove the constant pool + # - Remove the line number table + # - Some other transient lines + # + # `/PATTERN-1/,/PATTERN-1/{//!d}` is a trick to delete lines between two patterns, without + # the start and the end lines. + sed -e 's/#[0-9][0-9]*/#x/g' \ + -e 's/^\( *\)[0-9][0-9]*:/\1x:/' \ + -e '/^Constant pool:/,/^[^ ]/{//!d}' \ + -e '/^ *line *[0-9][0-9]*: *[0-9][0-9]*$/d' \ + -e '/SHA-256 checksum/d' \ + -e '/Last modified/d' \ + -e '/^Classfile jar/d' + else + cat # Print as-is. + fi +} + +# Write to the output file (specified with -o) as needed. +write_to_out() { + if [[ -n "$output" ]] ; then + cat >"$output" + echo "Wrote output to $output" 1>&2 + else + cat # print to stdout + fi +} + +for file in "${@}"; do + + # *.class? + if echo "$file" | grep -qE '\.class$' ; then + echo "# Class: $file" 1>&2 + javap $dump_code_opt $JAVAP_OPTS $file + + # *.jar? + elif echo "$file" | grep -qE '\.jar(:.*)?$' ; then + # Take the regex. Remove everything up to : in $file + regex="" + if [[ "$file" =~ : ]] ; then + regex="$(normalize "${file##*:}")" + fi + + # Remove everything after ':', inclusively, in $file. + file="${file%:*}" + + # Print the filename and the regex. + if ! (( $simple )) ; then + echo -n "# Jar: $file" + if [[ "$regex" != "" ]] ;then + echo -n " (regex: $regex)" + fi + echo + fi + + jar tf "$file" | grep '\.class$' | sort | while read -r class ; do + if normalize "$class" | grep -q -- "$regex" ; then + echo "## Class: $class" + javap $dump_code_opt $JAVAP_OPTS -cp $file ${class%.class} + else + (( $verbose )) && echo "## Skipping class: $class" + fi + done + + else + echo "Unknown file type: $file" 1>&2 + exit 1 + fi +done | filter_output | write_to_out diff --git a/tools/hoststubgen/scripts/run-all-tests.sh b/tools/hoststubgen/scripts/run-all-tests.sh new file mode 100755 index 000000000000..82faa91e2cac --- /dev/null +++ b/tools/hoststubgen/scripts/run-all-tests.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +source "${0%/*}"/../common.sh + +# Move to the top directory of hoststubgen +cd .. + +# These tests are known to pass. +READY_TEST_MODULES=( + HostStubGenTest-framework-all-test-host-test + hoststubgen-test-tiny-test + CtsUtilTestCasesRavenwood +) + +MUST_BUILD_MODULES=( + "${NOT_READY_TEST_MODULES[*]}" + HostStubGenTest-framework-test +) + +# First, build all the test / etc modules. This shouldn't fail. +run m "${MUST_BUILD_MODULES[@]}" + +# Run the hoststubgen unittests / etc +run atest hoststubgentest hoststubgen-invoke-test + +# Next, run the golden check. This should always pass too. +# The following scripts _should_ pass too, but they depend on the internal paths to soong generated +# files, and they may fail when something changes in the build system. +run ./hoststubgen/test-tiny-framework/diff-and-update-golden.sh + +run ./hoststubgen/test-framework/run-test-without-atest.sh + +run ./hoststubgen/test-tiny-framework/run-test-manually.sh +run atest tiny-framework-dump-test +run ./scripts/build-framework-hostside-jars-and-extract.sh + +# This script is already broken on goog/master +# run ./scripts/build-framework-hostside-jars-without-genrules.sh + +# These tests should all pass. +run atest ${READY_TEST_MODULES[*]} + +echo ""${0##*/}" finished, with no unexpected failures. Ready to submit!"
\ No newline at end of file diff --git a/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt index f1727b78f135..a18ed1555998 100644 --- a/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt @@ -29,9 +29,10 @@ val AIDL_PERMISSION_ANNOTATIONS = listOf( const val BINDER_CLASS = "android.os.Binder" const val IINTERFACE_INTERFACE = "android.os.IInterface" -const val AIDL_PERMISSION_HELPER_SUFFIX = "_enforcePermission" const val PERMISSION_PREFIX_LITERAL = "android.permission." +const val AIDL_PERMISSION_HELPER_SUFFIX = "_enforcePermission" + /** * If a non java (e.g. c++) backend is enabled, the @EnforcePermission * annotation cannot be used. At time of writing, the mechanism diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt index c7be36efd991..22f749eee36b 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt +++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt @@ -53,10 +53,9 @@ class SimpleManualPermissionEnforcementDetector : AidlImplementationDetector() { lintFix ) - // TODO(b/265014041): turn on errors once all code that would cause one is fixed - // if (enforcePermissionFix.errorLevel) { - // incident.overrideSeverity(Severity.ERROR) - // } + if (enforcePermissionFix.errorLevel) { + incident.overrideSeverity(Severity.ERROR) + } context.report(incident) } diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt index 6b8e72cf9222..9170e752934f 100644 --- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt +++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt @@ -51,10 +51,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:7: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:7: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( @@ -168,10 +168,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:8: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] mContext.enforceCallingOrSelfPermission( ^ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( @@ -209,10 +209,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:8: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS, "foo"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( @@ -252,10 +252,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:10: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:10: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] mContext.enforceCallingOrSelfPermission( ^ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( @@ -414,10 +414,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:14: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:14: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] helper(); ~~~~~~~~~ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( @@ -506,10 +506,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:16: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:16: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] mContext.enforceCallingOrSelfPermission("FOO", "foo"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( @@ -558,10 +558,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:19: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:19: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] helperHelper(); ~~~~~~~~~~~~~~~ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( @@ -599,10 +599,10 @@ class SimpleManualPermissionEnforcementDetectorTest : LintDetectorTest() { .run() .expect( """ - src/Foo.java:7: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] + src/Foo.java:7: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement] if (mContext.checkCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo") ^ - 0 errors, 1 warnings + 1 errors, 0 warnings """ ) .expectFixDiffs( diff --git a/tools/streaming_proto/OWNERS b/tools/streaming_proto/OWNERS new file mode 100644 index 000000000000..5f6e59f82c8a --- /dev/null +++ b/tools/streaming_proto/OWNERS @@ -0,0 +1 @@ +mwachens@google.com diff --git a/tools/streaming_proto/cpp/main.cpp b/tools/streaming_proto/cpp/main.cpp index fe9a438d81d7..905ed354049b 100644 --- a/tools/streaming_proto/cpp/main.cpp +++ b/tools/streaming_proto/cpp/main.cpp @@ -119,9 +119,8 @@ write_message(stringstream& text, const DescriptorProto& message, const string& text << endl; } -static void -write_header_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor) -{ +static void write_header_file(const string& request_parameter, CodeGeneratorResponse* response, + const FileDescriptorProto& file_descriptor) { stringstream text; text << "// Generated by protoc-gen-cppstream. DO NOT MODIFY." << endl; @@ -159,6 +158,9 @@ write_header_file(CodeGeneratorResponse* response, const FileDescriptorProto& fi text << endl; text << "#endif // " << header << endl; + if (request_parameter.find("experimental_allow_proto3_optional") != string::npos) { + response->set_supported_features(CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL); + } CodeGeneratorResponse::File* file_response = response->add_file(); file_response->set_name(make_filename(file_descriptor)); file_response->set_content(text.str()); @@ -182,7 +184,7 @@ int main(int argc, char const *argv[]) for (int i=0; i<N; i++) { const FileDescriptorProto& file_descriptor = request.proto_file(i); if (should_generate_for_file(request, file_descriptor.name())) { - write_header_file(&response, file_descriptor); + write_header_file(request.parameter(), &response, file_descriptor); } } diff --git a/tools/xmlpersistence/OWNERS b/tools/xmlpersistence/OWNERS deleted file mode 100644 index 4f4d06a32676..000000000000 --- a/tools/xmlpersistence/OWNERS +++ /dev/null @@ -1 +0,0 @@ -zhanghai@google.com diff --git a/tools/xmlpersistence/manifest.txt b/tools/xmlpersistence/manifest.txt deleted file mode 100644 index 6d9771998efc..000000000000 --- a/tools/xmlpersistence/manifest.txt +++ /dev/null @@ -1 +0,0 @@ -Main-class: MainKt diff --git a/tools/xmlpersistence/src/main/kotlin/Generator.kt b/tools/xmlpersistence/src/main/kotlin/Generator.kt deleted file mode 100644 index 8e62388c860f..000000000000 --- a/tools/xmlpersistence/src/main/kotlin/Generator.kt +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.squareup.javapoet.ClassName -import com.squareup.javapoet.FieldSpec -import com.squareup.javapoet.JavaFile -import com.squareup.javapoet.MethodSpec -import com.squareup.javapoet.NameAllocator -import com.squareup.javapoet.ParameterSpec -import com.squareup.javapoet.TypeSpec -import java.io.File -import java.io.FileInputStream -import java.io.FileNotFoundException -import java.io.FileOutputStream -import java.io.IOException -import java.nio.charset.StandardCharsets -import java.time.Year -import java.util.Objects -import javax.lang.model.element.Modifier - -// JavaPoet only supports line comments, and can't add a newline after file level comments. -val FILE_HEADER = """ - /* - * Copyright (C) ${Year.now().value} The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - // Generated by xmlpersistence. DO NOT MODIFY! - // CHECKSTYLE:OFF Generated code - // @formatter:off -""".trimIndent() + "\n\n" - -private val atomicFileType = ClassName.get("android.util", "AtomicFile") - -fun generate(persistence: PersistenceInfo): JavaFile { - val distinctClassFields = persistence.root.allClassFields.distinctBy { it.type } - val type = TypeSpec.classBuilder(persistence.name) - .addJavadoc( - """ - Generated class implementing XML persistence for${'$'}W{@link $1T}. - <p> - This class provides atomicity for persistence via {@link $2T}, however it does not provide - thread safety, so please bring your own synchronization mechanism. - """.trimIndent(), persistence.root.type, atomicFileType - ) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addField(generateFileField()) - .addMethod(generateConstructor()) - .addMethod(generateReadMethod(persistence.root)) - .addMethod(generateParseMethod(persistence.root)) - .addMethods(distinctClassFields.map { generateParseClassMethod(it) }) - .addMethod(generateWriteMethod(persistence.root)) - .addMethod(generateSerializeMethod(persistence.root)) - .addMethods(distinctClassFields.map { generateSerializeClassMethod(it) }) - .addMethod(generateDeleteMethod()) - .build() - return JavaFile.builder(persistence.root.type.packageName(), type) - .skipJavaLangImports(true) - .indent(" ") - .build() -} - -private val nonNullType = ClassName.get("android.annotation", "NonNull") - -private fun generateFileField(): FieldSpec = - FieldSpec.builder(atomicFileType, "mFile", Modifier.PRIVATE, Modifier.FINAL) - .addAnnotation(nonNullType) - .build() - -private fun generateConstructor(): MethodSpec = - MethodSpec.constructorBuilder() - .addJavadoc( - """ - Create an instance of this class. - - @param file the XML file for persistence - """.trimIndent() - ) - .addModifiers(Modifier.PUBLIC) - .addParameter( - ParameterSpec.builder(File::class.java, "file").addAnnotation(nonNullType).build() - ) - .addStatement("mFile = new \$1T(file)", atomicFileType) - .build() - -private val nullableType = ClassName.get("android.annotation", "Nullable") - -private val xmlPullParserType = ClassName.get("org.xmlpull.v1", "XmlPullParser") - -private val xmlType = ClassName.get("android.util", "Xml") - -private val xmlPullParserExceptionType = ClassName.get("org.xmlpull.v1", "XmlPullParserException") - -private fun generateReadMethod(rootField: ClassFieldInfo): MethodSpec = - MethodSpec.methodBuilder("read") - .addJavadoc( - """ - Read${'$'}W{@link $1T}${'$'}Wfrom${'$'}Wthe${'$'}WXML${'$'}Wfile. - - @return the persisted${'$'}W{@link $1T},${'$'}Wor${'$'}W{@code null}${'$'}Wif${'$'}Wthe${'$'}WXML${'$'}Wfile${'$'}Wdoesn't${'$'}Wexist - @throws IllegalArgumentException if an error occurred while reading - """.trimIndent(), rootField.type - ) - .addAnnotation(nullableType) - .addModifiers(Modifier.PUBLIC) - .returns(rootField.type) - .addControlFlow("try (\$1T inputStream = mFile.openRead())", FileInputStream::class.java) { - addStatement("final \$1T parser = \$2T.newPullParser()", xmlPullParserType, xmlType) - addStatement("parser.setInput(inputStream, null)") - addStatement("return parse(parser)") - nextControlFlow("catch (\$1T e)", FileNotFoundException::class.java) - addStatement("return null") - nextControlFlow( - "catch (\$1T | \$2T e)", IOException::class.java, xmlPullParserExceptionType - ) - addStatement("throw new IllegalArgumentException(e)") - } - .build() - -private val ClassFieldInfo.allClassFields: List<ClassFieldInfo> - get() = - mutableListOf<ClassFieldInfo>().apply { - this += this@allClassFields - for (field in fields) { - when (field) { - is ClassFieldInfo -> this += field.allClassFields - is ListFieldInfo -> this += field.element.allClassFields - else -> {} - } - } - } - -private fun generateParseMethod(rootField: ClassFieldInfo): MethodSpec = - MethodSpec.methodBuilder("parse") - .addAnnotation(nonNullType) - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .returns(rootField.type) - .addParameter( - ParameterSpec.builder(xmlPullParserType, "parser").addAnnotation(nonNullType).build() - ) - .addExceptions(listOf(ClassName.get(IOException::class.java), xmlPullParserExceptionType)) - .apply { - addStatement("int type") - addStatement("int depth") - addStatement("int innerDepth = parser.getDepth() + 1") - addControlFlow( - "while ((type = parser.next()) != \$1T.END_DOCUMENT\$W" - + "&& ((depth = parser.getDepth()) >= innerDepth || type != \$1T.END_TAG))", - xmlPullParserType - ) { - addControlFlow( - "if (depth > innerDepth || type != \$1T.START_TAG)", xmlPullParserType - ) { - addStatement("continue") - } - addControlFlow( - "if (\$1T.equals(parser.getName(),\$W\$2S))", Objects::class.java, - rootField.tagName - ) { - addStatement("return \$1L(parser)", rootField.parseMethodName) - } - } - addStatement( - "throw new IllegalArgumentException(\$1S)", - "Missing root tag <${rootField.tagName}>" - ) - } - .build() - -private fun generateParseClassMethod(classField: ClassFieldInfo): MethodSpec = - MethodSpec.methodBuilder(classField.parseMethodName) - .addAnnotation(nonNullType) - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .returns(classField.type) - .addParameter( - ParameterSpec.builder(xmlPullParserType, "parser").addAnnotation(nonNullType).build() - ) - .apply { - val (attributeFields, tagFields) = classField.fields - .partition { it is PrimitiveFieldInfo || it is StringFieldInfo } - if (tagFields.isNotEmpty()) { - addExceptions( - listOf(ClassName.get(IOException::class.java), xmlPullParserExceptionType) - ) - } - val nameAllocator = NameAllocator().apply { - newName("parser") - newName("type") - newName("depth") - newName("innerDepth") - } - for (field in attributeFields) { - val variableName = nameAllocator.newName(field.variableName, field) - when (field) { - is PrimitiveFieldInfo -> { - val stringVariableName = - nameAllocator.newName("${field.variableName}String") - addStatement( - "final String \$1L =\$Wparser.getAttributeValue(null,\$W\$2S)", - stringVariableName, field.attributeName - ) - if (field.isRequired) { - addControlFlow("if (\$1L == null)", stringVariableName) { - addStatement( - "throw new IllegalArgumentException(\$1S)", - "Missing attribute \"${field.attributeName}\"" - ) - } - } - val boxedType = field.type.box() - val parseTypeMethodName = if (field.type.isPrimitive) { - "parse${field.type.toString().capitalize()}" - } else { - "valueOf" - } - if (field.isRequired) { - addStatement( - "final \$1T \$2L =\$W\$3T.\$4L($5L)", field.type, variableName, - boxedType, parseTypeMethodName, stringVariableName - ) - } else { - addStatement( - "final \$1T \$2L =\$W$3L != null ?\$W\$4T.\$5L($3L)\$W: null", - field.type, variableName, stringVariableName, boxedType, - parseTypeMethodName - ) - } - } - is StringFieldInfo -> - addStatement( - "final String \$1L =\$Wparser.getAttributeValue(null,\$W\$2S)", - variableName, field.attributeName - ) - else -> error(field) - } - } - if (tagFields.isNotEmpty()) { - for (field in tagFields) { - val variableName = nameAllocator.newName(field.variableName, field) - when (field) { - is ClassFieldInfo -> - addStatement("\$1T \$2L =\$Wnull", field.type, variableName) - is ListFieldInfo -> - addStatement( - "final \$1T \$2L =\$Wnew \$3T<>()", field.type, variableName, - ArrayList::class.java - ) - else -> error(field) - } - } - addStatement("int type") - addStatement("int depth") - addStatement("int innerDepth = parser.getDepth() + 1") - addControlFlow( - "while ((type = parser.next()) != \$1T.END_DOCUMENT\$W" - + "&& ((depth = parser.getDepth()) >= innerDepth || type != \$1T.END_TAG))", - xmlPullParserType - ) { - addControlFlow( - "if (depth > innerDepth || type != \$1T.START_TAG)", xmlPullParserType - ) { - addStatement("continue") - } - addControlFlow("switch (parser.getName())") { - for (field in tagFields) { - addControlFlow("case \$1S:", field.tagName) { - val variableName = nameAllocator.get(field) - when (field) { - is ClassFieldInfo -> { - addControlFlow("if (\$1L != null)", variableName) { - addStatement( - "throw new IllegalArgumentException(\$1S)", - "Duplicate tag \"${field.tagName}\"" - ) - } - addStatement( - "\$1L =\$W\$2L(parser)", variableName, - field.parseMethodName - ) - addStatement("break") - } - is ListFieldInfo -> { - val elementNameAllocator = nameAllocator.clone() - val elementVariableName = elementNameAllocator.newName( - field.element.xmlName!!.toLowerCamelCase() - ) - addStatement( - "final \$1T \$2L =\$W\$3L(parser)", field.element.type, - elementVariableName, field.element.parseMethodName - ) - addStatement( - "\$1L.add(\$2L)", variableName, elementVariableName - ) - addStatement("break") - } - else -> error(field) - } - } - } - } - } - } - for (field in tagFields.filter { it is ClassFieldInfo && it.isRequired }) { - addControlFlow("if ($1L == null)", nameAllocator.get(field)) { - addStatement( - "throw new IllegalArgumentException(\$1S)", "Missing tag <${field.tagName}>" - ) - } - } - addStatement( - classField.fields.joinToString(",\$W", "return new \$1T(", ")") { - nameAllocator.get(it) - }, classField.type - ) - } - .build() - -private val ClassFieldInfo.parseMethodName: String - get() = "parse${type.simpleName().toUpperCamelCase()}" - -private val xmlSerializerType = ClassName.get("org.xmlpull.v1", "XmlSerializer") - -private fun generateWriteMethod(rootField: ClassFieldInfo): MethodSpec = - MethodSpec.methodBuilder("write") - .apply { - val nameAllocator = NameAllocator().apply { - newName("outputStream") - newName("serializer") - } - val parameterName = nameAllocator.newName(rootField.variableName) - addJavadoc( - """ - Write${'$'}W{@link $1T}${'$'}Wto${'$'}Wthe${'$'}WXML${'$'}Wfile. - - @param $2L the${'$'}W{@link ${'$'}1T}${'$'}Wto${'$'}Wpersist - """.trimIndent(), rootField.type, parameterName - ) - addAnnotation(nullableType) - addModifiers(Modifier.PUBLIC) - addParameter( - ParameterSpec.builder(rootField.type, parameterName) - .addAnnotation(nonNullType) - .build() - ) - addStatement("\$1T outputStream = null", FileOutputStream::class.java) - addControlFlow("try") { - addStatement("outputStream = mFile.startWrite()") - addStatement( - "final \$1T serializer =\$W\$2T.newSerializer()", xmlSerializerType, xmlType - ) - addStatement( - "serializer.setOutput(outputStream, \$1T.UTF_8.name())", - StandardCharsets::class.java - ) - addStatement( - "serializer.setFeature(\$1S, true)", - "http://xmlpull.org/v1/doc/features.html#indent-output" - ) - addStatement("serializer.startDocument(null, true)") - addStatement("serialize(serializer,\$W\$1L)", parameterName) - addStatement("serializer.endDocument()") - addStatement("mFile.finishWrite(outputStream)") - nextControlFlow("catch (Exception e)") - addStatement("e.printStackTrace()") - addStatement("mFile.failWrite(outputStream)") - } - } - .build() - -private fun generateSerializeMethod(rootField: ClassFieldInfo): MethodSpec = - MethodSpec.methodBuilder("serialize") - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .addParameter( - ParameterSpec.builder(xmlSerializerType, "serializer") - .addAnnotation(nonNullType) - .build() - ) - .apply { - val nameAllocator = NameAllocator().apply { newName("serializer") } - val parameterName = nameAllocator.newName(rootField.variableName) - addParameter( - ParameterSpec.builder(rootField.type, parameterName) - .addAnnotation(nonNullType) - .build() - ) - addException(IOException::class.java) - addStatement("serializer.startTag(null, \$1S)", rootField.tagName) - addStatement("\$1L(serializer, \$2L)", rootField.serializeMethodName, parameterName) - addStatement("serializer.endTag(null, \$1S)", rootField.tagName) - } - .build() - -private fun generateSerializeClassMethod(classField: ClassFieldInfo): MethodSpec = - MethodSpec.methodBuilder(classField.serializeMethodName) - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .addParameter( - ParameterSpec.builder(xmlSerializerType, "serializer") - .addAnnotation(nonNullType) - .build() - ) - .apply { - val nameAllocator = NameAllocator().apply { - newName("serializer") - newName("i") - } - val parameterName = nameAllocator.newName(classField.serializeParameterName) - addParameter( - ParameterSpec.builder(classField.type, parameterName) - .addAnnotation(nonNullType) - .build() - ) - addException(IOException::class.java) - val (attributeFields, tagFields) = classField.fields - .partition { it is PrimitiveFieldInfo || it is StringFieldInfo } - for (field in attributeFields) { - val variableName = "$parameterName.${field.name}" - if (!field.isRequired) { - beginControlFlow("if (\$1L != null)", variableName) - } - when (field) { - is PrimitiveFieldInfo -> { - if (field.isRequired && !field.type.isPrimitive) { - addControlFlow("if (\$1L == null)", variableName) { - addStatement( - "throw new IllegalArgumentException(\$1S)", - "Field \"${field.name}\" is null" - ) - } - } - val stringVariableName = - nameAllocator.newName("${field.variableName}String") - addStatement( - "final String \$1L =\$WString.valueOf(\$2L)", stringVariableName, - variableName - ) - addStatement( - "serializer.attribute(null, \$1S, \$2L)", field.attributeName, - stringVariableName - ) - } - is StringFieldInfo -> { - if (field.isRequired) { - addControlFlow("if (\$1L == null)", variableName) { - addStatement( - "throw new IllegalArgumentException(\$1S)", - "Field \"${field.name}\" is null" - ) - } - } - addStatement( - "serializer.attribute(null, \$1S, \$2L)", field.attributeName, - variableName - ) - } - else -> error(field) - } - if (!field.isRequired) { - endControlFlow() - } - } - for (field in tagFields) { - val variableName = "$parameterName.${field.name}" - if (field.isRequired) { - addControlFlow("if (\$1L == null)", variableName) { - addStatement( - "throw new IllegalArgumentException(\$1S)", - "Field \"${field.name}\" is null" - ) - } - } - when (field) { - is ClassFieldInfo -> { - addStatement("serializer.startTag(null, \$1S)", field.tagName) - addStatement( - "\$1L(serializer, \$2L)", field.serializeMethodName, variableName - ) - addStatement("serializer.endTag(null, \$1S)", field.tagName) - } - is ListFieldInfo -> { - val sizeVariableName = nameAllocator.newName("${field.variableName}Size") - addStatement( - "final int \$1L =\$W\$2L.size()", sizeVariableName, variableName - ) - addControlFlow("for (int i = 0;\$Wi < \$1L;\$Wi++)", sizeVariableName) { - val elementNameAllocator = nameAllocator.clone() - val elementVariableName = elementNameAllocator.newName( - field.element.xmlName!!.toLowerCamelCase() - ) - addStatement( - "final \$1T \$2L =\$W\$3L.get(i)", field.element.type, - elementVariableName, variableName - ) - addControlFlow("if (\$1L == null)", elementVariableName) { - addStatement( - "throw new IllegalArgumentException(\$1S\$W+ i\$W+ \$2S)", - "Field element \"${field.name}[", "]\" is null" - ) - } - addStatement("serializer.startTag(null, \$1S)", field.element.tagName) - addStatement( - "\$1L(serializer,\$W\$2L)", field.element.serializeMethodName, - elementVariableName - ) - addStatement("serializer.endTag(null, \$1S)", field.element.tagName) - } - } - else -> error(field) - } - } - } - .build() - -private val ClassFieldInfo.serializeMethodName: String - get() = "serialize${type.simpleName().toUpperCamelCase()}" - -private val ClassFieldInfo.serializeParameterName: String - get() = type.simpleName().toLowerCamelCase() - -private val FieldInfo.variableName: String - get() = name.toLowerCamelCase() - -private val FieldInfo.attributeName: String - get() { - check(this is PrimitiveFieldInfo || this is StringFieldInfo) - return xmlNameOrName.toLowerCamelCase() - } - -private val FieldInfo.tagName: String - get() { - check(this is ClassFieldInfo || this is ListFieldInfo) - return xmlNameOrName.toLowerKebabCase() - } - -private val FieldInfo.xmlNameOrName: String - get() = xmlName ?: name - -private fun generateDeleteMethod(): MethodSpec = - MethodSpec.methodBuilder("delete") - .addJavadoc("Delete the XML file, if any.") - .addModifiers(Modifier.PUBLIC) - .addStatement("mFile.delete()") - .build() - -private inline fun MethodSpec.Builder.addControlFlow( - controlFlow: String, - vararg args: Any, - block: MethodSpec.Builder.() -> Unit -): MethodSpec.Builder { - beginControlFlow(controlFlow, *args) - block() - endControlFlow() - return this -} diff --git a/tools/xmlpersistence/src/main/kotlin/Main.kt b/tools/xmlpersistence/src/main/kotlin/Main.kt deleted file mode 100644 index e271f8cb9361..000000000000 --- a/tools/xmlpersistence/src/main/kotlin/Main.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.io.File -import java.nio.file.Files - -fun main(args: Array<String>) { - val showUsage = args.isEmpty() || when (args.singleOrNull()) { - "-h", "--help" -> true - else -> false - } - if (showUsage) { - usage() - return - } - - val files = args.flatMap { - File(it).walk().filter { it.isFile && it.extension == "java" }.map { it.toPath() } - } - val persistences = parse(files) - for (persistence in persistences) { - val file = generate(persistence) - Files.newBufferedWriter(persistence.path).use { - it.write(FILE_HEADER) - file.writeTo(it) - } - } -} - -private fun usage() { - println("Usage: xmlpersistence <FILES>") -} diff --git a/tools/xmlpersistence/src/main/kotlin/Parser.kt b/tools/xmlpersistence/src/main/kotlin/Parser.kt deleted file mode 100644 index 3ea12a9aa389..000000000000 --- a/tools/xmlpersistence/src/main/kotlin/Parser.kt +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.github.javaparser.JavaParser -import com.github.javaparser.ParseProblemException -import com.github.javaparser.ParseResult -import com.github.javaparser.ParserConfiguration -import com.github.javaparser.ast.Node -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration -import com.github.javaparser.ast.body.FieldDeclaration -import com.github.javaparser.ast.body.TypeDeclaration -import com.github.javaparser.ast.expr.AnnotationExpr -import com.github.javaparser.ast.expr.Expression -import com.github.javaparser.ast.expr.NormalAnnotationExpr -import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr -import com.github.javaparser.ast.expr.StringLiteralExpr -import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration -import com.github.javaparser.resolution.types.ResolvedPrimitiveType -import com.github.javaparser.resolution.types.ResolvedReferenceType -import com.github.javaparser.symbolsolver.JavaSymbolSolver -import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration -import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver -import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver -import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver -import com.squareup.javapoet.ClassName -import com.squareup.javapoet.ParameterizedTypeName -import com.squareup.javapoet.TypeName -import java.nio.file.Path -import java.util.Optional - -class PersistenceInfo( - val name: String, - val root: ClassFieldInfo, - val path: Path -) - -sealed class FieldInfo { - abstract val name: String - abstract val xmlName: String? - abstract val type: TypeName - abstract val isRequired: Boolean -} - -class PrimitiveFieldInfo( - override val name: String, - override val xmlName: String?, - override val type: TypeName, - override val isRequired: Boolean -) : FieldInfo() - -class StringFieldInfo( - override val name: String, - override val xmlName: String?, - override val isRequired: Boolean -) : FieldInfo() { - override val type: TypeName = ClassName.get(String::class.java) -} - -class ClassFieldInfo( - override val name: String, - override val xmlName: String?, - override val type: ClassName, - override val isRequired: Boolean, - val fields: List<FieldInfo> -) : FieldInfo() - -class ListFieldInfo( - override val name: String, - override val xmlName: String?, - override val type: ParameterizedTypeName, - val element: ClassFieldInfo -) : FieldInfo() { - override val isRequired: Boolean = true -} - -fun parse(files: List<Path>): List<PersistenceInfo> { - val typeSolver = CombinedTypeSolver().apply { add(ReflectionTypeSolver()) } - val javaParser = JavaParser(ParserConfiguration() - .setSymbolResolver(JavaSymbolSolver(typeSolver))) - val compilationUnits = files.map { javaParser.parse(it).getOrThrow() } - val memoryTypeSolver = MemoryTypeSolver().apply { - for (compilationUnit in compilationUnits) { - for (typeDeclaration in compilationUnit.getNodesByClass<TypeDeclaration<*>>()) { - val name = typeDeclaration.fullyQualifiedName.getOrNull() ?: continue - addDeclaration(name, typeDeclaration.resolve()) - } - } - } - typeSolver.add(memoryTypeSolver) - return mutableListOf<PersistenceInfo>().apply { - for (compilationUnit in compilationUnits) { - val classDeclarations = compilationUnit - .getNodesByClass<ClassOrInterfaceDeclaration>() - .filter { !it.isInterface && (!it.isNestedType || it.isStatic) } - this += classDeclarations.mapNotNull { parsePersistenceInfo(it) } - } - } -} - -private fun parsePersistenceInfo(classDeclaration: ClassOrInterfaceDeclaration): PersistenceInfo? { - val annotation = classDeclaration.getAnnotationByName("XmlPersistence").getOrNull() - ?: return null - val rootClassName = classDeclaration.nameAsString - val name = annotation.getMemberValue("value")?.stringLiteralValue - ?: "${rootClassName}Persistence" - val rootXmlName = classDeclaration.getAnnotationByName("XmlName").getOrNull() - ?.getMemberValue("value")?.stringLiteralValue - val root = parseClassFieldInfo( - rootXmlName ?: rootClassName, rootXmlName, true, classDeclaration - ) - val path = classDeclaration.findCompilationUnit().get().storage.get().path - .resolveSibling("$name.java") - return PersistenceInfo(name, root, path) -} - -private fun parseClassFieldInfo( - name: String, - xmlName: String?, - isRequired: Boolean, - classDeclaration: ClassOrInterfaceDeclaration -): ClassFieldInfo { - val fields = classDeclaration.fields.filterNot { it.isStatic }.map { parseFieldInfo(it) } - val type = classDeclaration.resolve().typeName - return ClassFieldInfo(name, xmlName, type, isRequired, fields) -} - -private fun parseFieldInfo(field: FieldDeclaration): FieldInfo { - require(field.isPublic && field.isFinal) - val variable = field.variables.single() - val name = variable.nameAsString - val annotations = field.annotations + variable.type.annotations - val annotation = annotations.getByName("XmlName") - val xmlName = annotation?.getMemberValue("value")?.stringLiteralValue - val isRequired = annotations.getByName("NonNull") != null - return when (val type = variable.type.resolve()) { - is ResolvedPrimitiveType -> { - val primitiveType = type.typeName - PrimitiveFieldInfo(name, xmlName, primitiveType, true) - } - is ResolvedReferenceType -> { - when (type.qualifiedName) { - Boolean::class.javaObjectType.name, Byte::class.javaObjectType.name, - Short::class.javaObjectType.name, Char::class.javaObjectType.name, - Integer::class.javaObjectType.name, Long::class.javaObjectType.name, - Float::class.javaObjectType.name, Double::class.javaObjectType.name -> - PrimitiveFieldInfo(name, xmlName, type.typeName, isRequired) - String::class.java.name -> StringFieldInfo(name, xmlName, isRequired) - List::class.java.name -> { - requireNotNull(xmlName) - val elementType = type.typeParametersValues().single() - require(elementType is ResolvedReferenceType) - val listType = ParameterizedTypeName.get( - ClassName.get(List::class.java), elementType.typeName - ) - val element = parseClassFieldInfo( - "(element)", xmlName, true, elementType.classDeclaration - ) - ListFieldInfo(name, xmlName, listType, element) - } - else -> parseClassFieldInfo(name, xmlName, isRequired, type.classDeclaration) - } - } - else -> error(type) - } -} - -private fun <T> ParseResult<T>.getOrThrow(): T = - if (isSuccessful) { - result.get() - } else { - throw ParseProblemException(problems) - } - -private inline fun <reified T : Node> Node.getNodesByClass(): List<T> = - getNodesByClass(T::class.java) - -private fun <T : Node> Node.getNodesByClass(klass: Class<T>): List<T> = mutableListOf<T>().apply { - if (klass.isInstance(this@getNodesByClass)) { - this += klass.cast(this@getNodesByClass) - } - for (childNode in childNodes) { - this += childNode.getNodesByClass(klass) - } -} - -private fun <T> Optional<T>.getOrNull(): T? = orElse(null) - -private fun List<AnnotationExpr>.getByName(name: String): AnnotationExpr? = - find { it.name.identifier == name } - -private fun AnnotationExpr.getMemberValue(name: String): Expression? = - when (this) { - is NormalAnnotationExpr -> pairs.find { it.nameAsString == name }?.value - is SingleMemberAnnotationExpr -> if (name == "value") memberValue else null - else -> null - } - -private val Expression.stringLiteralValue: String - get() { - require(this is StringLiteralExpr) - return value - } - -private val ResolvedReferenceType.classDeclaration: ClassOrInterfaceDeclaration - get() { - val resolvedClassDeclaration = typeDeclaration - require(resolvedClassDeclaration is JavaParserClassDeclaration) - return resolvedClassDeclaration.wrappedNode - } - -private val ResolvedPrimitiveType.typeName: TypeName - get() = - when (this) { - ResolvedPrimitiveType.BOOLEAN -> TypeName.BOOLEAN - ResolvedPrimitiveType.BYTE -> TypeName.BYTE - ResolvedPrimitiveType.SHORT -> TypeName.SHORT - ResolvedPrimitiveType.CHAR -> TypeName.CHAR - ResolvedPrimitiveType.INT -> TypeName.INT - ResolvedPrimitiveType.LONG -> TypeName.LONG - ResolvedPrimitiveType.FLOAT -> TypeName.FLOAT - ResolvedPrimitiveType.DOUBLE -> TypeName.DOUBLE - } - -// This doesn't support type parameters. -private val ResolvedReferenceType.typeName: TypeName - get() = typeDeclaration.typeName - -private val ResolvedReferenceTypeDeclaration.typeName: ClassName - get() { - val packageName = packageName - val classNames = className.split(".") - val topLevelClassName = classNames.first() - val nestedClassNames = classNames.drop(1) - return ClassName.get(packageName, topLevelClassName, *nestedClassNames.toTypedArray()) - } diff --git a/tools/xmlpersistence/src/main/kotlin/StringCaseExtensions.kt b/tools/xmlpersistence/src/main/kotlin/StringCaseExtensions.kt deleted file mode 100644 index b4bdbba7170b..000000000000 --- a/tools/xmlpersistence/src/main/kotlin/StringCaseExtensions.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.util.Locale - -private val camelHumpBoundary = Regex( - "-" - + "|_" - + "|(?<=[0-9])(?=[^0-9])" - + "|(?<=[A-Z])(?=[^A-Za-z]|[A-Z][a-z])" - + "|(?<=[a-z])(?=[^a-z])" -) - -private fun String.toCamelHumps(): List<String> = split(camelHumpBoundary) - -fun String.toUpperCamelCase(): String = - toCamelHumps().joinToString("") { it.toLowerCase(Locale.ROOT).capitalize(Locale.ROOT) } - -fun String.toLowerCamelCase(): String = toUpperCamelCase().decapitalize(Locale.ROOT) - -fun String.toUpperKebabCase(): String = - toCamelHumps().joinToString("-") { it.toUpperCase(Locale.ROOT) } - -fun String.toLowerKebabCase(): String = - toCamelHumps().joinToString("-") { it.toLowerCase(Locale.ROOT) } - -fun String.toUpperSnakeCase(): String = - toCamelHumps().joinToString("_") { it.toUpperCase(Locale.ROOT) } - -fun String.toLowerSnakeCase(): String = - toCamelHumps().joinToString("_") { it.toLowerCase(Locale.ROOT) } |