Treat hidden API exemptions as whitelist.
This was a request from android-api-council, effectively to treat
exempted APIs as equivalent to public APIs. The reasoning for this is
that if the support library uses such APIs, we don't want to confuse
developers with a warning in the log.
To avoid examing the exemptions list on all light greylist API accesses,
also change the light greylist warn behavior to only print a warning in
the log if the app is debuggable. This means:
- less log spam from light greylist usages
- debuggable apps still get info about light greylist usage
Bug: 64382372
Test: m
Test: Boot device
Test: $ adb shell settings put global hidden_api_blacklist_exemptions \
Test: "\"Landroid/app/Activity;->mWindow:,Landroid/app/Activity;->mCalled:\""
Test: Verified with test app & adb logcat
Merged-In: Ibada61b591517f7e72c7101aea04ff0ad4beb0ee
Change-Id: Ibada61b591517f7e72c7101aea04ff0ad4beb0ee
(cherry picked from commit c8ce5f520d2ba84ff8f393f78ba953ae6d467ca8)
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index fa47e3a..02b4f53 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -125,25 +125,29 @@
Runtime* runtime = Runtime::Current();
- if (action == kDeny) {
- // If we were about to deny, check for an exemption first.
- // Exempted APIs are treated as light grey list.
+ // Check for an exemption first. Exempted APIs are treated as white list.
+ // We only do this if we're about to deny, or if the app is debuggable. This is because:
+ // - we only print a warning for light greylist violations for debuggable apps
+ // - for non-debuggable apps, there is no distinction between light grey & whitelisted APIs.
+ // - we want to avoid the overhead of checking for exemptions for light greylisted APIs whenever
+ // possible.
+ if (action == kDeny || runtime->IsJavaDebuggable()) {
if (member_signature.IsExempted(runtime->GetHiddenApiExemptions())) {
- action = kAllowButWarn;
+ action = kAllow;
// Avoid re-examining the exemption list next time.
- // Note this results in the warning below showing "light greylist", which
- // seems like what one would expect. Exemptions effectively add new members to
- // the light greylist.
+ // Note this results in no warning for the member, which seems like what one would expect.
+ // Exemptions effectively adds new members to the whitelist.
member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
- member->GetAccessFlags(), HiddenApiAccessFlags::kLightGreylist));
+ member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
+ return kAllow;
}
- }
- if (access_method != kNone) {
- // Print a log message with information about this class member access.
- // We do this regardless of whether we block the access or not.
- member_signature.WarnAboutAccess(access_method,
- HiddenApiAccessFlags::DecodeFromRuntime(member->GetAccessFlags()));
+ if (access_method != kNone) {
+ // Print a log message with information about this class member access.
+ // We do this if we're about to block access, or the app is debuggable.
+ member_signature.WarnAboutAccess(access_method,
+ HiddenApiAccessFlags::DecodeFromRuntime(member->GetAccessFlags()));
+ }
}
if (action == kDeny) {
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 56d95e0..67813a7 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -1006,7 +1006,8 @@
// Whether access checks on hidden API should be performed.
hiddenapi::EnforcementPolicy hidden_api_policy_;
- // List of signature prefixes of methods that have been removed from the blacklist
+ // List of signature prefixes of methods that have been removed from the blacklist, and treated
+ // as if whitelisted.
std::vector<std::string> hidden_api_exemptions_;
// Whether the application has used an API which is not restricted but we