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
diff --git a/libartbase/base/sdk_version.h b/libartbase/base/sdk_version.h
new file mode 100644
index 0000000..4372e5a
--- /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 1539867..6434828 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 @@
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 0b005e0..2236e61 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 @@
// 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 12136bf..19498f3 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 @@
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 ab9e65c..188c5f3 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 @@
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 @@
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 98414f7..32bae11 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -117,13 +117,6 @@
// 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 627d9a7..314d878 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 @@
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 6769368..a61a48a 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 @@
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 49b71cd..e213dc7 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -29,6 +29,7 @@
#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 @@
// 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 7157928..33c8597 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -323,7 +323,7 @@
.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 ccbc2d9..19c1623 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 @@
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 f6a5634..a696c28 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -583,11 +583,11 @@
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 @@
return jdwp_provider_;
}
- static constexpr int32_t kUnsetSdkVersion = 0u;
-
uint32_t GetVerifierLoggingThresholdMs() const {
return verifier_logging_threshold_ms_;
}
@@ -975,7 +973,7 @@
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 f8c680d..12dab15 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 ae1e08f..5cec309 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -116,7 +116,8 @@
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 7b07389..0b33a0b 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 @@
// 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 @@
}
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 @@
}
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 @@
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 c4439de..d11aa57 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 @@
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);
}