diff options
| -rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 95 | ||||
| -rw-r--r-- | runtime/interpreter/unstarted_runtime_list.h | 2 |
2 files changed, 97 insertions, 0 deletions
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 02e05c5429..fe388cd16d 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -484,6 +484,101 @@ void UnstartedRuntime::UnstartedSystemGetSecurityManager( result->SetL(nullptr); } +static constexpr const char* kAndroidHardcodedSystemPropertiesFieldName = "STATIC_PROPERTIES"; + +static void GetSystemProperty(Thread* self, + ShadowFrame* shadow_frame, + JValue* result, + size_t arg_offset, + bool is_default_version) + SHARED_REQUIRES(Locks::mutator_lock_) { + StackHandleScope<4> hs(self); + Handle<mirror::String> h_key( + hs.NewHandle(reinterpret_cast<mirror::String*>(shadow_frame->GetVRegReference(arg_offset)))); + if (h_key.Get() == nullptr) { + AbortTransactionOrFail(self, "getProperty key was null"); + return; + } + + // This is overall inefficient, but reflecting the values here is not great, either. So + // for simplicity, and with the assumption that the number of getProperty calls is not + // too great, just iterate each time. + + // Get the storage class. + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Handle<mirror::Class> h_props_class(hs.NewHandle( + class_linker->FindClass(self, + "Ljava/lang/AndroidHardcodedSystemProperties;", + ScopedNullHandle<mirror::ClassLoader>()))); + if (h_props_class.Get() == nullptr) { + AbortTransactionOrFail(self, "Could not find AndroidHardcodedSystemProperties"); + return; + } + if (!class_linker->EnsureInitialized(self, h_props_class, true, true)) { + AbortTransactionOrFail(self, "Could not initialize AndroidHardcodedSystemProperties"); + return; + } + + // Get the storage array. + ArtField* static_properties = + h_props_class->FindDeclaredStaticField(kAndroidHardcodedSystemPropertiesFieldName, + "[[Ljava/lang/String;"); + if (static_properties == nullptr) { + AbortTransactionOrFail(self, + "Could not find %s field", + kAndroidHardcodedSystemPropertiesFieldName); + return; + } + Handle<mirror::ObjectArray<mirror::ObjectArray<mirror::String>>> h_2string_array( + hs.NewHandle(reinterpret_cast<mirror::ObjectArray<mirror::ObjectArray<mirror::String>>*>( + static_properties->GetObject(h_props_class.Get())))); + if (h_2string_array.Get() == nullptr) { + AbortTransactionOrFail(self, "Field %s is null", kAndroidHardcodedSystemPropertiesFieldName); + return; + } + + // Iterate over it. + const int32_t prop_count = h_2string_array->GetLength(); + // Use the third handle as mutable. + MutableHandle<mirror::ObjectArray<mirror::String>> h_string_array( + hs.NewHandle<mirror::ObjectArray<mirror::String>>(nullptr)); + for (int32_t i = 0; i < prop_count; ++i) { + h_string_array.Assign(h_2string_array->Get(i)); + if (h_string_array.Get() == nullptr || + h_string_array->GetLength() != 2 || + h_string_array->Get(0) == nullptr) { + AbortTransactionOrFail(self, + "Unexpected content of %s", + kAndroidHardcodedSystemPropertiesFieldName); + return; + } + if (h_key->Equals(h_string_array->Get(0))) { + // Found a value. + if (h_string_array->Get(1) == nullptr && is_default_version) { + // Null is being delegated to the default map, and then resolved to the given default value. + // As there's no default map, return the given value. + result->SetL(shadow_frame->GetVRegReference(arg_offset + 1)); + } else { + result->SetL(h_string_array->Get(1)); + } + return; + } + } + + // Key is not supported. + AbortTransactionOrFail(self, "getProperty key %s not supported", h_key->ToModifiedUtf8().c_str()); +} + +void UnstartedRuntime::UnstartedSystemGetProperty( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + GetSystemProperty(self, shadow_frame, result, arg_offset, false); +} + +void UnstartedRuntime::UnstartedSystemGetPropertyWithDefault( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + GetSystemProperty(self, shadow_frame, result, arg_offset, true); +} + void UnstartedRuntime::UnstartedThreadLocalGet( Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) { std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod())); diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h index 3312701135..3b5bee829e 100644 --- a/runtime/interpreter/unstarted_runtime_list.h +++ b/runtime/interpreter/unstarted_runtime_list.h @@ -34,6 +34,8 @@ V(SystemArraycopyChar, "void java.lang.System.arraycopy(char[], int, char[], int, int)") \ V(SystemArraycopyInt, "void java.lang.System.arraycopy(int[], int, int[], int, int)") \ V(SystemGetSecurityManager, "java.lang.SecurityManager java.lang.System.getSecurityManager()") \ + V(SystemGetProperty, "java.lang.String java.lang.System.getProperty(java.lang.String)") \ + V(SystemGetPropertyWithDefault, "java.lang.String java.lang.System.getProperty(java.lang.String, java.lang.String)") \ V(ThreadLocalGet, "java.lang.Object java.lang.ThreadLocal.get()") \ V(MathCeil, "double java.lang.Math.ceil(double)") \ V(MathFloor, "double java.lang.Math.floor(double)") \ |