summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Atneya Nair <atneya@google.com> 2024-08-12 14:18:23 -0700
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-08-20 08:55:22 +0000
commitcc49e6ffd89b660ef86c12d72db3e646669d19ea (patch)
treeaea28767a19b7e9501c8946c0cdfb695513f8204
parent27eb1043f383c059d997e2e7f677edebaf482e8d (diff)
hiddenapi: Accept Unsupported/Sdk conflict
The hiddenapi tool currently doesn't accept a API being labeled as both Unsupported, as well as part of the Sdk. In order to enable migrations from UAU to Sdk with flags, this conflict must be tolerated in the flag enabled case. UAU must remain for the flag disabled case. Test: Builds with API with @UAU and @SystemApi Bug: 358250700 Change-Id: I70821a8c57ec06fe9fd9957da5f4a597a875b1ca
-rw-r--r--libartbase/base/hiddenapi_flags.h30
1 files changed, 29 insertions, 1 deletions
diff --git a/libartbase/base/hiddenapi_flags.h b/libartbase/base/hiddenapi_flags.h
index 9d0a18e78f..0d7938aca1 100644
--- a/libartbase/base/hiddenapi_flags.h
+++ b/libartbase/base/hiddenapi_flags.h
@@ -263,11 +263,37 @@ class ApiList {
bool operator<(const ApiList& other) const { return dex_flags_ < other.dex_flags_; }
bool operator>(const ApiList& other) const { return dex_flags_ > other.dex_flags_; }
+ // In order to correctly handle flagged changes from Unsupported to the Sdk, where both will be
+ // set when the flag is enabled, consider Sdk to take precedence over any form of unsupported.
+ // Note, this is not necessary in the inverse direction, because API flagging does not currently
+ // support API removal. Moving from the blocklist to unsupported is also a case we don't have to
+ // consider.
+ // If this is true, the conflict resolves to Value::kSdk.
+ static bool is_conflicting_flags_acceptable(Value x, Value y) {
+ const auto predicate_non_symmetric = [] (auto l, auto r) {
+ if (l != Value::kSdk) return false;
+ switch (r) {
+ case Value::kSdk:
+ case Value::kUnsupported:
+ case Value::kMaxTargetO:
+ case Value::kMaxTargetP:
+ case Value::kMaxTargetQ:
+ case Value::kMaxTargetR:
+ case Value::kMaxTargetS:
+ return true;
+ default:
+ return false;
+ }
+ };
+ return predicate_non_symmetric(x, y) || predicate_non_symmetric(y, x);
+ }
+
// Returns true if combining this ApiList with `other` will succeed.
bool CanCombineWith(const ApiList& other) const {
const Value val1 = GetValue();
const Value val2 = other.GetValue();
- return (val1 == val2) || (val1 == Value::kInvalid) || (val2 == Value::kInvalid);
+ return (val1 == val2) || (val1 == Value::kInvalid) || (val2 == Value::kInvalid) ||
+ is_conflicting_flags_acceptable(val1, val2);
}
// Combine two ApiList instances.
@@ -285,6 +311,8 @@ class ApiList {
return ApiList(val2, domain_apis);
} else if (val2 == Value::kInvalid) {
return ApiList(val1, domain_apis);
+ } else if (is_conflicting_flags_acceptable(val1, val2)) {
+ return ApiList(Value::kSdk, domain_apis);
} else {
LOG(FATAL) << "Invalid combination of values " << Dumpable(ApiList(val1))
<< " and " << Dumpable(ApiList(val2));