diff options
author | 2018-11-13 18:24:26 +0000 | |
---|---|---|
committer | 2018-11-16 11:11:20 +0000 | |
commit | 2bb2fbd2879d0a6d9ebf7acff817079dde89b417 (patch) | |
tree | d607aa6bfb2ea55fbfd875237b37c79f3cfed5f6 | |
parent | 85865697ff9fabede3d64ff64cde72727c3fc4c1 (diff) |
Create SdkVersion enum, migrate users to it
Creates a new SdkVersion enum with integer codes of known
Android SDK versions, together with helper functions for common
predicates. Also converts target_sdk_version_ in Runtime to
uint32_t and cleans up its uses.
Test: m test-art
Change-Id: Idc6e518c8675068bf952d0256686c88bb0eb833e
-rw-r--r-- | libartbase/base/sdk_version.h | 58 | ||||
-rw-r--r-- | runtime/dex/dex_file_annotations.cc | 4 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 6 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.cc | 5 | ||||
-rw-r--r-- | runtime/hidden_api.cc | 17 | ||||
-rw-r--r-- | runtime/hidden_api.h | 7 | ||||
-rw-r--r-- | runtime/hidden_api_test.cc | 5 | ||||
-rw-r--r-- | runtime/jni/java_vm_ext.cc | 3 | ||||
-rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 8 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 2 | ||||
-rw-r--r-- | runtime/runtime.cc | 3 | ||||
-rw-r--r-- | runtime/runtime.h | 8 | ||||
-rw-r--r-- | runtime/runtime_options.cc | 1 | ||||
-rw-r--r-- | runtime/runtime_options.def | 3 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 16 | ||||
-rw-r--r-- | test/674-hiddenapi/hiddenapi.cc | 3 |
16 files changed, 107 insertions, 42 deletions
diff --git a/libartbase/base/sdk_version.h b/libartbase/base/sdk_version.h new file mode 100644 index 0000000000..4372e5a02f --- /dev/null +++ b/libartbase/base/sdk_version.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018 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_LIBARTBASE_BASE_SDK_VERSION_H_ +#define ART_LIBARTBASE_BASE_SDK_VERSION_H_ + +#include <cstdint> +#include <limits> + +namespace art { + +enum class SdkVersion : uint32_t { + kMin = 0u, + kUnset = 0u, + kL = 21u, + kL_MR1 = 22u, + kM = 23u, + kN = 24u, + kN_MR1 = 25u, + kO = 26u, + kO_MR1 = 27u, + kP = 28u, + kP_MR1 = 29u, + kMax = std::numeric_limits<uint32_t>::max(), +}; + +inline bool IsSdkVersionSetAndMoreThan(uint32_t lhs, SdkVersion rhs) { + return lhs != static_cast<uint32_t>(SdkVersion::kUnset) && lhs > static_cast<uint32_t>(rhs); +} + +inline bool IsSdkVersionSetAndAtLeast(uint32_t lhs, SdkVersion rhs) { + return lhs != static_cast<uint32_t>(SdkVersion::kUnset) && lhs >= static_cast<uint32_t>(rhs); +} + +inline bool IsSdkVersionSetAndAtMost(uint32_t lhs, SdkVersion rhs) { + return lhs != static_cast<uint32_t>(SdkVersion::kUnset) && lhs <= static_cast<uint32_t>(rhs); +} + +inline bool IsSdkVersionSetAndLessThan(uint32_t lhs, SdkVersion rhs) { + return lhs != static_cast<uint32_t>(SdkVersion::kUnset) && lhs < static_cast<uint32_t>(rhs); +} + +} // namespace art + +#endif // ART_LIBARTBASE_BASE_SDK_VERSION_H_ diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc index 15398672b2..6434828298 100644 --- a/runtime/dex/dex_file_annotations.cc +++ b/runtime/dex/dex_file_annotations.cc @@ -22,6 +22,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" +#include "base/sdk_version.h" #include "class_linker-inl.h" #include "class_root.h" #include "dex/dex_file-inl.h" @@ -129,8 +130,7 @@ ObjPtr<mirror::Object> CreateAnnotationMember(const ClassData& klass, bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) { if (expected == DexFile::kDexVisibilityRuntime) { - int32_t sdk_version = Runtime::Current()->GetTargetSdkVersion(); - if (sdk_version > 0 && sdk_version <= 23) { + if (IsSdkVersionSetAndAtMost(Runtime::Current()->GetTargetSdkVersion(), SdkVersion::kM)) { return actual == DexFile::kDexVisibilityRuntime || actual == DexFile::kDexVisibilityBuild; } } diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 0b005e0851..2236e61d75 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -22,6 +22,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" #include "base/enums.h" +#include "base/sdk_version.h" #include "class_linker-inl.h" #include "common_throws.h" #include "dex/dex_file.h" @@ -94,8 +95,9 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, // even going back from boot image methods to the same oat file. However, this is // not currently implemented in the compiler. Therefore crossing dex file boundary // indicates that the inlined definition is not the same as the one used at runtime. - bool target_sdk_pre_p = Runtime::Current()->GetTargetSdkVersion() < 28; - LOG(target_sdk_pre_p ? WARNING : FATAL) + bool target_sdk_at_least_p = + IsSdkVersionSetAndAtLeast(Runtime::Current()->GetTargetSdkVersion(), SdkVersion::kP); + LOG(target_sdk_at_least_p ? FATAL : WARNING) << "Inlined method resolution crossed dex file boundary: from " << method->PrettyMethod() << " in " << method->GetDexFile()->GetLocation() << "/" diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index 12136bf476..19498f386c 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -20,6 +20,7 @@ #include "art_method-inl.h" #include "base/enums.h" #include "base/mutex.h" +#include "base/sdk_version.h" #include "class_linker-inl.h" #include "dex/dex_file-inl.h" #include "entrypoints/entrypoint_utils-inl.h" @@ -64,9 +65,9 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons soa.Self()->AssertThreadSuspensionIsAllowable(); jobjectArray args_jobj = nullptr; const JValue zero; - int32_t target_sdk_version = Runtime::Current()->GetTargetSdkVersion(); + uint32_t target_sdk_version = Runtime::Current()->GetTargetSdkVersion(); // Do not create empty arrays unless needed to maintain Dalvik bug compatibility. - if (args.size() > 0 || (target_sdk_version > 0 && target_sdk_version <= 21)) { + if (args.size() > 0 || IsSdkVersionSetAndAtMost(target_sdk_version, SdkVersion::kL)) { args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, nullptr); if (args_jobj == nullptr) { CHECK(soa.Self()->IsExceptionPending()); diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc index ab9e65c458..188c5f353b 100644 --- a/runtime/hidden_api.cc +++ b/runtime/hidden_api.cc @@ -21,6 +21,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" #include "base/dumpable.h" +#include "base/sdk_version.h" #include "dex/class_accessor-inl.h" #include "scoped_thread_state_change.h" #include "thread-inl.h" @@ -75,24 +76,19 @@ enum AccessContextFlags { kAccessDenied = 1 << 1, }; -static int32_t GetMaxAllowedSdkVersionForApiList(ApiList api_list) { - SdkCodes sdk = SdkCodes::kVersionNone; +static SdkVersion GetMaxAllowedSdkVersionForApiList(ApiList api_list) { switch (api_list) { case ApiList::kWhitelist: case ApiList::kLightGreylist: - sdk = SdkCodes::kVersionUnlimited; - break; + return SdkVersion::kMax; case ApiList::kDarkGreylist: - sdk = SdkCodes::kVersionO_MR1; - break; + return SdkVersion::kO_MR1; case ApiList::kBlacklist: - sdk = SdkCodes::kVersionNone; - break; + return SdkVersion::kMin; case ApiList::kNoList: LOG(FATAL) << "Unexpected value"; UNREACHABLE(); } - return static_cast<int32_t>(sdk); } MemberSignature::MemberSignature(ArtField* field) { @@ -326,7 +322,8 @@ bool ShouldDenyAccessToMemberImpl(T* member, const bool deny_access = (policy == EnforcementPolicy::kEnabled) && - (runtime->GetTargetSdkVersion() > GetMaxAllowedSdkVersionForApiList(api_list)); + IsSdkVersionSetAndMoreThan(runtime->GetTargetSdkVersion(), + GetMaxAllowedSdkVersionForApiList(api_list)); MemberSignature member_signature(member); diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h index 98414f7a87..32bae1127b 100644 --- a/runtime/hidden_api.h +++ b/runtime/hidden_api.h @@ -117,13 +117,6 @@ class ScopedHiddenApiEnforcementPolicySetting { // Implementation details. DO NOT ACCESS DIRECTLY. namespace detail { -enum class SdkCodes { - kVersionNone = std::numeric_limits<int32_t>::min(), - kVersionUnlimited = std::numeric_limits<int32_t>::max(), - kVersionO_MR1 = 27, - kVersionP = 28, -}; - // Class to encapsulate the signature of a member (ArtField or ArtMethod). This // is used as a helper when matching prefixes, and when logging the signature. class MemberSignature { diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc index 627d9a7e1c..314d878c66 100644 --- a/runtime/hidden_api_test.cc +++ b/runtime/hidden_api_test.cc @@ -16,6 +16,7 @@ #include "hidden_api.h" +#include "base/sdk_version.h" #include "common_runtime_test.h" #include "jni/jni_internal.h" #include "proxy_test.h" @@ -112,14 +113,14 @@ TEST_F(HiddenApiTest, CheckGetActionFromRuntimeFlags) { ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kBlacklist), false); runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled); - runtime_->SetTargetSdkVersion(static_cast<int32_t>(hiddenapi::detail::SdkCodes::kVersionO_MR1)); + runtime_->SetTargetSdkVersion(static_cast<uint32_t>(SdkVersion::kO_MR1)); ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kWhitelist), false); ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kLightGreylist), false); ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kDarkGreylist), false); ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kBlacklist), true); runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled); - runtime_->SetTargetSdkVersion(static_cast<int32_t>(hiddenapi::detail::SdkCodes::kVersionP)); + runtime_->SetTargetSdkVersion(static_cast<uint32_t>(SdkVersion::kP)); ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kWhitelist), false); ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kLightGreylist), false); ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::kDarkGreylist), true); diff --git a/runtime/jni/java_vm_ext.cc b/runtime/jni/java_vm_ext.cc index 6769368ee4..a61a48a29b 100644 --- a/runtime/jni/java_vm_ext.cc +++ b/runtime/jni/java_vm_ext.cc @@ -23,6 +23,7 @@ #include "art_method-inl.h" #include "base/dumpable.h" #include "base/mutex-inl.h" +#include "base/sdk_version.h" #include "base/stl_util.h" #include "base/systrace.h" #include "check_jni.h" @@ -1030,7 +1031,7 @@ bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym); int version = (*jni_on_load)(this, nullptr); - if (runtime_->GetTargetSdkVersion() != 0 && runtime_->GetTargetSdkVersion() <= 21) { + if (IsSdkVersionSetAndAtMost(runtime_->GetTargetSdkVersion(), SdkVersion::kL)) { // Make sure that sigchain owns SIGSEGV. EnsureFrontOfChain(SIGSEGV); } diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 49b71cd801..e213dc79b8 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -29,6 +29,7 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version); #include "arch/instruction_set.h" #include "art_method-inl.h" #include "base/enums.h" +#include "base/sdk_version.h" #include "class_linker-inl.h" #include "common_throws.h" #include "debugger.h" @@ -256,12 +257,15 @@ static void VMRuntime_setTargetSdkVersionNative(JNIEnv*, jobject, jint target_sd // where workarounds can be enabled. // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000). // Note that targetSdkVersion may be 0, meaning "current". - Runtime::Current()->SetTargetSdkVersion(target_sdk_version); + uint32_t uint_target_sdk_version = + target_sdk_version <= 0 ? static_cast<uint32_t>(SdkVersion::kUnset) + : static_cast<uint32_t>(target_sdk_version); + Runtime::Current()->SetTargetSdkVersion(uint_target_sdk_version); #ifdef ART_TARGET_ANDROID // This part is letting libc/dynamic linker know about current app's // target sdk version to enable compatibility workarounds. - android_set_application_target_sdk_version(static_cast<uint32_t>(target_sdk_version)); + android_set_application_target_sdk_version(uint_target_sdk_version); #endif } diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 715792876d..33c85973b3 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -323,7 +323,7 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .WithValueMap({{"false", false}, {"true", true}}) .IntoKey(M::SlowDebug) .Define("-Xtarget-sdk-version:_") - .WithType<int>() + .WithType<unsigned int>() .IntoKey(M::TargetSdkVersion) .Define("-Xhidden-api-checks") .IntoKey(M::HiddenApiChecks) diff --git a/runtime/runtime.cc b/runtime/runtime.cc index ccbc2d92e1..19c1623d1f 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -61,6 +61,7 @@ #include "base/mutex.h" #include "base/os.h" #include "base/quasi_atomic.h" +#include "base/sdk_version.h" #include "base/stl_util.h" #include "base/systrace.h" #include "base/unix_file/fd_file.h" @@ -253,7 +254,7 @@ Runtime::Runtime() preinitialization_transactions_(), verify_(verifier::VerifyMode::kNone), allow_dex_file_fallback_(true), - target_sdk_version_(kUnsetSdkVersion), + target_sdk_version_(static_cast<uint32_t>(SdkVersion::kUnset)), implicit_null_checks_(false), implicit_so_checks_(false), implicit_suspend_checks_(false), diff --git a/runtime/runtime.h b/runtime/runtime.h index f6a5634379..a696c2845e 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -583,11 +583,11 @@ class Runtime { return is_running_on_memory_tool_; } - void SetTargetSdkVersion(int32_t version) { + void SetTargetSdkVersion(uint32_t version) { target_sdk_version_ = version; } - int32_t GetTargetSdkVersion() const { + uint32_t GetTargetSdkVersion() const { return target_sdk_version_; } @@ -793,8 +793,6 @@ class Runtime { return jdwp_provider_; } - static constexpr int32_t kUnsetSdkVersion = 0u; - uint32_t GetVerifierLoggingThresholdMs() const { return verifier_logging_threshold_ms_; } @@ -975,7 +973,7 @@ class Runtime { std::vector<std::string> cpu_abilist_; // Specifies target SDK version to allow workarounds for certain API levels. - int32_t target_sdk_version_; + uint32_t target_sdk_version_; // Implicit checks flags. bool implicit_null_checks_; // NullPointer checks are implicit. diff --git a/runtime/runtime_options.cc b/runtime/runtime_options.cc index f8c680db44..12dab158e5 100644 --- a/runtime/runtime_options.cc +++ b/runtime/runtime_options.cc @@ -18,6 +18,7 @@ #include <memory> +#include "base/sdk_version.h" #include "base/utils.h" #include "debugger.h" #include "gc/heap.h" diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index ae1e08f10b..5cec309453 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -116,7 +116,8 @@ RUNTIME_OPTIONS_KEY (std::vector<std::string>, \ ImageCompilerOptions) // -Ximage-compiler-option ... RUNTIME_OPTIONS_KEY (verifier::VerifyMode, \ Verify, verifier::VerifyMode::kEnable) -RUNTIME_OPTIONS_KEY (int, TargetSdkVersion, Runtime::kUnsetSdkVersion) +RUNTIME_OPTIONS_KEY (unsigned int, TargetSdkVersion, \ + static_cast<unsigned int>(SdkVersion::kUnset)) RUNTIME_OPTIONS_KEY (Unit, HiddenApiChecks) RUNTIME_OPTIONS_KEY (std::string, NativeBridge) RUNTIME_OPTIONS_KEY (unsigned int, ZygoteMaxFailedBoots, 10) diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 7b07389057..0b33a0b3c0 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -28,6 +28,7 @@ #include "base/indenter.h" #include "base/logging.h" // For VLOG. #include "base/mutex-inl.h" +#include "base/sdk_version.h" #include "base/stl_util.h" #include "base/systrace.h" #include "base/time_utils.h" @@ -3677,9 +3678,10 @@ const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) { // Note: we do this for unresolved classes to trigger re-verification at runtime. if (C == CheckAccess::kYes && result->IsNonZeroReferenceTypes() && - (api_level_ >= 28u || !result->IsUnresolvedTypes())) { + (IsSdkVersionSetAndAtLeast(api_level_, SdkVersion::kP) || !result->IsUnresolvedTypes())) { const RegType& referrer = GetDeclaringClass(); - if ((api_level_ >= 28u || !referrer.IsUnresolvedTypes()) && !referrer.CanAccess(*result)) { + if ((IsSdkVersionSetAndAtLeast(api_level_, SdkVersion::kP) || !referrer.IsUnresolvedTypes()) && + !referrer.CanAccess(*result)) { Fail(VERIFY_ERROR_ACCESS_CLASS) << "(possibly) illegal class access: '" << referrer << "' -> '" << *result << "'"; } @@ -4562,7 +4564,9 @@ ArtField* MethodVerifier::GetStaticField(int field_idx) { } if (klass_type.IsUnresolvedTypes()) { // Accessibility checks depend on resolved fields. - DCHECK(klass_type.Equals(GetDeclaringClass()) || !failures_.empty() || api_level_ < 28u); + DCHECK(klass_type.Equals(GetDeclaringClass()) || + !failures_.empty() || + IsSdkVersionSetAndLessThan(api_level_, SdkVersion::kP)); return nullptr; // Can't resolve Class so no more to do here, will do checking at runtime. } @@ -4603,7 +4607,9 @@ ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_id } if (klass_type.IsUnresolvedTypes()) { // Accessibility checks depend on resolved fields. - DCHECK(klass_type.Equals(GetDeclaringClass()) || !failures_.empty() || api_level_ < 28u); + DCHECK(klass_type.Equals(GetDeclaringClass()) || + !failures_.empty() || + IsSdkVersionSetAndLessThan(api_level_, SdkVersion::kP)); return nullptr; // Can't resolve Class so no more to do here } @@ -4739,7 +4745,7 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& DCHECK(!can_load_classes_ || self_->IsExceptionPending()); self_->ClearException(); } - } else if (api_level_ >= 28u) { + } else if (IsSdkVersionSetAndAtLeast(api_level_, SdkVersion::kP)) { // If we don't have the field (it seems we failed resolution) and this is a PUT, we need to // redo verification at runtime as the field may be final, unless the field id shows it's in // the same class. diff --git a/test/674-hiddenapi/hiddenapi.cc b/test/674-hiddenapi/hiddenapi.cc index c4439de550..d11aa579e5 100644 --- a/test/674-hiddenapi/hiddenapi.cc +++ b/test/674-hiddenapi/hiddenapi.cc @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "base/sdk_version.h" #include "class_linker.h" #include "dex/art_dex_file_loader.h" #include "hidden_api.h" @@ -29,7 +30,7 @@ namespace Test674HiddenApi { extern "C" JNIEXPORT void JNICALL Java_Main_init(JNIEnv*, jclass) { Runtime* runtime = Runtime::Current(); runtime->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled); - runtime->SetTargetSdkVersion(static_cast<int32_t>(hiddenapi::detail::SdkCodes::kVersionO_MR1)); + runtime->SetTargetSdkVersion(static_cast<uint32_t>(SdkVersion::kO_MR1)); runtime->SetDedupeHiddenApiWarnings(false); } |