Merge "Actually use --copy-and-update-profile-key argument in profman..."
diff --git a/Android.bp b/Android.bp
index ad42d3f..bb92e5f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,7 +1,6 @@
// TODO: These should be handled with transitive static library dependencies
art_static_dependencies = [
// Note: the order is important because of static linking resolution.
- "libdexfile",
"libziparchive",
"libnativehelper",
"libnativebridge",
diff --git a/Android.mk b/Android.mk
index 361ceec..2489308 100644
--- a/Android.mk
+++ b/Android.mk
@@ -79,6 +79,7 @@
include $(art_path)/oatdump/Android.mk
include $(art_path)/tools/Android.mk
include $(art_path)/tools/ahat/Android.mk
+include $(art_path)/tools/amm/Android.mk
include $(art_path)/tools/dexfuzz/Android.mk
include $(art_path)/libart_fake/Android.mk
@@ -486,8 +487,10 @@
$(ART_TARGET_SHARED_LIBRARY_BENCHMARK) \
$(TARGET_CORE_IMG_OUT_BASE).art \
$(TARGET_CORE_IMG_OUT_BASE)-interpreter.art
+ # remove libartd.so and libdexfiled.so from public.libraries.txt because golem builds
+ # won't have it.
sed -i '/libartd.so/d' $(TARGET_OUT)/etc/public.libraries.txt
- # remove libartd.so from public.libraries.txt because golem builds won't have it.
+ sed -i '/libdexfiled.so/d' $(TARGET_OUT)/etc/public.libraries.txt
########################################################################
# Phony target for building what go/lem requires on host.
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 4539659..ba08d79 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -184,7 +184,6 @@
},
generated_sources: ["art_compiler_operator_srcs"],
shared_libs: [
- "libdexfile",
"libbase",
"libcutils", // for atrace.
"liblzma",
@@ -250,6 +249,7 @@
},
shared_libs: [
"libart",
+ "libdexfile",
],
pgo: {
@@ -295,6 +295,7 @@
},
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 43ca2cf..f91d37b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4567,7 +4567,7 @@
kFieldClinitCheckRequirementSize>;
// Cached values of the resolved method, to avoid needing the mutator lock.
- MethodReference target_method_;
+ const MethodReference target_method_;
DispatchInfo dispatch_info_;
};
std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs);
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index ab06ddd..dd16ba4 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -152,7 +152,7 @@
"libartd-compiler",
"libartd-dexlayout",
"libartd",
- "libdexfile",
+ "libdexfiled",
"libbase",
"liblz4",
"libsigchain",
@@ -185,6 +185,7 @@
"libart-compiler",
"libart-dexlayout",
"libart",
+ "libdexfile",
"libvixl-arm",
"libvixl-arm64",
] + art_static_dependencies,
@@ -216,6 +217,7 @@
"libartd-compiler",
"libartd-dexlayout",
"libartd",
+ "libdexfiled",
"libvixld-arm",
"libvixld-arm64",
] + art_static_dependencies,
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
index f6b7a6b..eca0844 100644
--- a/dexdump/Android.bp
+++ b/dexdump/Android.bp
@@ -45,6 +45,7 @@
host_supported: true,
device_supported: false,
static_libs: [
+ "libdexfile",
"libbase",
] + art_static_dependencies,
target: {
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 3ea7f4b..bea61d0 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -27,7 +27,6 @@
],
export_include_dirs: ["."],
shared_libs: [
- "libdexfile",
"libbase",
],
static_libs: ["libz"],
@@ -36,7 +35,10 @@
art_cc_library {
name: "libart-dexlayout",
defaults: ["libart-dexlayout-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
pgo: {
instrumentation: true,
@@ -51,7 +53,10 @@
"libart-dexlayout-defaults",
"art_debug_defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
cc_defaults {
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index bcf2bdb..90c603f 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -93,6 +93,14 @@
},
}
+art_cc_library {
+ name: "libdexfiled",
+ defaults: [
+ "art_debug_defaults",
+ "libdexfile_defaults",
+ ],
+}
+
art_cc_test {
name: "art_libdexfile_tests",
defaults: [
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 18eb903..6a704c1 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,6 +45,21 @@
static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
+void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) {
+ uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer());
+ uint32_t new_flag = class_it.GetMemberAccessFlags();
+ bool is_method = class_it.IsAtMethod();
+ // Go back 1 uleb to start.
+ data = ReverseSearchUnsignedLeb128(data);
+ if (is_method) {
+ // Methods have another uleb field before the access flags
+ data = ReverseSearchUnsignedLeb128(data);
+ }
+ DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
+ new_flag);
+ UpdateUnsignedLeb128(data, new_flag);
+}
+
uint32_t DexFile::CalculateChecksum() const {
return CalculateChecksum(Begin(), Size());
}
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index a38e76c..a62ab62 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -35,6 +35,7 @@
namespace art {
+class ClassDataItemIterator;
class CompactDexFile;
enum InvokeType : uint32_t;
class MemMap;
@@ -1000,6 +1001,9 @@
return container_.get();
}
+ // Changes the dex file pointed to by class_it to not have any hiddenapi flags.
+ static void UnHideAccessFlags(ClassDataItemIterator& class_it);
+
protected:
// First Dex format version supporting default methods.
static const uint32_t kDefaultMethodsVersion = 37;
diff --git a/oatdump/Android.bp b/oatdump/Android.bp
index c93c172..012100d 100644
--- a/oatdump/Android.bp
+++ b/oatdump/Android.bp
@@ -51,7 +51,7 @@
"libartd",
"libartd-compiler",
"libartd-disassembler",
- "libdexfile",
+ "libdexfiled",
"libbase",
],
}
@@ -76,6 +76,7 @@
],
static_libs: [
"libart",
+ "libdexfile",
"libart-compiler",
"libart-disassembler",
"libvixl-arm",
@@ -106,6 +107,7 @@
],
static_libs: [
"libartd",
+ "libdexfiled",
"libartd-compiler",
"libartd-disassembler",
"libvixld-arm",
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
index 1500bca..1553b78 100644
--- a/openjdkjvmti/Android.bp
+++ b/openjdkjvmti/Android.bp
@@ -58,7 +58,6 @@
"libopenjdkjvmti_headers",
],
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -70,6 +69,7 @@
"libart",
"libart-compiler",
"libart-dexlayout",
+ "libdexfile",
],
}
@@ -83,5 +83,6 @@
"libartd",
"libartd-compiler",
"libartd-dexlayout",
+ "libdexfiled",
],
}
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index 427d87e..90c6449 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -40,6 +40,7 @@
#include "dex/compact_dex_level.h"
#include "dex_to_dex_decompiler.h"
#include "dexlayout.h"
+#include "leb128.h"
#include "oat_file.h"
#include "vdex_file.h"
@@ -50,21 +51,41 @@
dex_file->CalculateChecksum();
}
-static void DoDexUnquicken(const art::DexFile& new_dex_file,
- const art::DexFile& original_dex_file) {
+static void UnhideApis(const art::DexFile& target_dex_file) {
+ for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
+ const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i));
+ if (class_data != nullptr) {
+ for (art::ClassDataItemIterator class_it(target_dex_file, class_data);
+ class_it.HasNext();
+ class_it.Next()) {
+ art::DexFile::UnHideAccessFlags(class_it);
+ }
+ }
+ }
+}
+
+static const art::VdexFile* GetVdex(const art::DexFile& original_dex_file) {
const art::OatDexFile* oat_dex = original_dex_file.GetOatDexFile();
if (oat_dex == nullptr) {
- return;
+ return nullptr;
}
const art::OatFile* oat_file = oat_dex->GetOatFile();
if (oat_file == nullptr) {
- return;
+ return nullptr;
}
- const art::VdexFile* vdex = oat_file->GetVdexFile();
- if (vdex == nullptr) {
- return;
+ return oat_file->GetVdexFile();
+}
+
+static void DoDexUnquicken(const art::DexFile& new_dex_file,
+ const art::DexFile& original_dex_file) {
+ const art::VdexFile* vdex = GetVdex(original_dex_file);
+ if (vdex != nullptr) {
+ vdex->UnquickenDexFile(new_dex_file, original_dex_file, /* decompile_return_instruction */true);
+ } else {
+ // The dex file isn't quickened since it is being used directly. We might still have hiddenapis
+ // so we need to get rid of those.
+ UnhideApis(new_dex_file);
}
- vdex->UnquickenDexFile(new_dex_file, original_dex_file, /* decompile_return_instruction */true);
}
static void DCheckVerifyDexFile(const art::DexFile& dex) {
diff --git a/profman/Android.bp b/profman/Android.bp
index 6592b9d..163be2b 100644
--- a/profman/Android.bp
+++ b/profman/Android.bp
@@ -31,7 +31,6 @@
},
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -41,6 +40,7 @@
defaults: ["profman-defaults"],
shared_libs: [
"libart",
+ "libdexfile",
],
}
@@ -52,6 +52,7 @@
],
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 110b04f..1ac770f 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -409,7 +409,6 @@
"jni_platform_headers",
],
shared_libs: [
- "libdexfile",
"libnativebridge",
"libnativeloader",
"libbacktrace",
@@ -430,10 +429,7 @@
// ART's macros.h depends on libbase's macros.h.
// Note: runtime_options.h depends on cmdline. But we don't really want to export this
// generically. dex2oat takes care of it itself.
- export_shared_lib_headers: [
- "libbase",
- "libdexfile",
- ],
+ export_shared_lib_headers: ["libbase"],
}
gensrcs {
@@ -490,6 +486,8 @@
strip: {
keep_symbols: true,
},
+ shared_libs: ["libdexfile"],
+ export_shared_lib_headers: ["libdexfile"],
}
art_cc_library {
@@ -498,6 +496,8 @@
"art_debug_defaults",
"libart_defaults",
],
+ shared_libs: ["libdexfiled"],
+ export_shared_lib_headers: ["libdexfiled"],
}
art_cc_library {
diff --git a/runtime/base/stringpiece.cc b/runtime/base/stringpiece.cc
index 672431c..aea4e74 100644
--- a/runtime/base/stringpiece.cc
+++ b/runtime/base/stringpiece.cc
@@ -23,13 +23,6 @@
namespace art {
-#if !defined(NDEBUG)
-char StringPiece::operator[](size_type i) const {
- CHECK_LT(i, length_);
- return ptr_[i];
-}
-#endif
-
void StringPiece::CopyToString(std::string* target) const {
target->assign(ptr_, length_);
}
diff --git a/runtime/base/stringpiece.h b/runtime/base/stringpiece.h
index 46743e9..e7109dc 100644
--- a/runtime/base/stringpiece.h
+++ b/runtime/base/stringpiece.h
@@ -20,6 +20,8 @@
#include <string.h>
#include <string>
+#include <android-base/logging.h>
+
namespace art {
// A string-like object that points to a sized piece of memory.
@@ -84,13 +86,10 @@
length_ = len;
}
-#if defined(NDEBUG)
char operator[](size_type i) const {
+ DCHECK_LT(i, length_);
return ptr_[i];
}
-#else
- char operator[](size_type i) const;
-#endif
void remove_prefix(size_type n) {
ptr_ += n;
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 5549122..05f099f 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -46,6 +46,7 @@
#include "well_known_classes.h"
namespace art {
+namespace {
using android::base::StringAppendF;
using android::base::StringPrintf;
@@ -1211,7 +1212,7 @@
// this particular instance of JNIEnv.
if (env != threadEnv) {
// Get the thread owning the JNIEnv that's being used.
- Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self_;
+ Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
AbortF("thread %s using JNIEnv* from thread %s",
ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
return false;
@@ -1223,7 +1224,7 @@
case kFlag_CritOkay: // okay to call this method
break;
case kFlag_CritBad: // not okay to call
- if (threadEnv->critical_ > 0) {
+ if (threadEnv->GetCritical() > 0) {
AbortF("thread %s using JNI after critical get",
ToStr<Thread>(*self).c_str());
return false;
@@ -1231,25 +1232,25 @@
break;
case kFlag_CritGet: // this is a "get" call
// Don't check here; we allow nested gets.
- if (threadEnv->critical_ == 0) {
- threadEnv->critical_start_us_ = self->GetCpuMicroTime();
+ if (threadEnv->GetCritical() == 0) {
+ threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
}
- threadEnv->critical_++;
+ threadEnv->SetCritical(threadEnv->GetCritical() + 1);
break;
case kFlag_CritRelease: // this is a "release" call
- if (threadEnv->critical_ == 0) {
+ if (threadEnv->GetCritical() == 0) {
AbortF("thread %s called too many critical releases",
ToStr<Thread>(*self).c_str());
return false;
- } else if (threadEnv->critical_ == 1) {
+ } else if (threadEnv->GetCritical() == 1) {
// Leaving the critical region, possibly warn about long critical regions.
- uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->critical_start_us_;
+ uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
if (critical_duration_us > kCriticalWarnTimeUs) {
LOG(WARNING) << "JNI critical lock held for "
<< PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
}
}
- threadEnv->critical_--;
+ threadEnv->SetCritical(threadEnv->GetCritical() - 1);
break;
default:
LOG(FATAL) << "Bad flags (internal error): " << flags_;
@@ -2621,7 +2622,7 @@
}
static const JNINativeInterface* baseEnv(JNIEnv* env) {
- return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions_;
+ return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
}
static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
@@ -3847,10 +3848,6 @@
CheckJNI::GetObjectRefType,
};
-const JNINativeInterface* GetCheckJniNativeInterface() {
- return &gCheckNativeInterface;
-}
-
class CheckJII {
public:
static jint DestroyJavaVM(JavaVM* vm) {
@@ -3922,6 +3919,12 @@
CheckJII::AttachCurrentThreadAsDaemon
};
+} // anonymous namespace
+
+const JNINativeInterface* GetCheckJniNativeInterface() {
+ return &gCheckNativeInterface;
+}
+
const JNIInvokeInterface* GetCheckJniInvokeInterface() {
return &gCheckInvokeInterface;
}
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index cd6e8d5..ae06f8f 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -226,14 +226,7 @@
const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
if (klass != nullptr) {
- if (klass->IsInterface()) {
- resolved = klass->FindInterfaceMethod(dex_cache, method_idx, pointer_size);
- } else {
- resolved = klass->FindClassMethod(dex_cache, method_idx, pointer_size);
- }
- if (resolved != nullptr) {
- dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size);
- }
+ resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
}
}
return resolved;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c4b1bf8..6262728 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7939,6 +7939,38 @@
return oss.str();
}
+ArtMethod* ClassLinker::FindResolvedMethod(ObjPtr<mirror::Class> klass,
+ ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader,
+ uint32_t method_idx) {
+ // Search for the method using dex_cache and method_idx. The Class::Find*Method()
+ // functions can optimize the search if the dex_cache is the same as the DexCache
+ // of the class, with fall-back to name and signature search otherwise.
+ ArtMethod* resolved = nullptr;
+ if (klass->IsInterface()) {
+ resolved = klass->FindInterfaceMethod(dex_cache, method_idx, image_pointer_size_);
+ } else {
+ resolved = klass->FindClassMethod(dex_cache, method_idx, image_pointer_size_);
+ }
+ DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
+ if (resolved != nullptr) {
+ // In case of jmvti, the dex file gets verified before being registered, so first
+ // check if it's registered before checking class tables.
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ CHECK(!IsDexFileRegistered(Thread::Current(), dex_file) ||
+ FindClassTable(Thread::Current(), dex_cache) == ClassTableForClassLoader(class_loader))
+ << "DexFile referrer: " << dex_file.GetLocation()
+ << " ClassLoader: " << DescribeLoaders(class_loader, "");
+ // Be a good citizen and update the dex cache to speed subsequent calls.
+ dex_cache->SetResolvedMethod(method_idx, resolved, image_pointer_size_);
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
+ CHECK(LookupResolvedType(method_id.class_idx_, dex_cache, class_loader) != nullptr)
+ << "Class: " << klass->PrettyClass() << ", "
+ << "DexFile referrer: " << dex_file.GetLocation();
+ }
+ return resolved;
+}
+
template <ClassLinker::ResolveMode kResolveMode>
ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
Handle<mirror::DexCache> dex_cache,
@@ -7971,6 +8003,7 @@
<< resolved->PrettyMethod() << ";" << resolved
<< "/0x" << std::hex << resolved->GetAccessFlags()
<< " ReferencedClass: " << descriptor
+ << " DexFile referrer: " << dex_file.GetLocation()
<< " ClassLoader: " << DescribeLoaders(class_loader.Get(), descriptor);
}
} else {
@@ -7991,19 +8024,7 @@
}
if (!valid_dex_cache_method) {
- // Search for the method using dex_cache and method_idx. The Class::Find*Method()
- // functions can optimize the search if the dex_cache is the same as the DexCache
- // of the class, with fall-back to name and signature search otherwise.
- if (klass->IsInterface()) {
- resolved = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, pointer_size);
- } else {
- resolved = klass->FindClassMethod(dex_cache.Get(), method_idx, pointer_size);
- }
- DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
- if (resolved != nullptr) {
- // Be a good citizen and update the dex cache to speed subsequent calls.
- dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size);
- }
+ resolved = FindResolvedMethod(klass, dex_cache.Get(), class_loader.Get(), method_idx);
}
// Note: We can check for IllegalAccessError only if we have a referrer.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 16fa1ce..6bb924f 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -312,6 +312,13 @@
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Find a method with the given index from class `klass`, and update the dex cache.
+ ArtMethod* FindResolvedMethod(ObjPtr<mirror::Class> klass,
+ ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader,
+ uint32_t method_idx)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Resolve a method with a given ID from the DexFile associated with the given DexCache
// and ClassLoader, storing the result in DexCache. The ClassLinker and ClassLoader are
// used as in ResolveType. What is unique is the method type argument which is used to
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 9ef7d42..404c535 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -99,14 +99,13 @@
<< "This must be due to playing wrongly with class loaders";
}
- inlined_method = klass->FindClassMethod(dex_cache, method_index, kRuntimePointerSize);
+ inlined_method = class_linker->FindResolvedMethod(klass, dex_cache, class_loader, method_index);
if (inlined_method == nullptr) {
LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor
<< " does not have " << dex_file->GetMethodName(method_id)
<< dex_file->GetMethodSignature(method_id) << " declared. "
<< "This must be due to duplicate classes or playing wrongly with class loaders";
}
- dex_cache->SetResolvedMethod(method_index, inlined_method, kRuntimePointerSize);
return inlined_method;
}
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 24cedb0..0ae6dbf 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -269,7 +269,20 @@
}
} else {
CHECK_NE(return_pc, 0U);
- CHECK(!reached_existing_instrumentation_frames_);
+ if (UNLIKELY(reached_existing_instrumentation_frames_)) {
+ std::string thread_name;
+ GetThread()->GetThreadName(thread_name);
+ uint32_t dex_pc = dex::kDexNoIndex;
+ if (last_return_pc_ != 0 &&
+ GetCurrentOatQuickMethodHeader() != nullptr) {
+ dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_);
+ }
+ LOG(FATAL) << "While walking " << thread_name << " found existing instrumentation frames."
+ << " method is " << GetMethod()->PrettyMethod()
+ << " return_pc is " << std::hex << return_pc
+ << " dex pc: " << dex_pc;
+ UNREACHABLE();
+ }
InstrumentationStackFrame instrumentation_frame(
m->IsRuntimeMethod() ? nullptr : GetThisObject(),
m,
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index 8c81c25..ac20afe 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -225,7 +225,7 @@
// Extra checking.
bool check_jni_;
- bool force_copy_;
+ const bool force_copy_;
const bool tracing_enabled_;
// Extra diagnostics.
diff --git a/runtime/jni_env_ext.h b/runtime/jni_env_ext.h
index 0e8fd03..291ac48 100644
--- a/runtime/jni_env_ext.h
+++ b/runtime/jni_env_ext.h
@@ -96,6 +96,15 @@
}
Thread* GetSelf() const { return self_; }
+ uint32_t GetCritical() const { return critical_; }
+ void SetCritical(uint32_t new_critical) { critical_ = new_critical; }
+ uint64_t GetCriticalStartUs() const { return critical_start_us_; }
+ void SetCriticalStartUs(uint64_t new_critical_start_us) {
+ critical_start_us_ = new_critical_start_us;
+ }
+ const JNINativeInterface* GetUncheckedFunctions() const {
+ return unchecked_functions_;
+ }
JavaVMExt* GetVm() const { return vm_; }
bool IsRuntimeDeleted() const { return runtime_deleted_; }
@@ -190,9 +199,7 @@
// If we are a JNI env for a daemon thread with a deleted runtime.
bool runtime_deleted_;
- friend class CheckJNI;
friend class JNI;
- friend class ScopedCheck;
friend class ScopedJniEnvLocalRefState;
friend class Thread;
ART_FRIEND_TEST(JniInternalTest, JNIEnvExtOffsets);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 57a429c..505b745 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -405,18 +405,15 @@
}
const DexFile* dex_file = dex_cache->GetDexFile();
const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
- ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupResolvedType(
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+
+ ObjPtr<mirror::Class> klass = class_linker->LookupResolvedType(
method_id.class_idx_, dex_cache, /* class_loader */ nullptr);
if (klass == nullptr) {
return;
}
- ArtMethod* method = klass->IsInterface()
- ? klass->FindInterfaceMethod(dex_cache, method_idx, kRuntimePointerSize)
- : klass->FindClassMethod(dex_cache, method_idx, kRuntimePointerSize);
- if (method == nullptr) {
- return;
- }
- dex_cache->SetResolvedMethod(method_idx, method, kRuntimePointerSize);
+ // Call FindResolvedMethod to populate the dex cache.
+ class_linker->FindResolvedMethod(klass, dex_cache, /* class_loader */ nullptr, method_idx);
}
struct DexCacheStats {
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 0829c54..443c35f 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -263,18 +263,6 @@
UnquickenDexFile(target_dex_file, source_dex_file.Begin(), decompile_return_instruction);
}
-static void UpdateAccessFlags(uint8_t* data, uint32_t new_flag, bool is_method) {
- // Go back 1 uleb to start.
- data = ReverseSearchUnsignedLeb128(data);
- if (is_method) {
- // Methods have another uleb field before the access flags
- data = ReverseSearchUnsignedLeb128(data);
- }
- DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
- new_flag);
- UpdateUnsignedLeb128(data, new_flag);
-}
-
void VdexFile::UnquickenDexFile(const DexFile& target_dex_file,
const uint8_t* source_dex_begin,
bool decompile_return_instruction) const {
@@ -312,14 +300,8 @@
quicken_data,
decompile_return_instruction);
}
- UpdateAccessFlags(const_cast<uint8_t*>(class_it.DataPointer()),
- class_it.GetMemberAccessFlags(),
- /*is_method*/ true);
- } else {
- UpdateAccessFlags(const_cast<uint8_t*>(class_it.DataPointer()),
- class_it.GetMemberAccessFlags(),
- /*is_method*/ false);
}
+ DexFile::UnHideAccessFlags(class_it);
}
}
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 3e9dfd1..66e578f 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3899,21 +3899,13 @@
}
ObjPtr<mirror::Class> klass = klass_type.GetClass();
const RegType& referrer = GetDeclaringClass();
- auto* cl = Runtime::Current()->GetClassLinker();
- auto pointer_size = cl->GetImagePointerSize();
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ PointerSize pointer_size = class_linker->GetImagePointerSize();
ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx, pointer_size);
if (res_method == nullptr) {
- // Try to find the method with the appropriate lookup for the klass type (interface or not).
- // If this lookup does not match `method_type`, errors shall be reported below.
- if (klass->IsInterface()) {
- res_method = klass->FindInterfaceMethod(dex_cache_.Get(), dex_method_idx, pointer_size);
- } else {
- res_method = klass->FindClassMethod(dex_cache_.Get(), dex_method_idx, pointer_size);
- }
- if (res_method != nullptr) {
- dex_cache_->SetResolvedMethod(dex_method_idx, res_method, pointer_size);
- }
+ res_method = class_linker->FindResolvedMethod(
+ klass, dex_cache_.Get(), class_loader_.Get(), dex_method_idx);
}
// Record result of method resolution attempt. The klass resolution has recorded whether
diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java
index ddfadf3..1a60185 100644
--- a/test/912-classes/src-art/art/Test912.java
+++ b/test/912-classes/src-art/art/Test912.java
@@ -398,6 +398,7 @@
public static double dummy = Math.random(); // So it can't be compile-time initialized.
}
+ @SuppressWarnings("RandomCast")
private static class TestForInitFail {
public static int dummy = ((int)Math.random())/0; // So it throws when initializing.
}
diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc
index dfefce2..9e65a99 100644
--- a/test/983-source-transform-verify/source_transform.cc
+++ b/test/983-source-transform-verify/source_transform.cc
@@ -14,30 +14,13 @@
* limitations under the License.
*/
-#include <inttypes.h>
+#include "source_transform.h"
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-#include <vector>
+#include "jni.h"
#include "android-base/stringprintf.h"
-#include "jni.h"
#include "jvmti.h"
-
-#include "base/macros.h"
-#include "bytecode_utils.h"
-#include "dex/code_item_accessors-inl.h"
-#include "dex/art_dex_file_loader.h"
-#include "dex/dex_file.h"
-#include "dex/dex_file_loader.h"
-#include "dex/dex_instruction.h"
-#include "jit/jit.h"
-#include "native_stack_dump.h"
-#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread-current-inl.h"
-#include "thread_list.h"
+#include "scoped_local_ref.h"
// Test infrastructure
#include "jvmti_helper.h"
@@ -48,9 +31,18 @@
constexpr bool kSkipInitialLoad = true;
+static void Println(JNIEnv* env, const char* msg) {
+ ScopedLocalRef<jclass> test_klass(env, env->FindClass("art/Test983"));
+ jmethodID println_method = env->GetStaticMethodID(test_klass.get(),
+ "doPrintln",
+ "(Ljava/lang/String;)V");
+ ScopedLocalRef<jstring> data(env, env->NewStringUTF(msg));
+ env->CallStaticVoidMethod(test_klass.get(), println_method, data.get());
+}
+
// The hook we are using.
void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
- JNIEnv* jni_env ATTRIBUTE_UNUSED,
+ JNIEnv* env,
jclass class_being_redefined,
jobject loader ATTRIBUTE_UNUSED,
const char* name,
@@ -60,78 +52,24 @@
jint* new_class_data_len ATTRIBUTE_UNUSED,
unsigned char** new_class_data ATTRIBUTE_UNUSED) {
if (kSkipInitialLoad && class_being_redefined == nullptr) {
- // Something got loaded concurrently. Just ignore it for now.
+ // Something got loaded concurrently. Just ignore it for now. To make sure the test is
+ // repeatable we only care about things that come from RetransformClasses.
return;
}
- std::cout << "Dex file hook for " << name << std::endl;
+ Println(env, android::base::StringPrintf("Dex file hook for %s", name).c_str());
if (IsJVM()) {
return;
}
- // Due to b/72402467 the class_data_len might just be an estimate.
- CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header));
- const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data);
- uint32_t header_file_size = header->file_size_;
- CHECK_LE(static_cast<jint>(header_file_size), class_data_len);
- class_data_len = static_cast<jint>(header_file_size);
-
- const ArtDexFileLoader dex_file_loader;
- std::string error;
- std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
- class_data_len,
- "fake_location.dex",
- /*location_checksum*/ 0,
- /*oat_dex_file*/ nullptr,
- /*verify*/ true,
- /*verify_checksum*/ true,
- &error));
- if (dex.get() == nullptr) {
- std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl;
- return;
- }
- for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
- const DexFile::ClassDef& def = dex->GetClassDef(i);
- const uint8_t* data_item = dex->GetClassData(def);
- if (data_item == nullptr) {
- continue;
- }
- for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
- if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
- continue;
- }
- for (const DexInstructionPcPair& pair :
- art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) {
- const Instruction& inst = pair.Inst();
- int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
- if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
- (inst.GetVerifyExtraFlags() & forbiden_flags) != 0) {
- std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
- << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
- << inst.DumpString(dex.get()) << std::endl;
- continue;
- }
- }
- }
- }
+ VerifyClassData(class_data_len, class_data);
}
// Get all capabilities except those related to retransformation.
-jint OnLoad(JavaVM* vm,
- char* options ATTRIBUTE_UNUSED,
- void* reserved ATTRIBUTE_UNUSED) {
- if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
- printf("Unable to get jvmti env!\n");
- return 1;
- }
- SetStandardCapabilities(jvmti_env);
+extern "C" JNIEXPORT void JNICALL Java_art_Test983_setupLoadHook(JNIEnv* env, jclass) {
jvmtiEventCallbacks cb;
memset(&cb, 0, sizeof(cb));
cb.ClassFileLoadHook = CheckDexFileHook;
- if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
- printf("Unable to set class file load hook cb!\n");
- return 1;
- }
- return 0;
+ JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)));
}
} // namespace Test983SourceTransformVerify
diff --git a/test/983-source-transform-verify/source_transform.h b/test/983-source-transform-verify/source_transform.h
index db9415a..2206498 100644
--- a/test/983-source-transform-verify/source_transform.h
+++ b/test/983-source-transform-verify/source_transform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -22,7 +22,7 @@
namespace art {
namespace Test983SourceTransformVerify {
-jint OnLoad(JavaVM* vm, char* options, void* reserved);
+void VerifyClassData(jint class_data_len, const unsigned char* class_data);
} // namespace Test983SourceTransformVerify
} // namespace art
diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc
new file mode 100644
index 0000000..5353370
--- /dev/null
+++ b/test/983-source-transform-verify/source_transform_art.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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 "source_transform.h"
+
+#include <inttypes.h>
+
+#include <memory>
+
+#include <android-base/logging.h>
+
+#include "dex/code_item_accessors-inl.h"
+#include "dex/art_dex_file_loader.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_loader.h"
+#include "dex/dex_instruction.h"
+
+namespace art {
+namespace Test983SourceTransformVerify {
+
+// The hook we are using.
+void VerifyClassData(jint class_data_len, const unsigned char* class_data) {
+ // Due to b/72402467 the class_data_len might just be an estimate.
+ CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header));
+ const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data);
+ uint32_t header_file_size = header->file_size_;
+ CHECK_LE(static_cast<jint>(header_file_size), class_data_len);
+ class_data_len = static_cast<jint>(header_file_size);
+
+ const ArtDexFileLoader dex_file_loader;
+ std::string error;
+ std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
+ class_data_len,
+ "fake_location.dex",
+ /*location_checksum*/ 0,
+ /*oat_dex_file*/ nullptr,
+ /*verify*/ true,
+ /*verify_checksum*/ true,
+ &error));
+ CHECK(dex.get() != nullptr) << "Failed to verify dex: " << error;
+ for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
+ const DexFile::ClassDef& def = dex->GetClassDef(i);
+ const uint8_t* data_item = dex->GetClassData(def);
+ if (data_item == nullptr) {
+ continue;
+ }
+ for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
+ if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
+ continue;
+ }
+ for (const DexInstructionPcPair& pair :
+ art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) {
+ const Instruction& inst = pair.Inst();
+ int forbidden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
+ if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
+ (inst.GetVerifyExtraFlags() & forbidden_flags) != 0) {
+ LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
+ << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
+ << inst.DumpString(dex.get()) << std::endl;
+ }
+ }
+ }
+ }
+}
+
+} // namespace Test983SourceTransformVerify
+} // namespace art
diff --git a/test/983-source-transform-verify/source_transform_slicer.cc b/test/983-source-transform-verify/source_transform_slicer.cc
new file mode 100644
index 0000000..abf32e7
--- /dev/null
+++ b/test/983-source-transform-verify/source_transform_slicer.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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 "source_transform.h"
+
+#pragma clang diagnostic push
+// slicer defines its own CHECK. b/65422458
+#pragma push_macro("CHECK")
+#undef CHECK
+
+// Slicer's headers have code that triggers these warnings. b/65298177
+#pragma clang diagnostic ignored "-Wsign-compare"
+#include "reader.h"
+
+#pragma pop_macro("CHECK")
+#pragma clang diagnostic pop
+
+namespace art {
+namespace Test983SourceTransformVerify {
+
+// The hook we are using.
+void VerifyClassData(jint class_data_len, const unsigned char* class_data) {
+ dex::Reader reader(class_data, class_data_len);
+ reader.CreateFullIr(); // This will verify all bytecode.
+}
+
+} // namespace Test983SourceTransformVerify
+} // namespace art
diff --git a/test/983-source-transform-verify/src/art/Test983.java b/test/983-source-transform-verify/src/art/Test983.java
index faae96a..7dc47ab 100644
--- a/test/983-source-transform-verify/src/art/Test983.java
+++ b/test/983-source-transform-verify/src/art/Test983.java
@@ -27,7 +27,15 @@
doTest();
}
+ private native static void setupLoadHook();
+
+ /* called from JNI */
+ public static void doPrintln(String str) {
+ System.out.println(str);
+ }
+
public static void doTest() {
+ setupLoadHook();
Redefinition.enableCommonRetransformation(true);
Redefinition.doCommonClassRetransformation(Transform.class);
Redefinition.doCommonClassRetransformation(Object.class);
diff --git a/test/Android.bp b/test/Android.bp
index 5f39ffe..9d44e09 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -62,7 +62,7 @@
"libvixld-arm",
"libvixld-arm64",
"libart-gtest",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libicuuc",
@@ -114,7 +114,7 @@
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
],
static_libs: [
"libgtest",
@@ -151,7 +151,7 @@
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libbacktrace",
],
@@ -238,6 +238,7 @@
"931-agent-thread/agent_thread.cc",
"933-misc-events/misc_events.cc",
"945-obsolete-native/obsolete_native.cc",
+ "983-source-transform-verify/source_transform.cc",
"984-obsolete-invoke/obsolete_invoke.cc",
"986-native-method-bind/native_bind.cc",
"987-agent-bind/agent_bind.cc",
@@ -288,20 +289,22 @@
"909-attach-agent/attach.cc",
"912-classes/classes_art.cc",
"936-search-onload/search_onload.cc",
- "983-source-transform-verify/source_transform.cc",
+ "983-source-transform-verify/source_transform_art.cc",
"1940-ddms-ext/ddm_ext.cc",
"1944-sudden-exit/sudden_exit.cc",
],
shared_libs: [
"libbase",
- "libdexfile",
],
}
art_cc_test_library {
name: "libtiagent",
defaults: ["libtiagent-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -310,24 +313,32 @@
"art_debug_defaults",
"libtiagent-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
-art_cc_test_library {
+cc_library_static {
name: "libctstiagent",
defaults: ["libtiagent-base-defaults"],
+ host_supported: false,
+ srcs: [
+ "983-source-transform-verify/source_transform_slicer.cc",
+ ],
whole_static_libs: [
- "libdexfile",
- "libz",
- "libziparchive",
+ "slicer",
+ "libz", // for slicer (using adler32).
],
static_libs: [
"libbase",
- "libcutils",
- "libutils",
],
- shared_libs: [
- "liblog",
+ header_libs: [
+ // This is needed to resolve the base/ header file in libdexfile. Unfortunately there are
+ // many problems with how we export headers that are making doing this the 'right' way
+ // difficult.
+ // TODO: move those headers to art/ rather than under runtime.
+ "libart_runtime_headers",
],
export_include_dirs: ["ti-agent"],
}
@@ -413,7 +424,6 @@
"708-jit-cache-churn/jit.cc",
],
shared_libs: [
- "libdexfile",
"libbacktrace",
"libbase",
"libnativehelper",
@@ -423,7 +433,10 @@
art_cc_test_library {
name: "libarttest",
defaults: ["libarttest-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -432,7 +445,10 @@
"art_debug_defaults",
"libarttest-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
art_cc_test_library {
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index bb6ace1..b8427f4 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -850,7 +850,7 @@
fi
# System libraries needed by libarttestd.so
- PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libbase.so:libnativehelper.so
+ PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libdexfiled.so:libbase.so:libnativehelper.so
# Create a script with the command. The command can get longer than the longest
# allowed adb command and there is no way to get the exit status from a adb shell
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 9a7352e..bfd165d 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -28,7 +28,6 @@
#include "901-hello-ti-agent/basics.h"
#include "909-attach-agent/attach.h"
#include "936-search-onload/search_onload.h"
-#include "983-source-transform-verify/source_transform.h"
#include "1919-vminit-thread-start-timing/vminit.h"
namespace art {
@@ -83,7 +82,6 @@
{ "939-hello-transformation-bcp", common_redefine::OnLoad, nullptr },
{ "941-recursive-obsolete-jit", common_redefine::OnLoad, nullptr },
{ "943-private-recursive-jit", common_redefine::OnLoad, nullptr },
- { "983-source-transform-verify", Test983SourceTransformVerify::OnLoad, nullptr },
{ "1919-vminit-thread-start-timing", Test1919VMInitThreadStart::OnLoad, nullptr },
};
diff --git a/tools/amm/AmmTest/AndroidManifest.xml b/tools/amm/AmmTest/AndroidManifest.xml
new file mode 100644
index 0000000..16529bc
--- /dev/null
+++ b/tools/amm/AmmTest/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.amm.test">
+
+ <application
+ android:label="AmmTest"
+ android:debuggable="true">
+
+ <activity android:name="com.android.amm.test.MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tools/amm/AmmTest/aahat.png b/tools/amm/AmmTest/aahat.png
new file mode 100644
index 0000000..01b92f4
--- /dev/null
+++ b/tools/amm/AmmTest/aahat.png
Binary files differ
diff --git a/tools/amm/AmmTest/jni/ammtest.c b/tools/amm/AmmTest/jni/ammtest.c
new file mode 100644
index 0000000..9d48475
--- /dev/null
+++ b/tools/amm/AmmTest/jni/ammtest.c
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+
+// A large uninitialized array gets put in the .bss section:
+char uninit[3 * 4096];
+
+// A large initialized array gets put in the .data section:
+char init[2 * 4096] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789..";
+
+// A large constant initialized array gets put in the .rodata section:
+const char cinit[1 * 4096] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789..";
+
+JNIEXPORT jint JNICALL
+Java_com_android_amm_test_SoCodeUse_nGetANumber(JNIEnv* env, jclass cls) {
+ (void) env;
+ (void) cls;
+
+ uninit[4096] = init[123] + cinit[123];
+ return 42;
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java b/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java
new file mode 100644
index 0000000..d8eba2e
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package com.android.amm.test;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+/**
+ * Exercise loading of a bitmap.
+ */
+class BitmapUse {
+
+ private Bitmap mBitmap;
+
+ public BitmapUse() {
+ ClassLoader loader = BitmapUse.class.getClassLoader();
+ mBitmap = BitmapFactory.decodeStream(loader.getResourceAsStream("aahat.png"), null, null);
+ }
+}
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java
new file mode 100644
index 0000000..4577f4b
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package com.android.amm.test;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+
+public class MainActivity extends Activity {
+
+ private BitmapUse mBitmapUse;
+ private SoCodeUse mSoCodeUse;
+ private TextureViewUse mTextureViewUse;
+ private SurfaceViewUse mSurfaceViewUse;
+ private ThreadedRendererUse mThreadedRendererUse;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mBitmapUse = new BitmapUse();
+ mSoCodeUse = new SoCodeUse();
+
+ LinearLayout ll = new LinearLayout(this);
+ mTextureViewUse = new TextureViewUse(this, ll, 200, 500);
+ mSurfaceViewUse = new SurfaceViewUse(this, ll, 240, 250);
+ setContentView(ll);
+
+ mThreadedRendererUse = new ThreadedRendererUse(this, 122, 152);
+ }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java b/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java
new file mode 100644
index 0000000..9636c0f
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package com.android.amm.test;
+
+class SoCodeUse {
+ private int value;
+
+ public SoCodeUse() {
+ // TODO: Figure out how to cause the native library to be unloaded when
+ // the SoCodeUse instance goes away?
+ System.loadLibrary("ammtestjni");
+ value = nGetANumber();
+ }
+
+ private static native int nGetANumber();
+}
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java
new file mode 100644
index 0000000..0c17c77
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+class SurfaceViewUse {
+
+ private SurfaceView mSurfaceView;
+
+ /**
+ * Constructs a SurfaceView object with given dimensions.
+ * The surface view is added to the given ViewGroup object, which should be
+ * included in the main display.
+ */
+ public SurfaceViewUse(Context context, ViewGroup vg, int width, int height) {
+ mSurfaceView = new SurfaceView(context);
+ vg.addView(mSurfaceView, width, height);
+ mSurfaceView.post(new CycleRunnable());
+ }
+
+ // To force as many graphics buffers as will ever be used to actually be
+ // used, we cycle the color of the surface view a handful of times right
+ // when things start up.
+ private class CycleRunnable implements Runnable {
+ private int mCycles = 0;
+ private int mRed = 255;
+ private int mGreen = 0;
+ private int mBlue = 255;
+
+ public void run() {
+ if (mCycles < 10) {
+ mCycles++;
+ updateSurfaceView();
+ mSurfaceView.post(this);
+ }
+ }
+
+ private void updateSurfaceView() {
+ SurfaceHolder holder = mSurfaceView.getHolder();
+ Canvas canvas = holder.lockHardwareCanvas();
+ if (canvas != null) {
+ canvas.drawRGB(mRed, mGreen, mBlue);
+ int tmp = mRed;
+ holder.unlockCanvasAndPost(canvas);
+ mRed = mGreen;
+ mGreen = mBlue;
+ mBlue = tmp;
+ }
+ }
+ }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java
new file mode 100644
index 0000000..51ffcd2
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.TextureView;
+import android.view.ViewGroup;
+
+class TextureViewUse {
+
+ private TextureView mTextureView;
+
+ /**
+ * Constructs a TextureView object with given dimensions.
+ * The texture view is added to the given ViewGroup object, which should be
+ * included in the main display.
+ */
+ public TextureViewUse(Context context, ViewGroup vg, int width, int height) {
+ mTextureView = new TextureView(context);
+ vg.addView(mTextureView, width, height);
+ mTextureView.post(new CycleRunnable());
+ }
+
+ // To force as many graphics buffers as will ever be used to actually be
+ // used, we cycle the color of the texture view a handful of times right
+ // when things start up.
+ private class CycleRunnable implements Runnable {
+ private int mCycles = 0;
+ private int mRed = 255;
+ private int mGreen = 255;
+ private int mBlue = 0;
+
+ public void run() {
+ if (mCycles < 10) {
+ mCycles++;
+ updateTextureView();
+ mTextureView.post(this);
+ }
+ }
+
+ private void updateTextureView() {
+ Canvas canvas = mTextureView.lockCanvas();
+ if (canvas != null) {
+ canvas.drawRGB(mRed, mGreen, mBlue);
+ int tmp = mRed;
+ mTextureView.unlockCanvasAndPost(canvas);
+ mRed = mGreen;
+ mGreen = mBlue;
+ mBlue = tmp;
+ }
+ }
+ }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java
new file mode 100644
index 0000000..9c25612
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+class ThreadedRendererUse {
+
+ private TextView mTextView;
+
+ /**
+ * Cause a threaded renderer EGL allocation to be used, with given
+ * dimensions.
+ */
+ public ThreadedRendererUse(Context context, int width, int height) {
+ mTextView = new TextView(context);
+ mTextView.setText("TRU");
+ mTextView.setBackgroundColor(0xffff0000);
+
+ // Adding a view to the WindowManager (as opposed to the app's root view
+ // hierarchy) causes a ThreadedRenderer and EGL allocations under the cover.
+ // We use a TextView here to trigger the use case, but we could use any
+ // other kind of view as well.
+ WindowManager wm = context.getSystemService(WindowManager.class);
+ WindowManager.LayoutParams layout = new WindowManager.LayoutParams();
+ layout.width = width;
+ layout.height = height;
+ wm.addView(mTextView, layout);
+
+ mTextView.post(new CycleRunnable());
+ }
+
+ // To force as many graphics buffers as will ever be used to actually be
+ // used, we cycle the text of the text view a handful of times right
+ // when things start up.
+ private class CycleRunnable implements Runnable {
+ private int mCycles = 0;
+
+ public void run() {
+ if (mCycles < 10) {
+ mCycles++;
+ mTextView.setText("TRU " + mCycles);
+ mTextView.post(this);
+ }
+ }
+ }
+}
+
diff --git a/tools/amm/Android.mk b/tools/amm/Android.mk
new file mode 100644
index 0000000..47030c5
--- /dev/null
+++ b/tools/amm/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# --- ammtestjni.so -------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libammtestjni
+LOCAL_SRC_FILES := $(call all-c-files-under, AmmTest/jni)
+LOCAL_SDK_VERSION := current
+include $(BUILD_SHARED_LIBRARY)
+
+# --- AmmTest.apk --------------
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := AmmTest
+LOCAL_MODULE_TAGS := samples tests
+LOCAL_SRC_FILES := $(call all-java-files-under, AmmTest/src)
+LOCAL_SDK_VERSION := current
+LOCAL_JNI_SHARED_LIBRARIES := libammtestjni
+LOCAL_JAVA_RESOURCE_FILES := $(LOCAL_PATH)/AmmTest/aahat.png
+LOCAL_MANIFEST_FILE := AmmTest/AndroidManifest.xml
+include $(BUILD_PACKAGE)
+
diff --git a/tools/amm/README.md b/tools/amm/README.md
new file mode 100644
index 0000000..17f94a8
--- /dev/null
+++ b/tools/amm/README.md
@@ -0,0 +1,16 @@
+# Actionable Memory Metric
+
+The goal of the actionable memory metric (AMM) is to provide a view of an
+application's memory use that application developers can track, understand,
+and control. AMM can be thought of as a Java heap dump augmented with models
+for non-Java allocations that app developers have some control of.
+
+There are two components of the actionable memory metric:
+1. The value of the metric.
+2. An actionable breakdown of the value of the metric.
+
+The metric is made up of a collection of separate models for different
+categories of memory use. Each model contributes to the value and actionable
+breakdown of the overall metric.
+
+See models/ for a list of models proposed for the actionable memory metric.
diff --git a/tools/amm/models/Bitmap.md b/tools/amm/models/Bitmap.md
new file mode 100644
index 0000000..49a0b9d
--- /dev/null
+++ b/tools/amm/models/Bitmap.md
@@ -0,0 +1,15 @@
+# Bitmap Model
+
+The value of the Bitmap model is the sum of bytes used for native pixel data
+of instances of `android.graphics.Bitmap`. It is calculated by summing for
+each instance `x` of `android.graphics.Bitmap`:
+
+ x.getAllocationByteCount()
+
+The actionable breakdown of the Bitmap model is a breakdown by
+`android.graphics.Bitmap` instance, including width, height, and ideally a
+thumbnail image of each bitmap.
+
+For example, an 800 x 600 bitmap instance using the `ARGB_8888` pixel format
+with native pixel data will be shown as an 800 x 600 bitmap instance taking up
+1875 kB.
diff --git a/tools/amm/models/DexCode.md b/tools/amm/models/DexCode.md
new file mode 100644
index 0000000..a907280
--- /dev/null
+++ b/tools/amm/models/DexCode.md
@@ -0,0 +1,17 @@
+# Dex Code Model
+
+The value of the Dex Code model is the sum of the original uncompressed file
+sizes of all loaded dex files. It is calculated using the best approximation
+of the dex file size available to us on device. On Android O, for example,
+this can be approximated as the virtual size of the corresponding memory
+mapped `.vdex` file read from `/proc/self/maps`. Different Android platform
+versions and scenarios may require different approximations.
+
+The actionable breakdown of the dex code model is a breakdown by
+`dalvik.system.DexFile` instance. Further breakdown of individual dex files
+can be achieved using tools such as dexdump.
+
+For example, for an application `AmmTest.apk` that has a single `classes.dex` file
+that is 500 KB uncompressed, the `DexFile` instance for
+`/data/app/com.android.amm.test-_uHI4CJWpeoztbjN6Tr-Nw==/base.apk` is shown as
+Taking up 500 KB (or the best available approximation thereof).
diff --git a/tools/amm/models/Graphics.md b/tools/amm/models/Graphics.md
new file mode 100644
index 0000000..b327961
--- /dev/null
+++ b/tools/amm/models/Graphics.md
@@ -0,0 +1,22 @@
+# Graphics Models
+
+There are three components to the graphics model, each modeling EGL memory
+use:
+1. For each `android.view.TextureView` instance:
+ 2 * (4 * width * height)
+
+2. For each `android.view.Surface$HwuiContext` instance:
+ 3 * (4 * width * height)
+
+3. For each initialized `android.view.ThreadedRenderer`:
+ 3 * (4 * width * height)
+
+Note: 4 is the number of bytes per pixel. 2 or 3 is the maximum number of
+buffers that may be allocated.
+
+The actionable breakdown is the breakdown by `TextureView`,
+`Surface$HwuiContext` and `ThreadedRenderer` instance, with further details
+about the width and height associated with each instance.
+
+For example, an application with a single 64x256 `TextureView` instance will
+be shown as taking up 128 KB.
diff --git a/tools/amm/models/JavaHeap.md b/tools/amm/models/JavaHeap.md
new file mode 100644
index 0000000..c34c186
--- /dev/null
+++ b/tools/amm/models/JavaHeap.md
@@ -0,0 +1,8 @@
+# Java Heap Model
+
+The value of the Java heap model is the sum of bytes of Java objects allocated
+on the Java heap. It can be calculated using:
+
+ Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
+
+A Java heap dump is used for an actionable breakdown of the Java heap.
diff --git a/tools/amm/models/SoCode.md b/tools/amm/models/SoCode.md
new file mode 100644
index 0000000..5d3184e
--- /dev/null
+++ b/tools/amm/models/SoCode.md
@@ -0,0 +1,17 @@
+# Shared Native Code Model
+
+The value of the Shared Native Code model is the sum of the virtual memory
+sizes of all loaded `.so` files. It is calculated by reading `/proc/self/maps`.
+
+The actionable breakdown of the shared native code model is a breakdown by
+library name. Unfortunately, due to technical limitations, this does not
+include information about what caused a library to be loaded, whether the
+library was loaded by the app or the platform, the library dependency graph,
+or what is causing a library to remain loaded. Individual `.so` files can be
+further broken down using tools such as `readelf`.
+
+For example, for an application `AmmTest.apk` that includes `libammtestjni.so` as a
+native library that loads 36 KB worth of memory regions, `BaseClassLoader` will
+be shown with library
+`/data/app/com.android.amm.test-_uHI4CJWpeoztbjN6Tr-Nw==/lib/arm64/libammtestjni.so`
+taking up 36 KB.
diff --git a/tools/hiddenapi/Android.bp b/tools/hiddenapi/Android.bp
index f9824f1..af87d31 100644
--- a/tools/hiddenapi/Android.bp
+++ b/tools/hiddenapi/Android.bp
@@ -30,7 +30,6 @@
},
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -40,6 +39,7 @@
defaults: ["hiddenapi-defaults"],
shared_libs: [
"libart",
+ "libdexfile",
],
}
@@ -51,6 +51,7 @@
],
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/tools/public.libraries.buildbot.txt b/tools/public.libraries.buildbot.txt
index 734fd1e..de636a8 100644
--- a/tools/public.libraries.buildbot.txt
+++ b/tools/public.libraries.buildbot.txt
@@ -1,6 +1,7 @@
libart.so
libartd.so
libdexfile.so
+libdexfiled.so
libbacktrace.so
libc.so
libc++.so