diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk index 889018dcec3..08156a6bea3 100644 --- a/build/Android.common_build.mk +++ b/build/Android.common_build.mk @@ -195,7 +195,6 @@ art_cflags := \ -Wunreachable-code \ -Wredundant-decls \ -Wshadow \ - -Wunused \ -fvisibility=protected \ $(art_default_gc_type_cflags) diff --git a/build/Android.executable.mk b/build/Android.executable.mk index dfea6e191e7..379ec7c9cba 100644 --- a/build/Android.executable.mk +++ b/build/Android.executable.mk @@ -47,6 +47,7 @@ define build-art-executable art_target_or_host := $(5) art_ndebug_or_debug := $(6) art_multilib := $(7) + art_static_libraries := $(8) art_out_binary_name := include $(CLEAR_VARS) @@ -55,6 +56,7 @@ define build-art-executable LOCAL_SRC_FILES := $$(art_source) LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime art/cmdline $$(art_c_includes) LOCAL_SHARED_LIBRARIES += $$(art_shared_libraries) + LOCAL_STATIC_LIBRARIES += $$(art_static_libraries) LOCAL_WHOLE_STATIC_LIBRARIES += libsigchain ifeq ($$(art_ndebug_or_debug),ndebug) diff --git a/dex2oat/Android.mk b/dex2oat/Android.mk index 3783c2b4ba3..4cb5f7f3be2 100644 --- a/dex2oat/Android.mk +++ b/dex2oat/Android.mk @@ -42,16 +42,16 @@ else endif ifeq ($(ART_BUILD_TARGET_NDEBUG),true) - $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler,art/compiler,target,ndebug,$(dex2oat_target_arch))) + $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler,art/compiler,target,ndebug,$(dex2oat_target_arch),libxz)) endif ifeq ($(ART_BUILD_TARGET_DEBUG),true) - $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler,art/compiler,target,debug,$(dex2oat_target_arch))) + $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler,art/compiler,target,debug,$(dex2oat_target_arch),libxz)) endif # We always build dex2oat and dependencies, even if the host build is otherwise disabled, since they are used to cross compile for the target. ifeq ($(ART_BUILD_HOST_NDEBUG),true) - $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler libziparchive-host,art/compiler,host,ndebug,$(dex2oat_host_arch))) + $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler libziparchive-host,art/compiler,host,ndebug,$(dex2oat_host_arch),libxz_host)) endif ifeq ($(ART_BUILD_HOST_DEBUG),true) - $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler libziparchive-host,art/compiler,host,debug,$(dex2oat_host_arch))) + $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler libziparchive-host,art/compiler,host,debug,$(dex2oat_host_arch),libxz_host)) endif diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 4740e86496f..c0ee890d2a2 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -79,6 +79,9 @@ #ifdef HAVE_ANDROID_OS #include "cutils/properties.h" #endif +#include "xz_config.h" +#include "xz.h" +#include "xz_private.h" namespace art { @@ -1325,7 +1328,7 @@ class Dex2Oat FINAL { } ATRACE_END(); } else { - size_t failure_count = OpenDexFiles(dex_filenames_, dex_locations_, &opened_dex_files_); + size_t failure_count = OpenDexFiles(dex_filenames_, dex_locations_, &opened_dex_files_, swap_fd_); if (failure_count > 0) { LOG(ERROR) << "Failed to open some dex files: " << failure_count; return false; @@ -1673,9 +1676,116 @@ class Dex2Oat FINAL { } private: + static File* InflateXZ(const std::string& filename, int out_fd, std::string* err) { + if (out_fd == -1) { + *err = "No swap file available"; + return nullptr; + } + + struct xz_buf b; + struct xz_dec *dec; + uint8_t xz_out[BUFSIZ]; + enum xz_ret ret; + std::string uncompressed; + + std::ifstream t(filename.c_str()); + std::ostringstream in_contents; + in_contents << t.rdbuf(); + std::string input_str = in_contents.str(); + + b.in = (const uint8_t*) input_str.c_str(); + b.in_pos = 0; + b.in_size = input_str.length(); + b.out = xz_out; + b.out_pos = 0; + b.out_size = BUFSIZ; + + xz_crc32_init(); + + xz_crc64_init(); + + dec = xz_dec_init(XZ_DYNALLOC, 1 << 26); + if(dec == NULL) { + LOG(WARNING) << "xz_dec_init FAILED!"; + return nullptr; + } + + while (b.in_pos != b.in_size) { + ret = xz_dec_run(dec, &b); + uncompressed.append((const char*) xz_out, b.out_pos); + b.out_pos = 0; + + if (ret == XZ_OK) + continue; + + if (ret == XZ_STREAM_END) { + + xz_dec_end(dec); + + std::unique_ptr out_file_ptr(new File(out_fd, false)); + + if (!out_file_ptr->WriteFully(uncompressed.c_str(), uncompressed.length())) { + *err = StringPrintf("Could not write to fd=%d", out_fd); + return nullptr; + } + + if (out_file_ptr->Flush() != 0) { + *err = StringPrintf("Could not flush swap file fd=%d", out_fd); + return nullptr; + } + + out_file_ptr->DisableAutoClose(); + return out_file_ptr.release(); + } + + if (ret == XZ_UNSUPPORTED_CHECK) { + LOG(WARNING) << "Unsupported check; not verifying file integrity"; + continue; + } + + if (ret == XZ_MEM_ERROR) { + LOG(ERROR) << "Memory allocation failed"; + break; + } + + if (ret == XZ_MEMLIMIT_ERROR) { + LOG(ERROR) << "Memory usage limit reached"; + break; + } + + if (ret == XZ_FORMAT_ERROR) { + LOG(ERROR) << "XZ file format error"; + break; + } + + if (ret == XZ_OPTIONS_ERROR) { + LOG(ERROR) << "Unsupported options in the .xz headers"; + break; + } + + if (ret == XZ_DATA_ERROR) { + LOG(ERROR) << "File data corrupt"; + break; + } + + if (ret == XZ_BUF_ERROR) { + LOG(ERROR) << "File buffer corrupt"; + break; + } else { + LOG(ERROR) << "XZ Bug!"; + break; + } + } + + *err = StringPrintf("Could not uncompress file=%s", filename.c_str()); + xz_dec_end(dec); + return nullptr; + } + static size_t OpenDexFiles(const std::vector& dex_filenames, const std::vector& dex_locations, - std::vector>* dex_files) { + std::vector>* dex_files, + int& swap_fd) { DCHECK(dex_files != nullptr) << "OpenDexFiles out-param is nullptr"; size_t failure_count = 0; for (size_t i = 0; i < dex_filenames.size(); i++) { @@ -1687,7 +1797,42 @@ class Dex2Oat FINAL { LOG(WARNING) << "Skipping non-existent dex file '" << dex_filename << "'"; continue; } - if (!DexFile::Open(dex_filename, dex_location, &error_msg, dex_files)) { + std::unique_ptr file; + if (EndsWith(dex_filename, ".xz")) { + file.reset(InflateXZ(dex_filename, swap_fd, &error_msg)); + if (file.get() == nullptr) { + LOG(WARNING) << "Failed to inflate " << dex_filename << "': " << error_msg; + ++failure_count; + continue; + } + swap_fd = -1; + } + if (file.get() != nullptr) { + std::unique_ptr elf_file(ElfFile::Open(file.release(), PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); + if (elf_file.get() == nullptr) { + LOG(WARNING) << "Failed to open ELF file from '" << dex_filename << "': " << error_msg; + ++failure_count; + continue; + } + const OatFile* oat_file = OatFile::OpenWithElfFile(elf_file.release(), dex_filename, nullptr, &error_msg); + if (oat_file == nullptr) { + LOG(WARNING) << "Failed to open oat file from '" << dex_filename << "': " << error_msg; + ++failure_count; + continue; + } else { + for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) { + CHECK(oat_dex_file != nullptr); + std::unique_ptr dex_file(oat_dex_file->OpenDexFile(&error_msg)); + if (dex_file.get() != nullptr) { + dex_files->push_back(std::move(dex_file)); + } else { + LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation() + << "' from file '" << dex_filename << "': " << error_msg; + ++failure_count; + } + } + } + } else if (!DexFile::Open(dex_filename, dex_location, &error_msg, dex_files)) { LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "': " << error_msg; ++failure_count; } diff --git a/runtime/Android.mk b/runtime/Android.mk index 684bef2815d..6e390920cfe 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -142,6 +142,7 @@ LIBART_COMMON_SRC_FILES := \ native/libcore_util_CharsetUtils.cc \ native/org_apache_harmony_dalvik_ddmc_DdmServer.cc \ native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc \ + native/samsung.cc \ native/sun_misc_Unsafe.cc \ oat.cc \ oat_file.cc \ diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 6bc5acf8398..2757fa82b75 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -285,6 +285,39 @@ ClassLinker::ClassLinker(InternTable* intern_table) std::fill_n(find_array_class_cache_, kFindArrayCacheSize, GcRoot(nullptr)); } +static void dexCacheExtraFieldsWorkaround(const DexFile* dex_file) { + const char* descriptor = "Ljava/lang/DexCache;"; + const size_t hash = ComputeModifiedUtf8Hash(descriptor); + const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor, hash); + if (dex_class_def != nullptr) { + const uint8_t* class_data = dex_file->GetClassData(*dex_class_def); + if (class_data != nullptr) { + for (ClassDataItemIterator it(*dex_file, class_data); it.HasNextInstanceField(); it.Next()) { + const DexFile::FieldId& field_id = dex_file->GetFieldId(it.GetMemberIndex()); + const char* name = dex_file->GetFieldName(field_id); + // Additional fields are normally 'literals' and 'z_padding'. + // Some devices have only 'literals' (without 'z_padding') but they work the same. + if (strcmp(name, "literals") == 0) { + mirror::sDexCacheJavaClassHasExtraFields = true; + LOG(INFO) << "java.lang.DexCache compatibility mode"; + break; + } + } + } + } +} + +static void checkOatFileDexCacheExtraFields(OatFile& oat_file) { + // Workaround for DexCache extra fields + std::string core_libart_jar = GetAndroidRoot(); + core_libart_jar += "/framework/core-libart.jar"; + const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(core_libart_jar.c_str(), nullptr); + std::string error_msg; + std::unique_ptr dex_file = oat_dex_file->OpenDexFile(&error_msg); + dexCacheExtraFieldsWorkaround(dex_file.get()); + dex_file.reset(); +} + void ClassLinker::InitWithoutImage(std::vector> boot_class_path) { VLOG(startup) << "ClassLinker::Init"; @@ -409,6 +442,18 @@ void ClassLinker::InitWithoutImage(std::vector> b // now that these are registered, we can use AllocClass() and AllocObjectArray + CHECK_NE(0U, boot_class_path.size()); + std::string core_libart_jar = GetAndroidRoot(); + core_libart_jar += "/framework/core-libart.jar"; + for (auto& dex_file : boot_class_path) { + CHECK(dex_file.get() != nullptr); + // Workaround for DexCache extra fields. and String extra method + if (dex_file->GetLocation() == core_libart_jar.c_str()) { + dexCacheExtraFieldsWorkaround(dex_file.get()); + break; + } + } + // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache. Handle java_lang_DexCache(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::DexCache::ClassSize(image_pointer_size_)))); @@ -431,9 +476,9 @@ void ClassLinker::InitWithoutImage(std::vector> b // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses // these roots. - CHECK_NE(0U, boot_class_path.size()); for (auto& dex_file : boot_class_path) { CHECK(dex_file.get() != nullptr); + AppendToBootClassPath(self, *dex_file); opened_dex_files_.push_back(std::move(dex_file)); } @@ -1134,6 +1179,9 @@ void ClassLinker::InitFromImage() { CHECK_EQ(oat_file.GetOatHeader().GetDexFileCount(), static_cast(dex_caches->GetLength())); + + checkOatFileDexCacheExtraFields(oat_file); + for (int32_t i = 0; i < dex_caches->GetLength(); i++) { StackHandleScope<1> hs2(self); Handle dex_cache(hs2.NewHandle(dex_caches->Get(i))); diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 2c6e71cd119..81791493398 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -2170,6 +2170,12 @@ class JNI { } if (m == nullptr) { + if (PrettyDescriptor(c) == "dalvik.system.PathClassLoader" && strcmp(name, "openNative") == 0) { + LOG(WARNING) << "Native method " << PrettyDescriptor(c) << "." << name << sig + << " not found in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8(); + continue; + } + LOG(return_errors ? ERROR : INTERNAL_FATAL) << "Failed to register native method " << PrettyDescriptor(c) << "." << name << sig << " in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8(); diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index 630faee3564..1c623e40b8b 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -31,6 +31,8 @@ namespace art { namespace mirror { +bool sDexCacheJavaClassHasExtraFields = false; + void DexCache::Init(const DexFile* dex_file, String* location, ObjectArray* strings, ObjectArray* resolved_types, PointerArray* resolved_methods, PointerArray* resolved_fields, size_t pointer_size) { @@ -42,10 +44,10 @@ void DexCache::Init(const DexFile* dex_file, String* location, ObjectArray(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location); + SetFieldObject(LocationOffset(), location); SetFieldObject(StringsOffset(), strings); SetFieldObject(ResolvedFieldsOffset(), resolved_fields); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types); + SetFieldObject(ResolvedTypesOffset(), resolved_types); SetFieldObject(ResolvedMethodsOffset(), resolved_methods); Runtime* const runtime = Runtime::Current(); diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h index 0ce83ec746f..7f6e6df9f18 100644 --- a/runtime/mirror/dex_cache.h +++ b/runtime/mirror/dex_cache.h @@ -23,6 +23,7 @@ #include "class.h" #include "object.h" #include "object_array.h" +#include "utils.h" namespace art { @@ -35,6 +36,10 @@ namespace mirror { class String; +// A flag for devices that have an additional 'String[] literals' field +// on the java class side. Mostly comes with 'Object z_padding' as well. +extern bool sDexCacheJavaClassHasExtraFields; + // C++ mirror of java.lang.DexCache. class MANAGED DexCache FINAL : public Object { public: @@ -42,8 +47,8 @@ class MANAGED DexCache FINAL : public Object { static uint32_t ClassSize(size_t pointer_size); // Size of an instance of java.lang.DexCache not including referenced values. - static constexpr uint32_t InstanceSize() { - return sizeof(DexCache); + static uint32_t InstanceSize() { + return sizeof(DexCache) + (sDexCacheJavaClassHasExtraFields ? 8 : 0); } void Init(const DexFile* dex_file, String* location, ObjectArray* strings, @@ -54,7 +59,11 @@ class MANAGED DexCache FINAL : public Object { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); String* GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, location_)); + return GetFieldObject(LocationOffset()); + } + + static MemberOffset LocationOffset() { + return MemberOffset(OFFSETOF_MEMBER(DexCache, location_) + (sDexCacheJavaClassHasExtraFields ? 4 : 0)); } static MemberOffset DexOffset() { @@ -62,15 +71,23 @@ class MANAGED DexCache FINAL : public Object { } static MemberOffset StringsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_); + return MemberOffset(OFFSETOF_MEMBER(DexCache, strings_) + (sDexCacheJavaClassHasExtraFields ? 4 : 0)); } static MemberOffset ResolvedFieldsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_fields_); + return MemberOffset(OFFSETOF_MEMBER(DexCache, resolved_fields_) + (sDexCacheJavaClassHasExtraFields ? 4 : 0)); } static MemberOffset ResolvedMethodsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_); + return MemberOffset(OFFSETOF_MEMBER(DexCache, resolved_methods_) + (sDexCacheJavaClassHasExtraFields ? 4 : 0)); + } + + static MemberOffset ResolvedTypesOffset() { + return MemberOffset(OFFSETOF_MEMBER(DexCache, resolved_types_) + (sDexCacheJavaClassHasExtraFields ? 4 : 0)); + } + + static MemberOffset DexFileOffset() { + return MemberOffset(OFFSETOF_MEMBER(DexCache, dex_file_) + (sDexCacheJavaClassHasExtraFields ? 8 : 0)); } size_t NumStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -127,7 +144,7 @@ class MANAGED DexCache FINAL : public Object { ObjectArray* GetResolvedTypes() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return GetFieldObject>( - OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_)); + ResolvedTypesOffset()); } PointerArray* GetResolvedMethods() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -139,12 +156,12 @@ class MANAGED DexCache FINAL : public Object { } const DexFile* GetDexFile() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetFieldPtr(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_)); + return GetFieldPtr(DexFileOffset()); } void SetDexFile(const DexFile* dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { - return SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file); + return SetFieldPtr(DexFileOffset(), dex_file); } private: diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h index d283f588660..9ba0134800a 100644 --- a/runtime/mirror/string-inl.h +++ b/runtime/mirror/string-inl.h @@ -32,6 +32,11 @@ namespace mirror { inline uint32_t String::ClassSize(size_t pointer_size) { uint32_t vtable_entries = Object::kVTableLength + 52; + if (IsSamsungROM()) { + // Samsung added a new method "string.clear()" + // Increase vtable length to support it + vtable_entries++; + } return Class::ComputeClassSize(true, vtable_entries, 0, 1, 0, 1, 2, pointer_size); } diff --git a/runtime/native/samsung.cc b/runtime/native/samsung.cc new file mode 100644 index 00000000000..acf59703c4a --- /dev/null +++ b/runtime/native/samsung.cc @@ -0,0 +1,25 @@ +#include "jni_internal.h" +#include "mirror/class-inl.h" +#include "samsung.h" + +namespace art { + +//---------------------------------------------------- +// dalvik.system.PathClassLoader + +static jobject PathClassLoader_openNative(JNIEnv* env, jobject javaThis) { + // Ignore Samsung native method and use the default PathClassLoader constructor + return nullptr; +} + +static JNINativeMethod gMethodsPathClassLoader[] = { + NATIVE_METHOD(PathClassLoader, openNative, "!(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)Ldalvik/system/PathClassLoader;"), +}; + + +//---------------------------------------------------- +void register_samsung_native_methods(JNIEnv* env) { + RegisterNativeMethods(env, "dalvik/system/PathClassLoader", gMethodsPathClassLoader, arraysize(gMethodsPathClassLoader)); +} + +} // namespace art diff --git a/runtime/native/samsung.h b/runtime/native/samsung.h new file mode 100644 index 00000000000..5a0aa217328 --- /dev/null +++ b/runtime/native/samsung.h @@ -0,0 +1,13 @@ + +#ifndef ART_RUNTIME_NATIVE_SAMSUNG_H_ +#define ART_RUNTIME_NATIVE_SAMSUNG_H_ + +#include + +namespace art { + +void register_samsung_native_methods(JNIEnv* env); + +} // namespace art + +#endif // ART_RUNTIME_NATIVE_SAMSUNG_H_ diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 768a3b2931f..0a4f3b60302 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -489,6 +489,22 @@ bool OatFile::Setup(const char* abs_dex_location, const std::string* elf_filenam const DexFile::Header* header = reinterpret_cast(dex_file_pointer); const uint32_t* methods_offsets_pointer = reinterpret_cast(oat); + /* + * Samsung has introduced a TypeLookupTable for each dex file in their oat files. + * Its relative offset is stored between the dex_file_offset and the methods_offsets_pointer. + * The lookup tables themselves are stored between the OatDexFiles (which we are currently + * iterating over) and the DexFiles. The OatClasses are stored further down the file. + * + * This means that on Samsung ROMs (with files created by Samsung's adjusted libart-compiler.so), + * methods_offsets_pointer[0] will actually hold the offset of the TypeLookupTable, which + * is lower than the DexFile. If we detect this case, we skip (and ignore) the value and + * adjust methods_offsets_pointer to point to the correct address. + */ + if (methods_offsets_pointer[0] < dex_file_offset) { + oat += sizeof(uint32_t); + methods_offsets_pointer = reinterpret_cast(oat); + } + oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_); if (UNLIKELY(oat > End())) { *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated " diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 1796b3d2706..28a42fd4a71 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -245,7 +245,7 @@ bool OatFileAssistant::HasOriginalDexFiles() { // has_original_dex_files_ is initialized. We don't care about the result of // GetRequiredDexChecksum. GetRequiredDexChecksum(); - return has_original_dex_files_; + return has_original_dex_files_ || EndsWith(OdexFileName()->c_str(), ".xz"); } const std::string* OatFileAssistant::OdexFileName() { @@ -260,13 +260,18 @@ const std::string* OatFileAssistant::OdexFileName() { // If we can't figure out the odex file, we treat it as if the odex // file was inaccessible. LOG(WARNING) << "Failed to determine odex file name: " << error_msg; + } else if (!OS::FileExists(cached_odex_file_name_.c_str())) { + std::string filename (cached_odex_file_name_ + ".xz"); + if (OS::FileExists(filename.c_str())) { + cached_odex_file_name_ = filename; + } } } return cached_odex_file_name_found_ ? &cached_odex_file_name_ : nullptr; } bool OatFileAssistant::OdexFileExists() { - return GetOdexFile() != nullptr; + return GetOdexFile() != nullptr || EndsWith(OdexFileName()->c_str(), ".xz"); } OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() { diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 96fa0d91b53..0f14e0a05b6 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -110,6 +110,7 @@ #include "native/libcore_util_CharsetUtils.h" #include "native/org_apache_harmony_dalvik_ddmc_DdmServer.h" #include "native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.h" +#include "native/samsung.h" #include "native/sun_misc_Unsafe.h" #include "native_bridge_art_interface.h" #include "oat_file.h" @@ -1235,6 +1236,7 @@ void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { register_libcore_util_CharsetUtils(env); register_org_apache_harmony_dalvik_ddmc_DdmServer(env); register_org_apache_harmony_dalvik_ddmc_DdmVmInternal(env); + register_samsung_native_methods(env); register_sun_misc_Unsafe(env); } diff --git a/runtime/utils.cc b/runtime/utils.cc index 3a24c7ae482..4b2fdd42dd5 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -1457,4 +1457,14 @@ std::string PrettyDescriptor(Primitive::Type type) { return PrettyDescriptor(Primitive::Descriptor(type)); } +bool IsSamsungROM() { + static bool checked = false; + static bool result = false; + if (!checked) { + result = OS::FileExists("/system/framework/twframework.jar"); + checked = true; + } + return result; +} + } // namespace art diff --git a/runtime/utils.h b/runtime/utils.h index 1ef98e70d58..a999921002b 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -324,6 +324,9 @@ static inline constexpr bool ValidPointerSize(size_t pointer_size) { return pointer_size == 4 || pointer_size == 8; } + +bool IsSamsungROM(); + } // namespace art #endif // ART_RUNTIME_UTILS_H_