diff options
-rw-r--r-- | libartbase/base/hiddenapi_flags.h | 29 | ||||
-rw-r--r-- | tools/hiddenapi/hiddenapi_test.cc | 34 |
2 files changed, 57 insertions, 6 deletions
diff --git a/libartbase/base/hiddenapi_flags.h b/libartbase/base/hiddenapi_flags.h index 59e17a8d90..e79e5f3bbc 100644 --- a/libartbase/base/hiddenapi_flags.h +++ b/libartbase/base/hiddenapi_flags.h @@ -64,6 +64,13 @@ namespace helper { // kMin and kMax and no integer values are skipped between them. template<typename T> constexpr uint32_t NumValues() { return ToUint(T::kMax) - ToUint(T::kMin) + 1; } + + // Returns enum value at position i from enum list. + template <typename T> + constexpr T GetEnumAt(uint32_t i) { + return static_cast<T>(ToUint(T::kMin) + i); + } + } // namespace helper /* @@ -101,10 +108,11 @@ class ApiList { // These are used for domain-specific API. enum class DomainApi : uint32_t { kCorePlatformApi = kValueBitSize, + kTestApi = kValueBitSize + 1, // Special values kMin = kCorePlatformApi, - kMax = kCorePlatformApi, + kMax = kTestApi, }; // Bit mask of all domain API flags. @@ -134,6 +142,7 @@ class ApiList { // Names corresponding to DomainApis. static constexpr const char* kDomainApiNames[] { "core-platform-api", + "test-api", }; // Maximum SDK versions allowed to access ApiList of given Value. @@ -185,6 +194,7 @@ class ApiList { static ApiList GreylistMaxO() { return ApiList(Value::kGreylistMaxO); } static ApiList GreylistMaxP() { return ApiList(Value::kGreylistMaxP); } static ApiList CorePlatformApi() { return ApiList(DomainApi::kCorePlatformApi); } + static ApiList TestApi() { return ApiList(DomainApi::kTestApi); } uint32_t GetDexFlags() const { return dex_flags_; } uint32_t GetIntValue() const { return helper::ToUint(GetValue()) - helper::ToUint(Value::kMin); } @@ -193,12 +203,12 @@ class ApiList { static ApiList FromName(const std::string& str) { for (uint32_t i = 0; i < kValueCount; ++i) { if (str == kValueNames[i]) { - return ApiList(static_cast<Value>(i + helper::ToUint(Value::kMin))); + return ApiList(helper::GetEnumAt<Value>(i)); } } for (uint32_t i = 0; i < kDomainApiCount; ++i) { if (str == kDomainApiNames[i]) { - return ApiList(static_cast<DomainApi>(i + helper::ToUint(DomainApi::kMin))); + return ApiList(helper::GetEnumAt<DomainApi>(i)); } } return ApiList(); @@ -290,14 +300,14 @@ class ApiList { } const uint32_t domain_apis = GetDomainApis(); - for (uint32_t i = helper::ToUint(DomainApi::kMin); i <= helper::ToUint(DomainApi::kMax); i++) { - if (helper::MatchesBitMask(helper::ToBit(i), domain_apis)) { + for (uint32_t i = 0; i < kDomainApiCount; i++) { + if (helper::MatchesBitMask(helper::ToBit(helper::GetEnumAt<DomainApi>(i)), domain_apis)) { if (is_first) { is_first = false; } else { os << ","; } - os << kDomainApiNames[i - helper::ToUint(DomainApi::kMin)]; + os << kDomainApiNames[i]; } } @@ -306,6 +316,13 @@ class ApiList { static constexpr uint32_t kValueCount = helper::NumValues<Value>(); static constexpr uint32_t kDomainApiCount = helper::NumValues<DomainApi>(); + + // Check min and max values are calculated correctly. + static_assert(Value::kMin == helper::GetEnumAt<Value>(0)); + static_assert(Value::kMax == helper::GetEnumAt<Value>(kValueCount - 1)); + + static_assert(DomainApi::kMin == helper::GetEnumAt<DomainApi>(0)); + static_assert(DomainApi::kMax == helper::GetEnumAt<DomainApi>(kDomainApiCount - 1)); }; inline std::ostream& operator<<(std::ostream& os, ApiList value) { diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc index 7c9a95cbfd..337fae4850 100644 --- a/tools/hiddenapi/hiddenapi_test.cc +++ b/tools/hiddenapi/hiddenapi_test.cc @@ -690,6 +690,40 @@ TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch3) { ASSERT_EQ(dex_file.get(), nullptr); } +TEST_F(HiddenApiTest, InstanceFieldCorePlatformApiMatch) { + ScratchFile dex, flags_csv; + OpenStream(flags_csv) + << "LMain;->ifield:LBadType1;,greylist" << std::endl + << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl + << "LMain;->ifield:I,greylist,core-platform-api" << std::endl; + auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex); + ASSERT_NE(dex_file.get(), nullptr); + ASSERT_EQ(hiddenapi::ApiList::CorePlatformApi() | + hiddenapi::ApiList::Greylist(), GetIFieldHiddenFlags(*dex_file)); +} + +TEST_F(HiddenApiTest, InstanceFieldTestApiMatch) { + ScratchFile dex, flags_csv; + OpenStream(flags_csv) + << "LMain;->ifield:LBadType1;,greylist" << std::endl + << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl + << "LMain;->ifield:I,greylist,test-api" << std::endl; + auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex); + ASSERT_NE(dex_file.get(), nullptr); + ASSERT_EQ(hiddenapi::ApiList::TestApi() + | hiddenapi::ApiList::Greylist(), GetIFieldHiddenFlags(*dex_file)); +} + +TEST_F(HiddenApiTest, InstanceFieldUnknownFlagMatch) { + ScratchFile dex, flags_csv; + OpenStream(flags_csv) + << "LMain;->ifield:LBadType1;,greylist" << std::endl + << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl + << "LMain;->ifield:I,greylist,unknown-flag" << std::endl; + auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex); + ASSERT_EQ(dex_file.get(), nullptr); +} + // The following tests use this class hierarchy: // // AbstractPackageClass PublicInterface |