diff options
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/compat_framework.cc | 65 | ||||
-rw-r--r-- | runtime/compat_framework.h | 73 | ||||
-rw-r--r-- | runtime/hidden_api.cc | 6 | ||||
-rw-r--r-- | runtime/hidden_api_test.cc | 5 | ||||
-rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 2 | ||||
-rw-r--r-- | runtime/native/java_lang_Class.cc | 4 | ||||
-rw-r--r-- | runtime/runtime.cc | 1 | ||||
-rw-r--r-- | runtime/runtime.h | 18 | ||||
-rw-r--r-- | test/674-hiddenapi/hiddenapi.cc | 5 |
10 files changed, 159 insertions, 21 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index 12f447bc9e..393c2cb94a 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -78,6 +78,7 @@ libart_cc_defaults { "class_root.cc", "class_table.cc", "common_throws.cc", + "compat_framework.cc", "compiler_filter.cc", "debug_print.cc", "debugger.cc", diff --git a/runtime/compat_framework.cc b/runtime/compat_framework.cc new file mode 100644 index 0000000000..40c4540f40 --- /dev/null +++ b/runtime/compat_framework.cc @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#include "compat_framework.h" + +#include "android-base/logging.h" +#include <sys/types.h> +#include <unistd.h> + +namespace art { + +// Compat change states as strings. +static constexpr char kUnknownChangeState[] = "UNKNOWN"; +static constexpr char kEnabledChangeState[] = "ENABLED"; +static constexpr char kDisabledChangeState[] = "DISABLED"; +static constexpr char kLoggedState[] = "LOGGED"; + +bool CompatFramework::IsChangeEnabled(uint64_t change_id) { + const auto enabled = disabled_compat_changes_.count(change_id) == 0; + ReportChange(change_id, enabled ? ChangeState::kEnabled : ChangeState::kDisabled); + return enabled; +} + +void CompatFramework::LogChange(uint64_t change_id) { + ReportChange(change_id, ChangeState::kLogged); +} + +void CompatFramework::ReportChange(uint64_t change_id, ChangeState state) { + bool already_reported = reported_compat_changes_.count(change_id) != 0; + if (already_reported) { + return; + } + LOG(DEBUG) << "Compat change id reported: " << change_id << "; UID " << getuid() + << "; state: " << ChangeStateToString(state); + // TODO(145743810): add an up call to java to log to statsd + reported_compat_changes_.emplace(change_id); +} + +std::string_view CompatFramework::ChangeStateToString(ChangeState state) { + switch (state) { + case ChangeState::kUnknown: + return kUnknownChangeState; + case ChangeState::kEnabled: + return kEnabledChangeState; + case ChangeState::kDisabled: + return kDisabledChangeState; + case ChangeState::kLogged: + return kLoggedState; + } +} + +} // namespace art diff --git a/runtime/compat_framework.h b/runtime/compat_framework.h new file mode 100644 index 0000000000..0b2426f3d3 --- /dev/null +++ b/runtime/compat_framework.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#ifndef ART_RUNTIME_COMPAT_FRAMEWORK_H_ +#define ART_RUNTIME_COMPAT_FRAMEWORK_H_ + +#include <set> + +#include "base/string_view_cpp20.h" + +namespace art { + +// ART counterpart of the compat framework (go/compat-framework). +// Created in order to avoid repeated up-calls to Java. +class CompatFramework { + public: + // Compat change reported state + // This must be kept in sync with AppCompatibilityChangeReported.State in + // frameworks/base/cmds/statsd/src/atoms.proto + enum class ChangeState { + kUnknown, + kEnabled, + kDisabled, + kLogged + }; + + void SetDisabledCompatChanges(const std::set<uint64_t>& disabled_changes) { + disabled_compat_changes_ = disabled_changes; + } + + const std::set<uint64_t>& GetDisabledCompatChanges() const { + return disabled_compat_changes_; + } + // Query if a given compatibility change is enabled for the current process. + // This also gets logged to logcat, and we add the information we logged in + // reported_compat_changes_. This ensures we only log once per change id for the app's lifetime. + bool IsChangeEnabled(uint64_t change_id); + + // Logs that the code path for this compatibility change has been reached. + // This also gets logged to logcat, and we add the information we logged in + // reported_compat_changes_. This ensures we only log once per change id for the app's lifetime. + void LogChange(uint64_t change_id); + + private: + // Get a string equivalent for a compatibility change state. + static std::string_view ChangeStateToString(ChangeState s); + // Report the state of a compatibility change to logcat. + // TODO(145743810): also report to statsd. + void ReportChange(uint64_t change_id, ChangeState state); + + // A set of disabled compat changes for the running app, all other changes are enabled. + std::set<uint64_t> disabled_compat_changes_; + + // A set of repoted compat changes for the running app. + std::set<uint64_t> reported_compat_changes_; +}; + +} // namespace art + +#endif // ART_RUNTIME_COMPAT_FRAMEWORK_H_ diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc index eb7f7b1419..62ff3ffee6 100644 --- a/runtime/hidden_api.cc +++ b/runtime/hidden_api.cc @@ -20,6 +20,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" +#include "compat_framework.h" #include "base/dumpable.h" #include "base/file_utils.h" #include "dex/class_accessor-inl.h" @@ -476,6 +477,7 @@ template<typename T> bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method) { DCHECK(member != nullptr); Runtime* runtime = Runtime::Current(); + CompatFramework& compatFramework = runtime->GetCompatFramework(); EnforcementPolicy hiddenApiPolicy = runtime->GetHiddenApiEnforcementPolicy(); DCHECK(hiddenApiPolicy != EnforcementPolicy::kDisabled) @@ -501,10 +503,10 @@ bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod acce } else { switch (api_list.GetMaxAllowedSdkVersion()) { case SdkVersion::kP: - deny_access = runtime->isChangeEnabled(kHideMaxtargetsdkPHiddenApis); + deny_access = compatFramework.IsChangeEnabled(kHideMaxtargetsdkPHiddenApis); break; case SdkVersion::kQ: - deny_access = runtime->isChangeEnabled(kHideMaxtargetsdkQHiddenApis); + deny_access = compatFramework.IsChangeEnabled(kHideMaxtargetsdkQHiddenApis); break; default: deny_access = IsSdkVersionSetAndMoreThan(runtime->GetTargetSdkVersion(), diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc index 6e573de528..6a002e5704 100644 --- a/runtime/hidden_api_test.cc +++ b/runtime/hidden_api_test.cc @@ -83,13 +83,14 @@ class HiddenApiTest : public CommonRuntimeTest { } void setChangeIdState(uint64_t change, bool enabled) { - std::set<uint64_t> disabled_changes = runtime_->GetDisabledCompatChanges(); + CompatFramework& compat_framework = runtime_->GetCompatFramework(); + std::set<uint64_t> disabled_changes = compat_framework.GetDisabledCompatChanges(); if (enabled) { disabled_changes.erase(change); } else { disabled_changes.insert(change); } - runtime_->SetDisabledCompatChanges(disabled_changes); + compat_framework.SetDisabledCompatChanges(disabled_changes); } bool ShouldDenyAccess(hiddenapi::ApiList list) REQUIRES_SHARED(Locks::mutator_lock_) { diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 2d0c60df75..2abdd982fd 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -277,7 +277,7 @@ static void VMRuntime_setDisabledCompatChangesNative(JNIEnv* env, jobject, for (int i = 0; i < length; i++) { disabled_compat_changes_set.insert(static_cast<uint64_t>(elements[i])); } - Runtime::Current()->SetDisabledCompatChanges(disabled_compat_changes_set); + Runtime::Current()->GetCompatFramework().SetDisabledCompatChanges(disabled_compat_changes_set); } static inline size_t clamp_to_size_t(jlong n) { diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 4443045319..776b14f735 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -24,6 +24,7 @@ #include "class_linker-inl.h" #include "class_root-inl.h" #include "common_throws.h" +#include "compat_framework.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_annotations.h" @@ -104,8 +105,9 @@ static hiddenapi::AccessContext GetReflectionCaller(Thread* self) // and walking over this frame would cause a null pointer dereference // (e.g. in 691-hiddenapi-proxy). ObjPtr<mirror::Class> proxy_class = GetClassRoot<mirror::Proxy>(); + CompatFramework& compat_framework = Runtime::Current()->GetCompatFramework(); if (declaring_class->IsInSamePackage(proxy_class) && declaring_class != proxy_class) { - if (Runtime::Current()->isChangeEnabled(kPreventMetaReflectionBlocklistAccess)) { + if (compat_framework.IsChangeEnabled(kPreventMetaReflectionBlocklistAccess)) { return true; } } diff --git a/runtime/runtime.cc b/runtime/runtime.cc index de9cfe4e3a..466a2fb85d 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -269,6 +269,7 @@ Runtime::Runtime() preinitialization_transactions_(), verify_(verifier::VerifyMode::kNone), target_sdk_version_(static_cast<uint32_t>(SdkVersion::kUnset)), + compat_framework_(), implicit_null_checks_(false), implicit_so_checks_(false), implicit_suspend_checks_(false), diff --git a/runtime/runtime.h b/runtime/runtime.h index 0746130eb6..de56de524a 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -32,6 +32,7 @@ #include "base/mem_map.h" #include "base/metrics.h" #include "base/string_view_cpp20.h" +#include "compat_framework.h" #include "deoptimization_kind.h" #include "dex/dex_file_types.h" #include "experimental_flags.h" @@ -672,17 +673,8 @@ class Runtime { return target_sdk_version_; } - void SetDisabledCompatChanges(const std::set<uint64_t>& disabled_changes) { - disabled_compat_changes_ = disabled_changes; - } - - std::set<uint64_t> GetDisabledCompatChanges() const { - return disabled_compat_changes_; - } - - bool isChangeEnabled(uint64_t change_id) const { - // TODO(145743810): add an up call to java to log to statsd - return disabled_compat_changes_.count(change_id) == 0; + CompatFramework& GetCompatFramework() { + return compat_framework_; } uint32_t GetZygoteMaxFailedBoots() const { @@ -1172,8 +1164,8 @@ class Runtime { // Specifies target SDK version to allow workarounds for certain API levels. uint32_t target_sdk_version_; - // A set of disabled compat changes for the running app, all other changes are enabled. - std::set<uint64_t> disabled_compat_changes_; + // ART counterpart for the compat framework (go/compat-framework). + CompatFramework compat_framework_; // Implicit checks flags. bool implicit_null_checks_; // NullPointer checks are implicit. diff --git a/test/674-hiddenapi/hiddenapi.cc b/test/674-hiddenapi/hiddenapi.cc index 6113e97d77..ebe9d10c47 100644 --- a/test/674-hiddenapi/hiddenapi.cc +++ b/test/674-hiddenapi/hiddenapi.cc @@ -321,7 +321,8 @@ extern "C" JNIEXPORT jint JNICALL Java_Reflection_getHiddenApiAccessFlags(JNIEnv extern "C" JNIEXPORT void JNICALL Java_Reflection_setHiddenApiCheckHardening(JNIEnv*, jclass, jboolean value) { - std::set<uint64_t> disabled_changes = Runtime::Current()->GetDisabledCompatChanges(); + CompatFramework& compat_framework = Runtime::Current()->GetCompatFramework(); + std::set<uint64_t> disabled_changes = compat_framework.GetDisabledCompatChanges(); if (value == JNI_TRUE) { // If hidden api check hardening is enabled, remove it from the set of disabled changes. disabled_changes.erase(kPreventMetaReflectionBlocklistAccess); @@ -329,7 +330,7 @@ extern "C" JNIEXPORT void JNICALL Java_Reflection_setHiddenApiCheckHardening(JNI // If hidden api check hardening is disabled, add it to the set of disabled changes. disabled_changes.insert(kPreventMetaReflectionBlocklistAccess); } - Runtime::Current()->SetDisabledCompatChanges(disabled_changes); + compat_framework.SetDisabledCompatChanges(disabled_changes); } } // namespace Test674HiddenApi |