Merge "Move common-compat lib tests near the code"
diff --git a/libraries/compatibility-common-util/Android.bp b/libraries/compatibility-common-util/Android.bp
index bc40510..5b58337 100644
--- a/libraries/compatibility-common-util/Android.bp
+++ b/libraries/compatibility-common-util/Android.bp
@@ -33,6 +33,7 @@
     name: "compatibility-common-util-lib",
     visibility: [
         "//test/suite_harness/common/util",
+        "//platform_testing/libraries/compatibility-common-util/tests",
     ],
     srcs: ["src/**/*.java"],
     host_supported: true,
diff --git a/libraries/compatibility-common-util/tests/Android.bp b/libraries/compatibility-common-util/tests/Android.bp
new file mode 100644
index 0000000..5f58654
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2015 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_test_host {
+    name: "compatibility-common-util-tests",
+    // Restrict visibility to only those targets that need to access it.
+    visibility: ["//visibility:private"],
+    defaults: ["cts_error_prone_rules"],
+
+    srcs: ["src/**/*.java"],
+    test_options: {
+        unit_test: true,
+    },
+
+    static_libs: [
+        "compatibility-common-util-lib",
+        "junit",
+        "kxml2-2.3.0",
+        "tradefed",
+    ],
+
+    // Holds golden sample files in assets for validation
+    java_resource_dirs: ["assets/"],
+}
diff --git a/libraries/compatibility-common-util/tests/assets/arm32_libdl.so b/libraries/compatibility-common-util/tests/assets/arm32_libdl.so
new file mode 100644
index 0000000..979ab20
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/arm32_libdl.so
Binary files differ
diff --git a/libraries/compatibility-common-util/tests/assets/arm32_libdl.txt b/libraries/compatibility-common-util/tests/assets/arm32_libdl.txt
new file mode 100644
index 0000000..6a4ccdc
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/arm32_libdl.txt
@@ -0,0 +1,271 @@
+ELF Header:
+  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
+  Class:                             ELF32
+  Data:                              2's complement, little endian
+  Version:                           1 (current)
+  OS/ABI:                            UNIX - System V
+  ABI Version:                       0
+  Type:                              DYN (Shared object file)
+  Machine:                           ARM
+  Version:                           0x1
+  Entry point address:               0x0
+  Start of program headers:          52 (bytes into file)
+  Start of section headers:          9304 (bytes into file)
+  Flags:                             0x5000200, Version5 EABI, soft-float ABI
+  Size of this header:               52 (bytes)
+  Size of program headers:           32 (bytes)
+  Number of program headers:         8
+  Size of section headers:           40 (bytes)
+  Number of section headers:         19
+  Section header string table index: 18
+
+Section Headers:
+  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
+  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
+  [ 1] .note.gnu.build-i NOTE            00000134 000134 000020 00   A  0   0  4
+  [ 2] .dynsym           DYNSYM          00000154 000154 0002e0 10   A  3   1  4
+  [ 3] .dynstr           STRTAB          00000434 000434 00041e 00   A  0   0  1
+  [ 4] .gnu.hash         GNU_HASH        00000854 000854 0000dc 04   A  2   0  4
+  [ 5] .hash             HASH            00000930 000930 000154 04   A  2   0  4
+  [ 6] .gnu.version      VERSYM          00000a84 000a84 00005c 02   A  2   0  2
+  [ 7] .gnu.version_d    VERDEF          00000ae0 000ae0 0000a4 00   A  3   5  4
+  [ 8] .rel.plt          REL             00000b84 000b84 000098 08  AI  2  13  4
+  [ 9] .plt              PROGBITS        00000c1c 000c1c 0000f8 00  AX  0   0  4
+  [10] .text             PROGBITS        00000d14 000d14 0002bc 00  AX  0   0  4
+  [11] .ARM.exidx        ARM_EXIDX       00000fd0 000fd0 000030 08  AL 10   0  4
+  [12] .dynamic          DYNAMIC         00001ef0 001ef0 0000b8 08  WA  3   0  4
+  [13] .got              PROGBITS        00001fa8 001fa8 000058 00  WA  0   0  4
+  [14] .bss              NOBITS          00002000 002000 001000 00  WA  0   0 4096
+  [15] .note.gnu.gold-ve NOTE            00000000 002000 00001c 00      0   0  4
+  [16] .ARM.attributes   ARM_ATTRIBUTES  00000000 00201c 00004a 00      0   0  1
+  [17] .gnu_debugdata    PROGBITS        00000000 002066 000338 00      0   0  1
+  [18] .shstrtab         STRTAB          00000000 00239e 0000b7 00      0   0  1
+Key to Flags:
+  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
+  L (link order), O (extra OS processing required), G (group), T (TLS),
+  C (compressed), x (unknown), o (OS specific), E (exclude),
+  y (purecode), p (processor specific)
+
+There are no section groups in this file.
+
+Program Headers:
+  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
+  PHDR           0x000034 0x00000034 0x00000034 0x00100 0x00100 R   0x4
+  LOAD           0x000000 0x00000000 0x00000000 0x01000 0x01000 R E 0x1000
+  LOAD           0x001ef0 0x00001ef0 0x00001ef0 0x00110 0x01110 RW  0x1000
+  DYNAMIC        0x001ef0 0x00001ef0 0x00001ef0 0x000b8 0x000b8 RW  0x4
+  NOTE           0x000134 0x00000134 0x00000134 0x00020 0x00020 R   0x4
+  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
+  EXIDX          0x000fd0 0x00000fd0 0x00000fd0 0x00030 0x00030 R   0x4
+  GNU_RELRO      0x001ef0 0x00001ef0 0x00001ef0 0x00110 0x00110 RW  0x4
+
+ Section to Segment mapping:
+  Segment Sections...
+   00     
+   01     .note.gnu.build-id .dynsym .dynstr .gnu.hash .hash .gnu.version .gnu.version_d .rel.plt .plt .text .ARM.exidx 
+   02     .dynamic .got .bss 
+   03     .dynamic 
+   04     .note.gnu.build-id 
+   05     
+   06     .ARM.exidx 
+   07     .dynamic .got 
+
+Dynamic section at offset 0x1ef0 contains 18 entries:
+  Tag        Type                         Name/Value
+ 0x00000003 (PLTGOT)                     0x1fa8
+ 0x00000002 (PLTRELSZ)                   152 (bytes)
+ 0x00000017 (JMPREL)                     0xb84
+ 0x00000014 (PLTREL)                     REL
+ 0x00000006 (SYMTAB)                     0x154
+ 0x0000000b (SYMENT)                     16 (bytes)
+ 0x00000005 (STRTAB)                     0x434
+ 0x0000000a (STRSZ)                      1054 (bytes)
+ 0x6ffffef5 (GNU_HASH)                   0x854
+ 0x00000004 (HASH)                       0x930
+ 0x00000001 (NEEDED)                     Shared library: [ld-android.so]
+ 0x0000000e (SONAME)                     Library soname: [libdl.so]
+ 0x0000001e (FLAGS)                      BIND_NOW
+ 0x6ffffffb (FLAGS_1)                    Flags: NOW
+ 0x6ffffff0 (VERSYM)                     0xa84
+ 0x6ffffffc (VERDEF)                     0xae0
+ 0x6ffffffd (VERDEFNUM)                  5
+ 0x00000000 (NULL)                       0x0
+
+Relocation section '.rel.plt' at offset 0xb84 contains 19 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+00001fb4  00001016 R_ARM_JUMP_SLOT   00000000   __loader_dlopen
+00001fb8  00000f16 R_ARM_JUMP_SLOT   00000000   __loader_dlerror
+00001fbc  00001116 R_ARM_JUMP_SLOT   00000000   __loader_dlsym
+00001fc0  00001216 R_ARM_JUMP_SLOT   00000000   __loader_dlvsym
+00001fc4  00000d16 R_ARM_JUMP_SLOT   00000000   __loader_dladdr
+00001fc8  00000e16 R_ARM_JUMP_SLOT   00000000   __loader_dlclose
+00001fcc  00000c16 R_ARM_JUMP_SLOT   00000000   __loader_dl_unwind_fin
+00001fd0  00000b16 R_ARM_JUMP_SLOT   00000000   __loader_dl_iterate_ph
+00001fd4  00000416 R_ARM_JUMP_SLOT   00000000   __loader_android_get_L
+00001fd8  00000a16 R_ARM_JUMP_SLOT   00000000   __loader_android_updat
+00001fdc  00000216 R_ARM_JUMP_SLOT   00000000   __loader_android_dlope
+00001fe0  00000916 R_ARM_JUMP_SLOT   00000000   __loader_android_set_a
+00001fe4  00000516 R_ARM_JUMP_SLOT   00000000   __loader_android_get_a
+00001fe8  00000716 R_ARM_JUMP_SLOT   00000000   __loader_android_init_
+00001fec  00000116 R_ARM_JUMP_SLOT   00000000   __loader_android_creat
+00001ff0  00000816 R_ARM_JUMP_SLOT   00000000   __loader_android_link_
+00001ff4  00000316 R_ARM_JUMP_SLOT   00000000   __loader_android_dlwar
+00001ff8  00000616 R_ARM_JUMP_SLOT   00000000   __loader_android_get_e
+00001ffc  00001316 R_ARM_JUMP_SLOT   00000000   __loader_cfi_fail
+
+Unwind section '.ARM.exidx' at offset 0xfd0 contains 6 entries:
+
+0xd14: 0x808408b0
+  Compact model index: 0
+  0x84 0x08 pop {r7, r14}
+  0xb0      finish
+
+0xd8c: 0x80058408
+  Compact model index: 0
+  0x05      vsp = vsp + 24
+  0x84 0x08 pop {r7, r14}
+
+0xdac: 0x808408b0
+  Compact model index: 0
+  0x84 0x08 pop {r7, r14}
+  0xb0      finish
+
+0xdc4: 0x80b0b0b0
+  Compact model index: 0
+  0xb0      finish
+  0xb0      finish
+  0xb0      finish
+
+0xdec: 0x8001a8b0
+  Compact model index: 0
+  0x01      vsp = vsp + 8
+  0xa8      pop {r4, r14}
+  0xb0      finish
+
+0xfd0: 0x1 [cantunwind]
+
+
+Symbol table '.dynsym' contains 46 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_create_n
+     2: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_dlopen_e
+     3: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_dlwarnin
+     4: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_get_LD_L
+     5: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_get_appl
+     6: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_get_expo
+     7: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_init_ano
+     8: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_link_nam
+     9: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_set_appl
+    10: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_update_L
+    11: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dl_iterate_phdr
+    12: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dl_unwind_find_e
+    13: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dladdr
+    14: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlclose
+    15: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlerror
+    16: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlopen
+    17: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlsym
+    18: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlvsym
+    19: 00000000     0 FUNC    WEAK   DEFAULT  UND __loader_cfi_fail
+    20: 00000d6b    10 FUNC    WEAK   DEFAULT   10 android_dlopen_ext@@LIBC
+    21: 00000e45    92 FUNC    GLOBAL DEFAULT   10 __cfi_slowpath_diag@@LIBC_OMR1
+    22: 00000d85     8 FUNC    WEAK   DEFAULT   10 android_init_anonymous_na@@LIBC_PLATFORM
+    23: 00000d63     8 FUNC    WEAK   DEFAULT   10 android_update_LD_LIBRARY@@LIBC_PLATFORM
+    24: 00000dbd     8 FUNC    WEAK   DEFAULT   10 android_get_exported_name@@LIBC_PLATFORM
+    25: 00000d75     8 FUNC    WEAK   DEFAULT   10 android_set_application_t@@LIBC_PLATFORM
+    26: 00000d27    10 FUNC    WEAK   DEFAULT   10 dlsym@@LIBC
+    27: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC_N
+    28: 00000dad     8 FUNC    WEAK   DEFAULT   10 android_link_namespaces@@LIBC_PLATFORM
+    29: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC
+    30: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC_PLATFORM
+    31: 00000d1f     8 FUNC    WEAK   DEFAULT   10 dlerror@@LIBC
+    32: 00000d15    10 FUNC    WEAK   DEFAULT   10 dlopen@@LIBC
+    33: 00000dd9    20 FUNC    GLOBAL DEFAULT   10 __cfi_shadow_size@@LIBC_OMR1
+    34: 00000d43     8 FUNC    WEAK   DEFAULT   10 dlclose@@LIBC
+    35: 00000db5     8 FUNC    WEAK   DEFAULT   10 android_dlwarning@@LIBC_PLATFORM
+    36: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC_OMR1
+    37: 00000d7d     8 FUNC    WEAK   DEFAULT   10 android_get_application_t@@LIBC_PLATFORM
+    38: 00000ded    88 FUNC    GLOBAL DEFAULT   10 __cfi_slowpath@@LIBC_OMR1
+    39: 00000d4b     8 FUNC    WEAK   DEFAULT   10 dl_unwind_find_exidx@@LIBC
+    40: 00000d8d    32 FUNC    WEAK   DEFAULT   10 android_create_namespace@@LIBC_PLATFORM
+    41: 00000d53     8 FUNC    WEAK   DEFAULT   10 dl_iterate_phdr@@LIBC
+    42: 00000d3b     8 FUNC    WEAK   DEFAULT   10 dladdr@@LIBC
+    43: 00000d5b     8 FUNC    WEAK   DEFAULT   10 android_get_LD_LIBRARY_PA@@LIBC_PLATFORM
+    44: 00000d31    10 FUNC    WEAK   DEFAULT   10 dlvsym@@LIBC_N
+    45: 00000dc9    16 FUNC    GLOBAL DEFAULT   10 __cfi_init@@LIBC_PLATFORM
+
+Histogram for bucket list length (total of 37 buckets):
+ Length  Number     % of total  Coverage
+      0  10         ( 27.0%)
+      1  14         ( 37.8%)     31.1%
+      2  10         ( 27.0%)     75.6%
+      3  2          (  5.4%)     88.9%
+      4  0          (  0.0%)     88.9%
+      5  1          (  2.7%)    100.0%
+
+Histogram for `.gnu.hash' bucket list length (total of 17 buckets):
+ Length  Number     % of total  Coverage
+      0  0          (  0.0%)
+      1  9          ( 52.9%)     34.6%
+      2  7          ( 41.2%)     88.5%
+      3  1          (  5.9%)    100.0%
+
+Version symbols section '.gnu.version' contains 46 entries:
+ Addr: 0000000000000a84  Offset: 0x000a84  Link: 2 (.dynsym)
+  000:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  004:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  008:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  00c:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  010:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  014:   2 (LIBC)          4 (LIBC_OMR1)     5 (LIBC_PLATFORM)   5 (LIBC_PLATFORM)
+  018:   5 (LIBC_PLATFORM)   5 (LIBC_PLATFORM)   2 (LIBC)          3 (LIBC_N)     
+  01c:   5 (LIBC_PLATFORM)   2 (LIBC)          5 (LIBC_PLATFORM)   2 (LIBC)       
+  020:   2 (LIBC)          4 (LIBC_OMR1)     2 (LIBC)          5 (LIBC_PLATFORM)
+  024:   4 (LIBC_OMR1)     5 (LIBC_PLATFORM)   4 (LIBC_OMR1)     2 (LIBC)       
+  028:   5 (LIBC_PLATFORM)   2 (LIBC)          2 (LIBC)          5 (LIBC_PLATFORM)
+  02c:   3 (LIBC_N)        5 (LIBC_PLATFORM)
+
+Version definition section '.gnu.version_d' contains 5 entries:
+  Addr: 0x0000000000000ae0  Offset: 0x000ae0  Link: 3 (.dynstr)
+  000000: Rev: 1  Flags: BASE  Index: 1  Cnt: 1  Name: libdl.so
+  0x001c: Rev: 1  Flags: none  Index: 2  Cnt: 1  Name: LIBC
+  0x0038: Rev: 1  Flags: none  Index: 3  Cnt: 2  Name: LIBC_N
+  0x0054: Parent 1: LIBC
+  0x005c: Rev: 1  Flags: none  Index: 4  Cnt: 2  Name: LIBC_OMR1
+  0x0078: Parent 1: LIBC_N
+  0x0080: Rev: 1  Flags: none  Index: 5  Cnt: 2  Name: LIBC_PLATFORM
+  0x009c: Parent 1: LIBC_OMR1
+
+Displaying notes found in: .note.gnu.build-id
+  Owner                 Data size	Description
+  GNU                  0x00000010	NT_GNU_BUILD_ID (unique build ID bitstring)
+    Build ID: 676a0450f6cc27cf2554a3d1634fc4fe
+
+Displaying notes found in: .note.gnu.gold-version
+  Owner                 Data size	Description
+  GNU                  0x00000009	NT_GNU_GOLD_VERSION (gold version)
+    Version: gold 1.12
+Attribute Section: aeabi
+File Attributes
+  Tag_conformance: "2.09"
+  Tag_CPU_name: "cortex-a53"
+  Tag_CPU_arch: v8
+  Tag_CPU_arch_profile: Application
+  Tag_ARM_ISA_use: Yes
+  Tag_THUMB_ISA_use: Thumb-2
+  Tag_Advanced_SIMD_arch: NEON for ARMv8
+  Tag_ABI_PCS_RW_data: PC-relative
+  Tag_ABI_PCS_RO_data: PC-relative
+  Tag_ABI_PCS_GOT_use: GOT-indirect
+  Tag_ABI_PCS_wchar_t: 4
+  Tag_ABI_FP_denormal: Needed
+  Tag_ABI_FP_exceptions: Needed
+  Tag_ABI_FP_number_model: IEEE 754
+  Tag_ABI_align_needed: 8-byte
+  Tag_ABI_align_preserved: 8-byte, except leaf SP
+  Tag_ABI_enum_size: int
+  Tag_CPU_unaligned_access: v6
+  Tag_FP_HP_extension: Allowed
+  Tag_ABI_FP_16bit_format: IEEE 754
+  Tag_MPextension_use: Allowed
+  Tag_Virtualization_use: TrustZone and Virtualization Extensions
diff --git a/libraries/compatibility-common-util/tests/assets/arm64_libdl.so b/libraries/compatibility-common-util/tests/assets/arm64_libdl.so
new file mode 100644
index 0000000..f6e3034
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/arm64_libdl.so
Binary files differ
diff --git a/libraries/compatibility-common-util/tests/assets/arm64_libdl.txt b/libraries/compatibility-common-util/tests/assets/arm64_libdl.txt
new file mode 100644
index 0000000..d531a96
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/arm64_libdl.txt
@@ -0,0 +1,232 @@
+ELF Header:
+  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
+  Class:                             ELF64
+  Data:                              2's complement, little endian
+  Version:                           1 (current)
+  OS/ABI:                            UNIX - System V
+  ABI Version:                       0
+  Type:                              DYN (Shared object file)
+  Machine:                           AArch64
+  Version:                           0x1
+  Entry point address:               0x0
+  Start of program headers:          64 (bytes into file)
+  Start of section headers:          66280 (bytes into file)
+  Flags:                             0x0
+  Size of this header:               64 (bytes)
+  Size of program headers:           56 (bytes)
+  Number of program headers:         8
+  Size of section headers:           64 (bytes)
+  Number of section headers:         19
+  Section header string table index: 18
+
+Section Headers:
+  [Nr] Name              Type             Address           Offset
+       Size              EntSize          Flags  Link  Info  Align
+  [ 0]                   NULL             0000000000000000  00000000
+       0000000000000000  0000000000000000           0     0     0
+  [ 1] .note.gnu.build-i NOTE             0000000000000200  00000200
+       0000000000000020  0000000000000000   A       0     0     4
+  [ 2] .dynsym           DYNSYM           0000000000000220  00000220
+       0000000000000420  0000000000000018   A       3     1     8
+  [ 3] .dynstr           STRTAB           0000000000000640  00000640
+       00000000000003eb  0000000000000000   A       0     0     1
+  [ 4] .gnu.hash         GNU_HASH         0000000000000a30  00000a30
+       00000000000000d8  0000000000000000   A       2     0     8
+  [ 5] .gnu.version      VERSYM           0000000000000b08  00000b08
+       0000000000000058  0000000000000002   A       2     0     2
+  [ 6] .gnu.version_d    VERDEF           0000000000000b60  00000b60
+       00000000000000a4  0000000000000000   A       3     5     4
+  [ 7] .rela.plt         RELA             0000000000000c08  00000c08
+       00000000000001b0  0000000000000018  AI       2    14     8
+  [ 8] .plt              PROGBITS         0000000000000db8  00000db8
+       0000000000000140  0000000000000010  AX       0     0     8
+  [ 9] .text             PROGBITS         0000000000000ef8  00000ef8
+       000000000000026c  0000000000000000  AX       0     0     4
+  [10] .eh_frame         PROGBITS         0000000000001168  00001168
+       00000000000002a8  0000000000000000   A       0     0     8
+  [11] .eh_frame_hdr     PROGBITS         0000000000001410  00001410
+       00000000000000b4  0000000000000000   A       0     0     4
+  [12] .dynamic          DYNAMIC          000000000001fdf0  0000fdf0
+       0000000000000160  0000000000000010  WA       3     0     8
+  [13] .got              PROGBITS         000000000001ff50  0000ff50
+       0000000000000008  0000000000000000  WA       0     0     8
+  [14] .got.plt          PROGBITS         000000000001ff58  0000ff58
+       00000000000000a8  0000000000000000  WA       0     0     8
+  [15] .bss              NOBITS           0000000000020000  00010000
+       0000000000001000  0000000000000000  WA       0     0     4096
+  [16] .note.gnu.gold-ve NOTE             0000000000000000  00010000
+       000000000000001c  0000000000000000           0     0     4
+  [17] .gnu_debugdata    PROGBITS         0000000000000000  0001001c
+       0000000000000208  0000000000000000           0     0     1
+  [18] .shstrtab         STRTAB           0000000000000000  00010224
+       00000000000000be  0000000000000000           0     0     1
+Key to Flags:
+  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
+  L (link order), O (extra OS processing required), G (group), T (TLS),
+  C (compressed), x (unknown), o (OS specific), E (exclude),
+  p (processor specific)
+
+There are no section groups in this file.
+
+Program Headers:
+  Type           Offset             VirtAddr           PhysAddr
+                 FileSiz            MemSiz              Flags  Align
+  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
+                 0x00000000000001c0 0x00000000000001c0  R      0x8
+  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
+                 0x00000000000014c4 0x00000000000014c4  R E    0x10000
+  LOAD           0x000000000000fdf0 0x000000000001fdf0 0x000000000001fdf0
+                 0x0000000000000210 0x0000000000001210  RW     0x10000
+  DYNAMIC        0x000000000000fdf0 0x000000000001fdf0 0x000000000001fdf0
+                 0x0000000000000160 0x0000000000000160  RW     0x8
+  NOTE           0x0000000000000200 0x0000000000000200 0x0000000000000200
+                 0x0000000000000020 0x0000000000000020  R      0x4
+  GNU_EH_FRAME   0x0000000000001410 0x0000000000001410 0x0000000000001410
+                 0x00000000000000b4 0x00000000000000b4  R      0x4
+  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
+                 0x0000000000000000 0x0000000000000000  RW     0x10
+  GNU_RELRO      0x000000000000fdf0 0x000000000001fdf0 0x000000000001fdf0
+                 0x0000000000000210 0x0000000000000210  RW     0x8
+
+ Section to Segment mapping:
+  Segment Sections...
+   00     
+   01     .note.gnu.build-id .dynsym .dynstr .gnu.hash .gnu.version .gnu.version_d .rela.plt .plt .text .eh_frame .eh_frame_hdr 
+   02     .dynamic .got .got.plt .bss 
+   03     .dynamic 
+   04     .note.gnu.build-id 
+   05     .eh_frame_hdr 
+   06     
+   07     .dynamic .got .got.plt 
+
+Dynamic section at offset 0xfdf0 contains 17 entries:
+  Tag        Type                         Name/Value
+ 0x0000000000000003 (PLTGOT)             0x1ff58
+ 0x0000000000000002 (PLTRELSZ)           432 (bytes)
+ 0x0000000000000017 (JMPREL)             0xc08
+ 0x0000000000000014 (PLTREL)             RELA
+ 0x0000000000000006 (SYMTAB)             0x220
+ 0x000000000000000b (SYMENT)             24 (bytes)
+ 0x0000000000000005 (STRTAB)             0x640
+ 0x000000000000000a (STRSZ)              1003 (bytes)
+ 0x000000006ffffef5 (GNU_HASH)           0xa30
+ 0x0000000000000001 (NEEDED)             Shared library: [ld-android.so]
+ 0x000000000000000e (SONAME)             Library soname: [libdl.so]
+ 0x000000000000001e (FLAGS)              BIND_NOW
+ 0x000000006ffffffb (FLAGS_1)            Flags: NOW
+ 0x000000006ffffff0 (VERSYM)             0xb08
+ 0x000000006ffffffc (VERDEF)             0xb60
+ 0x000000006ffffffd (VERDEFNUM)          5
+ 0x0000000000000000 (NULL)               0x0
+
+Relocation section '.rela.plt' at offset 0xc08 contains 18 entries:
+  Offset          Info           Type           Sym. Value    Sym. Name + Addend
+00000001ff70  000f00000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_dlopen + 0
+00000001ff78  000e00000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_dlerror + 0
+00000001ff80  001000000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_dlsym + 0
+00000001ff88  001100000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_dlvsym + 0
+00000001ff90  000c00000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_dladdr + 0
+00000001ff98  000d00000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_dlclose + 0
+00000001ffa0  000b00000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_dl_iterate_ph + 0
+00000001ffa8  000400000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_get_L + 0
+00000001ffb0  000a00000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_updat + 0
+00000001ffb8  000200000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_dlope + 0
+00000001ffc0  000900000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_set_a + 0
+00000001ffc8  000500000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_get_a + 0
+00000001ffd0  000700000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_init_ + 0
+00000001ffd8  000100000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_creat + 0
+00000001ffe0  000800000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_link_ + 0
+00000001ffe8  000300000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_dlwar + 0
+00000001fff0  000600000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_android_get_e + 0
+00000001fff8  001200000402 R_AARCH64_JUMP_SL 0000000000000000 __loader_cfi_fail + 0
+
+The decoding of unwind sections for machine type AArch64 is not currently supported.
+
+Symbol table '.dynsym' contains 44 entries:
+   Num:    Value          Size Type    Bind   Vis      Ndx Name
+     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_create_n
+     2: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_dlopen_e
+     3: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_dlwarnin
+     4: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_get_LD_L
+     5: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_get_appl
+     6: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_get_expo
+     7: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_init_ano
+     8: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_link_nam
+     9: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_set_appl
+    10: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_android_update_L
+    11: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_dl_iterate_phdr
+    12: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_dladdr
+    13: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlclose
+    14: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlerror
+    15: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlopen
+    16: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlsym
+    17: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_dlvsym
+    18: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __loader_cfi_fail
+    19: 0000000000000fb8    24 FUNC    WEAK   DEFAULT    9 android_dlopen_ext@@LIBC
+    20: 0000000000000ff8    24 FUNC    WEAK   DEFAULT    9 android_init_anonymous_na@@LIBC_PLATFORM
+    21: 0000000000001100   100 FUNC    GLOBAL DEFAULT    9 __cfi_slowpath_diag@@LIBC_OMR1
+    22: 0000000000000fa4    20 FUNC    WEAK   DEFAULT    9 android_update_LD_LIBRARY@@LIBC_PLATFORM
+    23: 0000000000001054    20 FUNC    WEAK   DEFAULT    9 android_get_exported_name@@LIBC_PLATFORM
+    24: 0000000000000fd0    20 FUNC    WEAK   DEFAULT    9 android_set_application_t@@LIBC_PLATFORM
+    25: 0000000000000f24    24 FUNC    WEAK   DEFAULT    9 dlsym@@LIBC
+    26: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC_N
+    27: 0000000000001028    24 FUNC    WEAK   DEFAULT    9 android_link_namespaces@@LIBC_PLATFORM
+    28: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC
+    29: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC_PLATFORM
+    30: 0000000000000f10    20 FUNC    WEAK   DEFAULT    9 dlerror@@LIBC
+    31: 0000000000000ef8    24 FUNC    WEAK   DEFAULT    9 dlopen@@LIBC
+    32: 000000000000107c    24 FUNC    GLOBAL DEFAULT    9 __cfi_shadow_size@@LIBC_OMR1
+    33: 0000000000000f68    20 FUNC    WEAK   DEFAULT    9 dlclose@@LIBC
+    34: 0000000000001040    20 FUNC    WEAK   DEFAULT    9 android_dlwarning@@LIBC_PLATFORM
+    35: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS LIBC_OMR1
+    36: 0000000000000fe4    20 FUNC    WEAK   DEFAULT    9 android_get_application_t@@LIBC_PLATFORM
+    37: 0000000000001094   108 FUNC    GLOBAL DEFAULT    9 __cfi_slowpath@@LIBC_OMR1
+    38: 0000000000001010    24 FUNC    WEAK   DEFAULT    9 android_create_namespace@@LIBC_PLATFORM
+    39: 0000000000000f7c    20 FUNC    WEAK   DEFAULT    9 dl_iterate_phdr@@LIBC
+    40: 0000000000000f54    20 FUNC    WEAK   DEFAULT    9 dladdr@@LIBC
+    41: 0000000000000f90    20 FUNC    WEAK   DEFAULT    9 android_get_LD_LIBRARY_PA@@LIBC_PLATFORM
+    42: 0000000000000f3c    24 FUNC    WEAK   DEFAULT    9 dlvsym@@LIBC_N
+    43: 0000000000001068    20 FUNC    GLOBAL DEFAULT    9 __cfi_init@@LIBC_PLATFORM
+
+Histogram for `.gnu.hash' bucket list length (total of 17 buckets):
+ Length  Number     % of total  Coverage
+      0  0          (  0.0%)
+      1  10         ( 58.8%)     40.0%
+      2  6          ( 35.3%)     88.0%
+      3  1          (  5.9%)    100.0%
+
+Version symbols section '.gnu.version' contains 44 entries:
+ Addr: 0000000000000b08  Offset: 0x000b08  Link: 2 (.dynsym)
+  000:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  004:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  008:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  00c:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  010:   0 (*local*)       0 (*local*)       0 (*local*)       2 (LIBC)       
+  014:   5 (LIBC_PLATFORM)   4 (LIBC_OMR1)     5 (LIBC_PLATFORM)   5 (LIBC_PLATFORM)
+  018:   5 (LIBC_PLATFORM)   2 (LIBC)          3 (LIBC_N)        5 (LIBC_PLATFORM)
+  01c:   2 (LIBC)          5 (LIBC_PLATFORM)   2 (LIBC)          2 (LIBC)       
+  020:   4 (LIBC_OMR1)     2 (LIBC)          5 (LIBC_PLATFORM)   4 (LIBC_OMR1)  
+  024:   5 (LIBC_PLATFORM)   4 (LIBC_OMR1)     5 (LIBC_PLATFORM)   2 (LIBC)       
+  028:   2 (LIBC)          5 (LIBC_PLATFORM)   3 (LIBC_N)        5 (LIBC_PLATFORM)
+
+Version definition section '.gnu.version_d' contains 5 entries:
+  Addr: 0x0000000000000b60  Offset: 0x000b60  Link: 3 (.dynstr)
+  000000: Rev: 1  Flags: BASE  Index: 1  Cnt: 1  Name: libdl.so
+  0x001c: Rev: 1  Flags: none  Index: 2  Cnt: 1  Name: LIBC
+  0x0038: Rev: 1  Flags: none  Index: 3  Cnt: 2  Name: LIBC_N
+  0x0054: Parent 1: LIBC
+  0x005c: Rev: 1  Flags: none  Index: 4  Cnt: 2  Name: LIBC_OMR1
+  0x0078: Parent 1: LIBC_N
+  0x0080: Rev: 1  Flags: none  Index: 5  Cnt: 2  Name: LIBC_PLATFORM
+  0x009c: Parent 1: LIBC_OMR1
+
+Displaying notes found in: .note.gnu.build-id
+  Owner                 Data size	Description
+  GNU                  0x00000010	NT_GNU_BUILD_ID (unique build ID bitstring)
+    Build ID: 52512b2d7a8b4c6fc4eace5145a3daca
+
+Displaying notes found in: .note.gnu.gold-version
+  Owner                 Data size	Description
+  GNU                  0x00000009	NT_GNU_GOLD_VERSION (gold version)
+    Version: gold 1.12
diff --git a/libraries/compatibility-common-util/tests/assets/logcat.txt b/libraries/compatibility-common-util/tests/assets/logcat.txt
new file mode 100644
index 0000000..ffb28ad
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/logcat.txt
@@ -0,0 +1,335 @@
+--------- beginning of system
+09-03 17:47:59.490  7039  7054 D AtCkpdCmdHandler: De-queing command
+--------- beginning of crash
+09-03 17:48:05.627 11071 11189 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xe9380000 in tid 11189 (AudioOut_D)
+09-03 17:48:05.707   359   359 W         : debuggerd: handling request: pid=11071 uid=1041 gid=1005 tid=11189
+09-03 17:48:05.796  7072  7072 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+09-03 17:48:05.796  7072  7072 F DEBUG   : Build fingerprint: 'google/angler/angler:7.1.1/N4F26T/3687331:userdebug/dev-keys'
+09-03 17:48:05.796  7072  7072 F DEBUG   : Revision: '0'
+09-03 17:48:05.796  7072  7072 F DEBUG   : ABI: 'arm'
+09-03 17:48:05.796  7072  7072 F DEBUG   : pid: 11071, tid: 11189, name: AudioOut_D  >>> /system/bin/audioserver <<<
+09-03 17:48:05.797  7072  7072 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xe9380000
+09-03 17:48:05.797  7072  7072 F DEBUG   :     r0 e9e7a240  r1 e9380000  r2 00000170  r3 00000000
+09-03 17:48:05.797  7072  7072 F DEBUG   :     r4 00000002  r5 00000000  r6 ec1e1f25  r7 eb6f8000
+09-03 17:48:05.797  7072  7072 F DEBUG   :     r8 00000000  r9 eb105204  sl 00000000  fp 000003c0
+09-03 17:48:05.797  7072  7072 F DEBUG   :     ip ebd3df18  sp eaf80688  lr ec1e1f41  pc ebd38dd6  cpsr 20000030
+09-03 17:48:05.805  7072  7072 F DEBUG   :
+09-03 17:48:05.805  7072  7072 F DEBUG   : backtrace:
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #00 pc 00002dd6  /system/lib/libaudioutils.so (memcpy_to_float_from_i16+5)
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #01 pc 00040f3d  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #02 pc 00040799  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #03 pc 00011178  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #04 pc 0003180b  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #05 pc 0002fe57  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #06 pc 0000e345  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140)
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #07 pc 000470b3  /system/lib/libc.so (_ZL15__pthread_startPv+22)
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #08 pc 00019e3d  /system/lib/libc.so (__start_thread+6)
+09-03 17:48:05.967 11272 11568 W NativeCrashListener: Couldn't find ProcessRecord for pid 11071
+09-03 17:48:05.969   359   359 W         : debuggerd: resuming target 11071
+09-03 17:48:05.981 11272 11307 I BootReceiver: Copying /data/tombstones/tombstone_01 to DropBox (SYSTEM_TOMBSTONE)
+09-03 17:48:06.067   394   394 I ServiceManager: service 'media.sound_trigger_hw' died
+06-15 19:57:33.607 12736 12761 D PermissionCache: checking android.permission.MODIFY_AUDIO_SETTINGS for uid=10197 => granted (698 us)
+--------- beginning of crash
+06-15 19:57:33.607 12736 12761 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 12761 (Binder:12736_2)
+06-15 19:57:33.608   379   379 W         : debuggerd: handling request: pid=12736 uid=1041 gid=1005 tid=12761
+06-15 19:57:33.670 26192 26192 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+06-15 19:57:33.670 26192 26192 F DEBUG   : Build fingerprint: 'google/bullhead/bullhead:7.1.2/N2G48C/4104010:userdebug/dev-keys'
+06-15 19:57:33.670 26192 26192 F DEBUG   : Revision: 'rev_1.0'
+06-15 19:57:33.670 26192 26192 F DEBUG   : ABI: 'arm'
+06-15 19:57:33.670 26192 26192 F DEBUG   : pid: 12736, tid: 12761, name: Binder:12736_2  >>> /system/bin/audioserver <<<
+06-15 19:57:33.670 26192 26192 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
+06-15 19:57:33.670 26192 26192 F DEBUG   :     r0 00000000  r1 00000000  r2 0000005f  r3 00000000
+06-15 19:57:33.670 26192 26192 F DEBUG   :     r4 ffffffff  r5 00000000  r6 f14f9000  r7 00000001
+06-15 19:57:33.670 26192 26192 F DEBUG   :     r8 00000004  r9 f3353114  sl f3313900  fp 00000000
+06-15 19:57:33.670 26192 26192 F DEBUG   :     ip f3bd4d88  sp f127d9c8  lr f3b9cbc5  pc f3b65af4  cpsr 60000030
+06-15 19:57:33.676 26192 26192 F DEBUG   :
+06-15 19:57:33.676 26192 26192 F DEBUG   : backtrace:
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #00 pc 00018af4  /system/lib/libc.so (strlen+71)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #01 pc 0004fbc1  /system/lib/libc.so (__strlen_chk+4)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #02 pc 0000c599  /system/lib/libutils.so (_ZN7android7String8C2EPKc+12)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #03 pc 0002fdbf  /system/lib/libaudiopolicymanagerdefault.so (_ZNK7android18HwModuleCollection19getDeviceDescriptorEjPKcS2_b+458)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #04 pc 0001de47  /system/lib/libaudiopolicymanagerdefault.so (_ZN7android18AudioPolicyManager27setDeviceConnectionStateIntEj24audio_policy_dev_state_tPKcS3_+178)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #05 pc 0000a009  /system/lib/libaudiopolicyservice.so
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #06 pc 000a01a5  /system/lib/libmedia.so (_ZN7android20BnAudioPolicyService10onTransactEjRKNS_6ParcelEPS1_j+1256)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #07 pc 000359c3  /system/lib/libbinder.so (_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j+70)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #08 pc 0003d1bb  /system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi+702)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #09 pc 0003ce07  /system/lib/libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+114)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #10 pc 0003d31b  /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+46)
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #11 pc 0004f8c5  /system/lib/libbinder.so
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #12 pc 0000e345  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140)
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #13 pc 000470b3  /system/lib/libc.so (_ZL15__pthread_startPv+22)
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #14 pc 00019e3d  /system/lib/libc.so (__start_thread+6)
+06-15 19:57:33.839   934  2991 W NativeCrashListener: Couldn't find ProcessRecord for pid 12736
+06-15 19:57:33.846   934   952 I BootReceiver: Copying /data/tombstones/tombstone_01 to DropBox (SYSTEM_TOMBSTONE)
+06-15 19:57:35.130 26201 26227 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 26227 (Binder:26201_3)
+06-15 19:57:35.130 26201 26228 D PermissionCache: checking android.permission.MODIFY_AUDIO_SETTINGS for uid=1000 => granted (318 us)
+06-15 19:57:35.130   379   379 W         : debuggerd: handling request: pid=26201 uid=1041 gid=1005 tid=26227
+06-15 19:57:35.131 26201 26212 D audio_hw_primary: select_devices: changing use case low-latency-playback output device from(0: none, acdb -1) to (2: speaker, acdb 14)
+06-15 19:57:35.191 26230 26230 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+06-15 19:57:35.191 26230 26230 F DEBUG   : Build fingerprint: 'google/bullhead/bullhead:7.1.2/N2G48C/4104010:userdebug/dev-keys'
+06-15 19:57:35.191 26230 26230 F DEBUG   : Revision: 'rev_1.0'
+06-15 19:57:35.191 26230 26230 F DEBUG   : ABI: 'arm'
+06-15 19:57:35.191 26230 26230 F DEBUG   : pid: 26201, tid: 26227, name: Binder:26201_3  >>> /system/bin/audioserver <<<
+06-15 19:57:35.191 26230 26230 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
+06-15 19:57:35.191 26230 26230 F DEBUG   :     r0 00000000  r1 00000000  r2 0000005f  r3 00000000
+06-15 19:57:35.191 26230 26230 F DEBUG   :     r4 ffffffff  r5 00000000  r6 e49bb000  r7 00000001
+06-15 19:57:35.191 26230 26230 F DEBUG   :     r8 00000004  r9 e6b53114  sl e6b13900  fp 00000000
+06-15 19:57:35.191 26230 26230 F DEBUG   :     ip e746bd88  sp e4c009c8  lr e7433bc5  pc e73fcaf4  cpsr 60000030
+06-15 19:57:35.195 26230 26230 F DEBUG   :
+06-15 19:57:35.195 26230 26230 F DEBUG   : backtrace:
+06-15 19:57:35.195 26230 26230 F DEBUG   :     #00 pc 00018af4  /system/lib/libc.so (strlen+71)
+06-15 19:57:35.195 26230 26230 F DEBUG   :     #01 pc 0004fbc1  /system/lib/libc.so (__strlen_chk+4)
+06-15 19:57:35.195 26230 26230 F DEBUG   :     #02 pc 0000c599  /system/lib/libutils.so (_ZN7android7String8C2EPKc+12)
+06-15 19:57:35.195 26230 26230 F DEBUG   :     #03 pc 0002fdbf  /system/lib/libaudiopolicymanagerdefault.so (_ZNK7android18HwModuleCollection19getDeviceDescriptorEjPKcS2_b+458)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #04 pc 0001de47  /system/lib/libaudiopolicymanagerdefault.so (_ZN7android18AudioPolicyManager27setDeviceConnectionStateIntEj24audio_policy_dev_state_tPKcS3_+178)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #05 pc 0000a009  /system/lib/libaudiopolicyservice.so
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #06 pc 000a01a5  /system/lib/libmedia.so (_ZN7android20BnAudioPolicyService10onTransactEjRKNS_6ParcelEPS1_j+1256)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #07 pc 000359c3  /system/lib/libbinder.so (_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j+70)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #08 pc 0003d1bb  /system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi+702)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #09 pc 0003ce07  /system/lib/libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+114)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #10 pc 0003d31b  /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+46)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #11 pc 0004f8c5  /system/lib/libbinder.so
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #12 pc 0000e345  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #13 pc 000470b3  /system/lib/libc.so (_ZL15__pthread_startPv+22)
+06-15 19:57:35.196 26230 26230 F DEBUG   :     #14 pc 00019e3d  /system/lib/libc.so (__start_thread+6)
+06-15 19:57:35.346   934  2991 W NativeCrashListener: Couldn't find ProcessRecord for pid 26201
+06-15 19:57:35.346 26230 26230 E         : AM data write failed: Broken pipe
+06-15 19:57:40.605 26246 26261 D audio_hw_primary: enable_snd_device: snd_device(78: vi-feedback)
+06-15 19:57:40.606 26246 26261 D audio_hw_primary: enable_audio_route: usecase(21) apply and update mixer path: spkr-vi-record
+06-15 19:57:40.673 26283 26283 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+06-15 19:57:40.674 26283 26283 F DEBUG   : Build fingerprint: 'google/bullhead/bullhead:7.1.2/N2G48C/4104010:userdebug/dev-keys'
+06-15 19:57:40.674 26283 26283 F DEBUG   : Revision: 'rev_1.0'
+06-15 19:57:40.674 26283 26283 F DEBUG   : ABI: 'arm'
+06-15 19:57:40.674 26283 26283 F DEBUG   : pid: 26246, tid: 26282, name: Binder:26246_5  >>> /system/bin/audioserver <<<
+06-15 19:57:40.674 26283 26283 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
+06-15 19:57:40.674 26283 26283 F DEBUG   :     r0 00000000  r1 00000000  r2 0000005f  r3 00000000
+06-15 19:57:40.674 26283 26283 F DEBUG   :     r4 ffffffff  r5 00000000  r6 eb750000  r7 00000001
+06-15 19:57:40.674 26283 26283 F DEBUG   :     r8 00000004  r9 ed953114  sl ed913900  fp 00000000
+06-15 19:57:40.674 26283 26283 F DEBUG   :     ip eda8bd88  sp eb4fd9c8  lr eda53bc5  pc eda1caf4  cpsr 60000030
+06-15 19:57:40.679 26283 26283 F DEBUG   :
+06-15 19:57:40.679 26283 26283 F DEBUG   : backtrace:
+06-15 19:57:40.679 26283 26283 F DEBUG   :     #00 pc 00018af4  /system/lib/libc.so (strlen+71)
+06-15 19:57:40.679 26283 26283 F DEBUG   :     #01 pc 0004fbc1  /system/lib/libc.so (__strlen_chk+4)
+06-15 19:57:40.679 26283 26283 F DEBUG   :     #02 pc 0000c599  /system/lib/libutils.so (_ZN7android7String8C2EPKc+12)
+06-15 19:57:40.679 26283 26283 F DEBUG   :     #03 pc 0002fdbf  /system/lib/libaudiopolicymanagerdefault.so (_ZNK7android18HwModuleCollection19getDeviceDescriptorEjPKcS2_b+458)
+06-15 19:57:40.679 26283 26283 F DEBUG   :     #04 pc 0001de47  /system/lib/libaudiopolicymanagerdefault.so (_ZN7android18AudioPolicyManager27setDeviceConnectionStateIntEj24audio_policy_dev_state_tPKcS3_+178)
+06-15 19:57:40.679 26283 26283 F DEBUG   :     #05 pc 0000a009  /system/lib/libaudiopolicyservice.so
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #06 pc 000a01a5  /system/lib/libmedia.so (_ZN7android20BnAudioPolicyService10onTransactEjRKNS_6ParcelEPS1_j+1256)
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #07 pc 000359c3  /system/lib/libbinder.so (_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j+70)
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #08 pc 0003d1bb  /system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi+702)
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #09 pc 0003ce07  /system/lib/libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+114)
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #10 pc 0003d31b  /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+46)
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #11 pc 0004f8c5  /system/lib/libbinder.so
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #12 pc 0000e345  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140)
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #13 pc 000470b3  /system/lib/libc.so (_ZL15__pthread_startPv+22)
+06-15 19:57:40.680 26283 26283 F DEBUG   :     #14 pc 00019e3d  /system/lib/libc.so (__start_thread+6)
+06-15 19:57:40.882   934  2991 W NativeCrashListener: Couldn't find ProcessRecord for pid 26246
+06-15 19:57:40.889   934   952 I BootReceiver: Copying /data/tombstones/tombstone_03 to DropBox (SYSTEM_TOMBSTONE)
+09-23 01:55:43.022   245   245 F installd: utils.cpp:67] Check failed: is_valid_package_name(package_name) == 0
+--------- beginning of crash
+09-23 01:55:43.022   245   245 F libc    : Fatal signal 6 (SIGABRT), code -6 in tid 245 (installd)
+09-23 01:55:43.022   166   166 W         : debuggerd: handling request: pid=245 uid=0 gid=0 tid=245
+09-23 01:55:43.026   546   546 E         : debuggerd: Unable to connect to activity manager (connect failed: Connection refused)
+09-23 01:55:43.076   546   546 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+09-23 01:55:43.076   546   546 F DEBUG   : Build fingerprint: 'google/ryu/dragon:7.1.2/N2G48C/4104010:userdebug/dev-keys'
+09-23 01:55:43.076   546   546 F DEBUG   : Revision: '0'
+09-23 01:55:43.076   546   546 F DEBUG   : ABI: 'arm64'
+09-23 01:55:43.077   546   546 F DEBUG   : pid: 245, tid: 245, name: installd  >>> /system/bin/installd <<<
+09-23 01:55:43.077   546   546 F DEBUG   : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
+09-23 01:55:43.077   546   546 F DEBUG   : Abort message: 'utils.cpp:67] Check failed: is_valid_package_name(package_name) == 0 '
+09-23 01:55:43.077   546   546 F DEBUG   :     x0   0000000000000000  x1   00000000000000f5  x2   0000000000000006  x3   0000000000000008
+09-23 01:55:43.078   546   546 F DEBUG   :     x4   0000000000000000  x5   0000000000000000  x6   00000076a4172000  x7   0000000000000000
+09-23 01:55:43.078   546   546 F DEBUG   :     x8   0000000000000083  x9   ffffffffffffffdf  x10  0000000000000000  x11  0000000000000001
+09-23 01:55:43.078   546   546 F DEBUG   :     x12  0000000000000018  x13  0000000000000000  x14  0000000000000000  x15  000157de95b365f0
+09-23 01:55:43.078   546   546 F DEBUG   :     x16  00000076a4099ee0  x17  00000076a4043b24  x18  0000000000000000  x19  00000076a4227b40
+09-23 01:55:43.078   546   546 F DEBUG   :     x20  0000000000000006  x21  00000076a4227a98  x22  0000000000000014  x23  0000000000000005
+09-23 01:55:43.078   546   546 F DEBUG   :     x24  00000076a3834040  x25  0000000000000000  x26  0000000000000005  x27  0000000000000006
+09-23 01:55:43.078   546   546 F DEBUG   :     x28  0000007ff8a77879  x29  0000007ff8a777f0  x30  00000076a4040f50
+09-23 01:55:43.078   546   546 F DEBUG   :     sp   0000007ff8a777d0  pc   00000076a4043b2c  pstate 0000000060000000
+09-23 01:55:43.081   546   546 F DEBUG   :
+09-23 01:55:43.081   546   546 F DEBUG   : backtrace:
+09-23 01:55:43.081   546   546 F DEBUG   :     #00 pc 000000000006bb2c  /system/lib64/libc.so (tgkill+8)
+09-23 01:55:43.081   546   546 F DEBUG   :     #01 pc 0000000000068f4c  /system/lib64/libc.so (pthread_kill+64)
+09-23 01:55:43.081   546   546 F DEBUG   :     #02 pc 0000000000023f58  /system/lib64/libc.so (raise+24)
+09-23 01:55:43.081   546   546 F DEBUG   :     #03 pc 000000000001c810  /system/lib64/libc.so (abort+52)
+09-23 01:55:43.081   546   546 F DEBUG   :     #04 pc 000000000000609c  /system/lib64/libbase.so (_ZN7android4base10LogMessageD1Ev+1084)
+09-23 01:55:43.082   546   546 F DEBUG   :     #05 pc 000000000001bbd4  /system/bin/installd
+09-23 01:55:43.082   546   546 F DEBUG   :     #06 pc 000000000001be38  /system/bin/installd
+09-23 01:55:43.082   546   546 F DEBUG   :     #07 pc 0000000000007f08  /system/bin/installd
+09-23 01:55:43.082   546   546 F DEBUG   :     #08 pc 0000000000005bd4  /system/bin/installd
+09-23 01:55:43.082   546   546 F DEBUG   :     #09 pc 000000000001a594  /system/lib64/libc.so (__libc_init+88)
+09-23 01:55:43.082   546   546 F DEBUG   :     #10 pc 0000000000004818  /system/bin/installd
+09-23 01:55:43.093   166   166 W         : debuggerd: resuming target 245
+09-23 01:55:43.132   516   516 E InstallerConnection: read exception
+09-23 01:55:43.132   516   516 I InstallerConnection: disconnecting...
+09-23 01:55:48.494   516   537 W WindowManager: App freeze timeout expired.
+09-23 01:55:52.058   163   163 W auditd  : type=1404 audit(0.0:4): enforcing=0 old_enforcing=1 auid=4294967295 ses=4294967295
+--------- beginning of main
+11-03 02:59:48.505  8049  8049 I stagefright: type=1400 audit(0.0:130): avc: denied { read } for path="/data/data/test1.mp4" dev="sda35" ino=868967 scontext=u:r:drmserver:s0 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=1
+11-03 02:59:48.505  3939  3939 I chatty  : uid=10040(u0_a40) com.google.android.setupwizard expire 52528 lines
+11-03 02:59:48.559  8049  8054 I OMXClient: Treble IOmx obtained
+--------- beginning of crash
+11-03 02:59:48.892  6371  8072 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+11-03 02:59:48.892  6371  8072 F DEBUG   : Build fingerprint: 'google/marlin/marlin:8.0.0/OC/mspect11021711:userdebug/dev-keys'
+11-03 02:59:48.892  6371  8072 F DEBUG   : Revision: '0'
+11-03 02:59:48.892  6371  8072 F DEBUG   : ABI: 'arm'
+11-03 02:59:48.892  6371  8072 F DEBUG   : pid: 6371, tid: 8072, name: media.codec  >>> omx@1.0-service <<<
+11-03 02:59:48.892  6371  8072 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xed000000
+11-03 02:59:48.900  6371  8072 F DEBUG   :     r0 ecffdba0  r1 ed000000  r2 d44854c0  r3 00000070
+11-03 02:59:48.900  6371  8072 F DEBUG   :     r4 00000070  r5 000021a0  r6 00000070  r7 00000070
+11-03 02:59:48.900  6371  8072 F DEBUG   :     r8 00000040  r9 ffc2b278  sl ffffde70  fp 00000060
+11-03 02:59:48.900  6371  8072 F DEBUG   :     ip ffffffa0  sp d2fff620  lr 00004308  pc ed1c0e7c  cpsr a00f0010
+11-03 02:59:48.901  6371  8072 F DEBUG   :
+11-03 02:59:48.901  6371  8072 F DEBUG   : backtrace:
+11-03 02:59:48.901  6371  8072 F DEBUG   :     #00 pc 00034e7c  /system/lib/libstagefright_soft_hevcdec.so
+--------- beginning of system
+11-03 02:59:48.905  1135  1155 I BootReceiver: Copying /data/tombstones/tombstone_03 to DropBox (SYSTEM_TOMBSTONE)
+05-04 21:59:23.695  9363  9363 I crash_dump64: performing dump of process 8373 (target tid = 8414)
+05-04 21:59:23.695  9363  9363 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+05-04 21:59:23.696  9363  9363 F DEBUG   : Build fingerprint: 'google/taimen/taimen:8.1.0/OPM2.171026.006.A1/4756228:userdebug/dev-keys'
+05-04 21:59:23.696  9363  9363 F DEBUG   : Revision: 'rev_10'
+05-04 21:59:23.696  9363  9363 F DEBUG   : ABI: 'arm64'
+05-04 21:59:23.696  9363  9363 F DEBUG   : pid: 8373, tid: 8414, name: btu message loo  >>> com.android.bluetooth <<<
+05-04 21:59:23.696  9363  9363 F DEBUG   : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
+05-04 21:59:23.700  9363  9363 F DEBUG   : Abort message: '[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end().
+05-04 21:59:23.700  9363  9363 F DEBUG   : '
+05-04 21:59:23.700  9363  9363 F DEBUG   :     x0   0000000000000000  x1   00000000000020de  x2   0000000000000006  x3   0000000000000008
+05-04 21:59:23.701  9363  9363 F DEBUG   :     x4   613a4c415441465b  x5   613a4c415441465b  x6   613a4c415441465b  x7   6f697461636f6c6c
+05-04 21:59:23.701  9363  9363 F DEBUG   :     x8   0000000000000083  x9   0000000010000000  x10  000000703a7a7c80  x11  0000000000000001
+05-04 21:59:23.701  9363  9363 F DEBUG   :     x12  746e655f70616d20  x13  6c61203d21207972  x14  ff00000000000000  x15  ffffffffffffffff
+05-04 21:59:23.701  9363  9363 F DEBUG   :     x16  0000006380f4afa8  x17  00000070d20af52c  x18  0000000000000000  x19  00000000000020b5
+05-04 21:59:23.701  9363  9363 F DEBUG   :     x20  00000000000020de  x21  0000000000000083  x22  000000703a7a9588  x23  000000703b8ee000
+05-04 21:59:23.701  9363  9363 F DEBUG   :     x24  000000703a7a7d01  x25  000000703a7a9588  x26  000000703bc7d948  x27  00000070484c92d8
+05-04 21:59:23.701  9363  9363 F DEBUG   :     x28  0000000000000006  x29  000000703a7a7cc0  x30  00000070d2064760
+05-04 21:59:23.701  9363  9363 F DEBUG   :     sp   000000703a7a7c80  pc   00000070d2064788  pstate 0000000060000000
+05-04 21:59:23.742  9363  9363 F DEBUG   :
+05-04 21:59:23.742  9363  9363 F DEBUG   : backtrace:
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #00 pc 000000000001d788  /system/lib64/libc.so (abort+120)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #01 pc 0000000000083470  /system/lib64/libchrome.so (base::debug::BreakDebugger()+20)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #02 pc 000000000009affc  /system/lib64/libchrome.so (logging::LogMessage::~LogMessage()+1068)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #03 pc 0000000000199130  /system/lib64/hw/bluetooth.default.so (allocation_tracker_notify_free(unsigned char, void*)+720)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #04 pc 000000000019984c  /system/lib64/hw/bluetooth.default.so (osi_free(void*)+20)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #05 pc 0000000000163f1c  /system/lib64/hw/bluetooth.default.so (l2c_fcr_cleanup(t_l2c_ccb*)+92)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #06 pc 000000000016adc8  /system/lib64/hw/bluetooth.default.so (l2cu_release_ccb(t_l2c_ccb*)+176)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #07 pc 0000000000162ea0  /system/lib64/hw/bluetooth.default.so (l2c_csm_execute(t_l2c_ccb*, unsigned short, void*)+1852)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #08 pc 000000000015e4f4  /system/lib64/hw/bluetooth.default.so (L2CA_DisconnectRsp(unsigned short)+92)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #09 pc 00000000001838b0  /system/lib64/hw/bluetooth.default.so (sdp_disconnect_ind(unsigned short, bool)+52)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #10 pc 0000000000163574  /system/lib64/hw/bluetooth.default.so (l2c_csm_execute(t_l2c_ccb*, unsigned short, void*)+3600)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #11 pc 0000000000169f94  /system/lib64/hw/bluetooth.default.so (l2c_rcv_acl_data(BT_HDR*)+3980)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #12 pc 00000000000849cc  /system/lib64/libchrome.so (base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask const&)+188)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #13 pc 000000000009efa4  /system/lib64/libchrome.so (base::MessageLoop::RunTask(base::PendingTask const&)+444)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #14 pc 000000000009f26c  /system/lib64/libchrome.so (base::MessageLoop::DeferOrRunPendingTask(base::PendingTask)+52)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #15 pc 000000000009f698  /system/lib64/libchrome.so (base::MessageLoop::DoWork()+356)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #16 pc 00000000000a08a8  /system/lib64/libchrome.so (base::MessagePumpDefault::Run(base::MessagePump::Delegate*)+220)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #17 pc 00000000000ba124  /system/lib64/libchrome.so (base::RunLoop::Run()+136)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #18 pc 0000000000138660  /system/lib64/hw/bluetooth.default.so (btu_message_loop_run(void*)+248)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #19 pc 00000000001a24fc  /system/lib64/hw/bluetooth.default.so (work_queue_read_cb(void*)+92)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #20 pc 00000000001a0758  /system/lib64/hw/bluetooth.default.so (run_reactor(reactor_t*, int)+320)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #21 pc 00000000001a05ec  /system/lib64/hw/bluetooth.default.so (reactor_start(reactor_t*)+84)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #22 pc 00000000001a1f94  /system/lib64/hw/bluetooth.default.so (run_thread(void*)+184)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #23 pc 0000000000067d80  /system/lib64/libc.so (__pthread_start(void*)+36)
+05-04 21:59:23.743  9363  9363 F DEBUG   :     #24 pc 000000000001ec18  /system/lib64/libc.so (__start_thread+68)
+11-25 19:47:35.417  8080 11665 F libc    : Fatal signal 6 (SIGABRT), code -6 in tid 11665 (generic)
+11-25 19:47:35.487   940   940 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+11-25 19:47:35.487   940   940 F DEBUG   : Build fingerprint: 'samsung/hero2qltezc/hero2qltechn:6.0.1/MMB29M/G9350ZCU2APJ6:user/release-keys'
+11-25 19:47:35.487   940   940 F DEBUG   : Revision: '15'
+11-25 19:47:35.487   940   940 F DEBUG   : ABI: 'arm'
+11-25 19:47:35.487   940   940 F DEBUG   : pid: 8080, tid: 11665, name: generic  >>> /system/bin/mediaserver <<<
+11-25 19:47:35.487   940   940 F DEBUG   : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
+11-25 19:47:35.577   940   940 F DEBUG   : Abort message: 'frameworks/av/media/libstagefright/MPEG4Extractor.cpp:6853 CHECK_EQ( (unsigned)ptr[0],1u) failed: 129 vs. 1'
+11-25 19:47:35.577   940   940 F DEBUG   :     r0 00000000  r1 00002d91  r2 00000006  r3 eb23f978
+11-25 19:47:35.577   940   940 F DEBUG   :     r4 eb23f980  r5 eb23f930  r6 00000009  r7 0000010c
+11-25 19:47:35.577   940   940 F DEBUG   :     r8 e9e91140  r9 00000000  sl 00000000  fp 000003d3
+11-25 19:47:35.577   940   940 F DEBUG   :     ip 00000006  sp eb23db70  lr f701313d  pc f7015538  cpsr 40010010
+11-25 19:47:35.597   940   940 F DEBUG   :
+11-25 19:47:35.597   940   940 F DEBUG   : backtrace:
+11-25 19:47:35.597   940   940 F DEBUG   :     #00 pc 00042538  /system/lib/libc.so (tgkill+12)
+11-25 19:47:35.597   940   940 F DEBUG   :     #01 pc 00040139  /system/lib/libc.so (pthread_kill+32)
+11-25 19:47:35.597   940   940 F DEBUG   :     #02 pc 0001c783  /system/lib/libc.so (raise+10)
+11-25 19:47:35.597   940   940 F DEBUG   :     #03 pc 000199f1  /system/lib/libc.so (__libc_android_abort+34)
+11-25 19:47:35.597   940   940 F DEBUG   :     #04 pc 000175ac  /system/lib/libc.so (abort+4)
+11-25 19:47:35.597   940   940 F DEBUG   :     #05 pc 000085e7  /system/lib/libcutils.so (__android_log_assert+86)
+11-25 19:47:35.597   940   940 F DEBUG   :     #06 pc 000c1f49  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor25avcc_getCodecSpecificInfoERNS_2spINS_7ABufferEEEPKcj+392)
+11-25 19:47:35.597   940   940 F DEBUG   :     #07 pc 000c213f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor15checkConfigDataEjRKNS_2spINS_8MetaDataEEE+218)
+11-25 19:47:35.597   940   940 F DEBUG   :     #08 pc 000bbd25  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor12checkSupportEjRKNS_2spINS_8MetaDataEEE+136)
+11-25 19:47:35.597   940   940 F DEBUG   :     #09 pc 000ba555  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+13060)
+11-25 19:47:35.597   940   940 F DEBUG   :     #10 pc 000ba32d  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+12508)
+11-25 19:47:35.597   940   940 F DEBUG   :     #11 pc 000b8a6f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+6174)
+11-25 19:47:35.597   940   940 F DEBUG   :     #12 pc 000b8a6f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+6174)
+11-25 19:47:35.597   940   940 F DEBUG   :     #13 pc 000b8a6f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+6174)
+11-25 19:47:35.597   940   940 F DEBUG   :     #14 pc 000b8a6f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+6174)
+11-25 19:47:35.597   940   940 F DEBUG   :     #15 pc 000b8a6f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+6174)
+11-25 19:47:35.597   940   940 F DEBUG   :     #16 pc 000b6e3b  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor12readMetaDataEv+94)
+11-25 19:47:35.597   940   940 F DEBUG   :     #17 pc 000b6daf  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor11getMetaDataEv+10)
+11-25 19:47:35.597   940   940 F DEBUG   :     #18 pc 00088c53  /system/lib/libmediaplayerservice.so (_ZN7android8NuPlayer13GenericSource18initFromDataSourceEv+386)
+11-25 19:47:35.597   940   940 F DEBUG   :     #19 pc 00089b43  /system/lib/libmediaplayerservice.so (_ZN7android8NuPlayer13GenericSource14onPrepareAsyncEv+238)
+11-25 19:47:35.597   940   940 F DEBUG   :     #20 pc 0000b405  /system/lib/libstagefright_foundation.so (_ZN7android8AHandler14deliverMessageERKNS_2spINS_8AMessageEEE+16)
+11-25 19:47:35.597   940   940 F DEBUG   :     #21 pc 0000d423  /system/lib/libstagefright_foundation.so (_ZN7android8AMessage7deliverEv+54)
+11-25 19:47:35.597   940   940 F DEBUG   :     #22 pc 0000be29  /system/lib/libstagefright_foundation.so (_ZN7android7ALooper4loopEv+224)
+11-25 19:47:35.597   940   940 F DEBUG   :     #23 pc 0001011d  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+112)
+11-25 19:47:35.597   940   940 F DEBUG   :     #24 pc 0003fa3b  /system/lib/libc.so (_ZL15__pthread_startPv+30)
+11-25 19:47:35.597   940   940 F DEBUG   :     #25 pc 0001a085  /system/lib/libc.so (__start_thread+6)
+11-25 19:47:35.837   940   940 F DEBUG   :
+11-25 19:47:35.837   940   940 F DEBUG   : Tombstone written to: /data/tombstones/tombstone_01
+--------- beginning of crash
+09-03 17:48:05.627 11071 11189 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xe9380000 in tid 11189 (synthetic_thread)
+09-03 17:48:05.707   359   359 W         : debuggerd: handling request: pid=11071 uid=1041 gid=1005 tid=11189
+09-03 17:48:05.796  7072  7072 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+09-03 17:48:05.796  7072  7072 F DEBUG   : Build fingerprint: 'google/angler/angler:7.1.1/N4F26T/3687331:userdebug/dev-keys'
+09-03 17:48:05.796  7072  7072 F DEBUG   : Revision: '0'
+09-03 17:48:05.796  7072  7072 F DEBUG   : ABI: 'arm'
+09-03 17:48:05.796  7072  7072 F DEBUG   : pid: 11071, tid: 11189, name: synthetic_thread  >>> synthetic_process_0 <<<
+09-03 17:48:05.797  7072  7072 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xe9380000
+09-03 17:48:05.797  7072  7072 F DEBUG   :     r0 e9e7a240  r1 e9380000  r2 00000170  r3 00000000
+09-03 17:48:05.797  7072  7072 F DEBUG   :     r4 00000002  r5 00000000  r6 ec1e1f25  r7 eb6f8000
+09-03 17:48:05.797  7072  7072 F DEBUG   :     r8 00000000  r9 eb105204  sl 00000000  fp 000003c0
+09-03 17:48:05.797  7072  7072 F DEBUG   :     ip ebd3df18  sp eaf80688  lr ec1e1f41  pc ebd38dd6  cpsr 20000030
+09-03 17:48:05.805  7072  7072 F DEBUG   :
+09-03 17:48:05.805  7072  7072 F DEBUG   : backtrace:
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #00 pc 00002dd6  /system/lib/libaudioutils.so (memcpy_to_float_from_i16+5)
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #01 pc 00040f3d  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #02 pc 00040799  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #03 pc 00011178  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #04 pc 0003180b  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #05 pc 0002fe57  /system/lib/libaudioflinger.so
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #06 pc 0000e345  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140)
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #07 pc 000470b3  /system/lib/libc.so (_ZL15__pthread_startPv+22)
+09-03 17:48:05.806  7072  7072 F DEBUG   :     #08 pc 00019e3d  /system/lib/libc.so (__start_thread+6)
+09-03 17:48:05.967 11272 11568 W NativeCrashListener: Couldn't find ProcessRecord for pid 11071
+09-03 17:48:05.969   359   359 W         : debuggerd: resuming target 11071
+09-03 17:48:05.981 11272 11307 I BootReceiver: Copying /data/tombstones/tombstone_01 to DropBox (SYSTEM_TOMBSTONE)
+09-03 17:48:06.067   394   394 I ServiceManager: service 'media.sound_trigger_hw' died
+06-15 19:57:33.607 12736 12761 D PermissionCache: checking android.permission.MODIFY_AUDIO_SETTINGS for uid=10197 => granted (698 us)
+--------- beginning of crash
+06-15 19:57:33.607 12736 12761 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 12761 (synthetic_thread)
+06-15 19:57:33.608   379   379 W         : debuggerd: handling request: pid=12736 uid=1041 gid=1005 tid=12761
+06-15 19:57:33.670 26192 26192 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+06-15 19:57:33.670 26192 26192 F DEBUG   : Build fingerprint: 'google/bullhead/bullhead:7.1.2/N2G48C/4104010:userdebug/dev-keys'
+06-15 19:57:33.670 26192 26192 F DEBUG   : Revision: 'rev_1.0'
+06-15 19:57:33.670 26192 26192 F DEBUG   : ABI: 'arm'
+06-15 19:57:33.670 26192 26192 F DEBUG   : pid: 12736, tid: 12761, name: synthetic_thread  >>> synthetic_process_1 <<<
+06-15 19:57:33.670 26192 26192 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
+06-15 19:57:33.670 26192 26192 F DEBUG   :     r0 00000000  r1 00000000  r2 0000005f  r3 00000000
+06-15 19:57:33.670 26192 26192 F DEBUG   :     r4 ffffffff  r5 00000000  r6 f14f9000  r7 00000001
+06-15 19:57:33.670 26192 26192 F DEBUG   :     r8 00000004  r9 f3353114  sl f3313900  fp 00000000
+06-15 19:57:33.670 26192 26192 F DEBUG   :     ip f3bd4d88  sp f127d9c8  lr f3b9cbc5  pc f3b65af4  cpsr 60000030
+06-15 19:57:33.676 26192 26192 F DEBUG   :
+06-15 19:57:33.676 26192 26192 F DEBUG   : backtrace:
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #00 pc 00018af4  /system/lib/libc.so (strlen+71)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #01 pc 0004fbc1  /system/lib/libc.so (__strlen_chk+4)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #02 pc 0000c599  /system/lib/libutils.so (_ZN7android7String8C2EPKc+12)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #03 pc 0002fdbf  /system/lib/libaudiopolicymanagerdefault.so (_ZNK7android18HwModuleCollection19getDeviceDescriptorEjPKcS2_b+458)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #04 pc 0001de47  /system/lib/libaudiopolicymanagerdefault.so (_ZN7android18AudioPolicyManager27setDeviceConnectionStateIntEj24audio_policy_dev_state_tPKcS3_+178)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #05 pc 0000a009  /system/lib/libaudiopolicyservice.so
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #06 pc 000a01a5  /system/lib/libmedia.so (_ZN7android20BnAudioPolicyService10onTransactEjRKNS_6ParcelEPS1_j+1256)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #07 pc 000359c3  /system/lib/libbinder.so (_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j+70)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #08 pc 0003d1bb  /system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi+702)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #09 pc 0003ce07  /system/lib/libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+114)
+06-15 19:57:33.677 26192 26192 F DEBUG   :     #10 pc 0003d31b  /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+46)
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #11 pc 0004f8c5  /system/lib/libbinder.so
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #12 pc 0000e345  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140)
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #13 pc 000470b3  /system/lib/libc.so (_ZL15__pthread_startPv+22)
+06-15 19:57:33.678 26192 26192 F DEBUG   :     #14 pc 00019e3d  /system/lib/libc.so (__start_thread+6)
+06-15 19:57:33.839   934  2991 W NativeCrashListener: Couldn't find ProcessRecord for pid 12736
+06-15 19:57:33.846   934   952 I BootReceiver: Copying /data/tombstones/tombstone_01 to DropBox (SYSTEM_TOMBSTONE)
+
diff --git a/libraries/compatibility-common-util/tests/assets/x86app_process32 b/libraries/compatibility-common-util/tests/assets/x86app_process32
new file mode 100644
index 0000000..d02fcd7
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/x86app_process32
Binary files differ
diff --git a/libraries/compatibility-common-util/tests/assets/x86app_process32.txt b/libraries/compatibility-common-util/tests/assets/x86app_process32.txt
new file mode 100644
index 0000000..f0ff7fb
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/x86app_process32.txt
@@ -0,0 +1,393 @@
+ELF Header:
+  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
+  Class:                             ELF32
+  Data:                              2's complement, little endian
+  Version:                           1 (current)
+  OS/ABI:                            UNIX - System V
+  ABI Version:                       0
+  Type:                              DYN (Shared object file)
+  Machine:                           Intel 80386
+  Version:                           0x1
+  Entry point address:               0x1530
+  Start of program headers:          52 (bytes into file)
+  Start of section headers:          22140 (bytes into file)
+  Flags:                             0x0
+  Size of this header:               52 (bytes)
+  Size of program headers:           32 (bytes)
+  Number of program headers:         9
+  Size of section headers:           40 (bytes)
+  Number of section headers:         27
+  Section header string table index: 26
+
+Section Headers:
+  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
+  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
+  [ 1] .interp           PROGBITS        00000154 000154 000013 00   A  0   0  1
+  [ 2] .note.android.ide NOTE            00000168 000168 000018 00   A  0   0  4
+  [ 3] .note.gnu.build-i NOTE            00000180 000180 000020 00   A  0   0  4
+  [ 4] .dynsym           DYNSYM          000001a0 0001a0 0004c0 10   A  5   1  4
+  [ 5] .dynstr           STRTAB          00000660 000660 000718 00   A  0   0  1
+  [ 6] .gnu.hash         GNU_HASH        00000d78 000d78 000048 04   A  4   0  4
+  [ 7] .gnu.version      VERSYM          00000dc0 000dc0 000098 02   A  4   0  2
+  [ 8] .gnu.version_r    VERNEED         00000e58 000e58 000050 00   A  5   2  4
+  [ 9] .rel.dyn          REL             00000ea8 000ea8 000088 08   A  4   0  4
+  [10] .rel.plt          REL             00000f30 000f30 0001f8 08  AI  4  22  4
+  [11] .plt              PROGBITS        00001130 001130 000400 04  AX  0   0 16
+  [12] .text             PROGBITS        00001530 001530 002125 00  AX  0   0 16
+  [13] .rodata           PROGBITS        00003655 003655 000484 00   A  0   0  1
+  [14] .eh_frame         PROGBITS        00003adc 003adc 000488 00   A  0   0  4
+  [15] .eh_frame_hdr     PROGBITS        00003f64 003f64 00012c 00   A  0   0  4
+  [16] .preinit_array    PREINIT_ARRAY   00005d34 004d34 000008 04  WA  0   0  4
+  [17] .init_array       INIT_ARRAY      00005d3c 004d3c 00000c 04  WA  0   0  4
+  [18] .fini_array       FINI_ARRAY      00005d48 004d48 000008 04  WA  0   0  4
+  [19] .data.rel.ro      PROGBITS        00005d50 004d50 000048 00  WA  0   0  4
+  [20] .dynamic          DYNAMIC         00005d98 004d98 000158 08  WA  5   0  4
+  [21] .got              PROGBITS        00005ef0 004ef0 000008 00  WA  0   0  4
+  [22] .got.plt          PROGBITS        00005ef8 004ef8 000108 00  WA  0   0  4
+  [23] .bss              NOBITS          00006000 005000 000e90 00  WA  0   0  4
+  [24] .note.gnu.gold-ve NOTE            00000000 005000 00001c 00      0   0  4
+  [25] .gnu_debugdata    PROGBITS        00000000 00501c 000540 00      0   0  1
+  [26] .shstrtab         STRTAB          00000000 00555c 00011e 00      0   0  1
+Key to Flags:
+  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
+  L (link order), O (extra OS processing required), G (group), T (TLS),
+  C (compressed), x (unknown), o (OS specific), E (exclude),
+  p (processor specific)
+
+There are no section groups in this file.
+
+Program Headers:
+  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
+  PHDR           0x000034 0x00000034 0x00000034 0x00120 0x00120 R   0x4
+  INTERP         0x000154 0x00000154 0x00000154 0x00013 0x00013 R   0x1
+      [Requesting program interpreter: /system/bin/linker]
+  LOAD           0x000000 0x00000000 0x00000000 0x04090 0x04090 R E 0x1000
+  LOAD           0x004d34 0x00005d34 0x00005d34 0x002cc 0x0115c RW  0x1000
+  DYNAMIC        0x004d98 0x00005d98 0x00005d98 0x00158 0x00158 RW  0x4
+  NOTE           0x000168 0x00000168 0x00000168 0x00038 0x00038 R   0x4
+  GNU_EH_FRAME   0x003f64 0x00003f64 0x00003f64 0x0012c 0x0012c R   0x4
+  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
+  GNU_RELRO      0x004d34 0x00005d34 0x00005d34 0x002cc 0x002cc RW  0x4
+
+ Section to Segment mapping:
+  Segment Sections...
+   00     
+   01     .interp 
+   02     .interp .note.android.ident .note.gnu.build-id .dynsym .dynstr .gnu.hash .gnu.version .gnu.version_r .rel.dyn .rel.plt .plt .text .rodata .eh_frame .eh_frame_hdr 
+   03     .preinit_array .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .bss 
+   04     .dynamic 
+   05     .note.android.ident .note.gnu.build-id 
+   06     .eh_frame_hdr 
+   07     
+   08     .preinit_array .init_array .fini_array .data.rel.ro .dynamic .got .got.plt 
+
+Dynamic section at offset 0x4d98 contains 38 entries:
+  Tag        Type                         Name/Value
+ 0x00000003 (PLTGOT)                     0x5ef8
+ 0x00000002 (PLTRELSZ)                   504 (bytes)
+ 0x00000017 (JMPREL)                     0xf30
+ 0x00000014 (PLTREL)                     REL
+ 0x00000011 (REL)                        0xea8
+ 0x00000012 (RELSZ)                      136 (bytes)
+ 0x00000013 (RELENT)                     8 (bytes)
+ 0x6ffffffa (RELCOUNT)                   15
+ 0x00000015 (DEBUG)                      0x0
+ 0x00000006 (SYMTAB)                     0x1a0
+ 0x0000000b (SYMENT)                     16 (bytes)
+ 0x00000005 (STRTAB)                     0x660
+ 0x0000000a (STRSZ)                      1816 (bytes)
+ 0x6ffffef5 (GNU_HASH)                   0xd78
+ 0x00000001 (NEEDED)                     Shared library: [libandroid_runtime.so]
+ 0x00000001 (NEEDED)                     Shared library: [libbinder.so]
+ 0x00000001 (NEEDED)                     Shared library: [libcutils.so]
+ 0x00000001 (NEEDED)                     Shared library: [libhwbinder.so]
+ 0x00000001 (NEEDED)                     Shared library: [liblog.so]
+ 0x00000001 (NEEDED)                     Shared library: [libnativeloader.so]
+ 0x00000001 (NEEDED)                     Shared library: [libutils.so]
+ 0x00000001 (NEEDED)                     Shared library: [libwilhelm.so]
+ 0x00000001 (NEEDED)                     Shared library: [libc++.so]
+ 0x00000001 (NEEDED)                     Shared library: [libc.so]
+ 0x00000001 (NEEDED)                     Shared library: [libm.so]
+ 0x00000001 (NEEDED)                     Shared library: [libdl.so]
+ 0x00000020 (PREINIT_ARRAY)              0x5d34
+ 0x00000021 (PREINIT_ARRAYSZ)            0x8
+ 0x00000019 (INIT_ARRAY)                 0x5d3c
+ 0x0000001b (INIT_ARRAYSZ)               12 (bytes)
+ 0x0000001a (FINI_ARRAY)                 0x5d48
+ 0x0000001c (FINI_ARRAYSZ)               8 (bytes)
+ 0x0000001e (FLAGS)                      BIND_NOW
+ 0x6ffffffb (FLAGS_1)                    Flags: NOW
+ 0x6ffffff0 (VERSYM)                     0xdc0
+ 0x6ffffffe (VERNEED)                    0xe58
+ 0x6fffffff (VERNEEDNUM)                 2
+ 0x00000000 (NULL)                       0x0
+
+Relocation section '.rel.dyn' at offset 0xea8 contains 17 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+00005d40  00000008 R_386_RELATIVE   
+00005d58  00000008 R_386_RELATIVE   
+00005d5c  00000008 R_386_RELATIVE   
+00005d60  00000008 R_386_RELATIVE   
+00005d64  00000008 R_386_RELATIVE   
+00005d68  00000008 R_386_RELATIVE   
+00005d6c  00000008 R_386_RELATIVE   
+00005d78  00000008 R_386_RELATIVE   
+00005d7c  00000008 R_386_RELATIVE   
+00005d80  00000008 R_386_RELATIVE   
+00005d84  00000008 R_386_RELATIVE   
+00005d88  00000008 R_386_RELATIVE   
+00005d8c  00000008 R_386_RELATIVE   
+00005d90  00000008 R_386_RELATIVE   
+00005d94  00000008 R_386_RELATIVE   
+00005ef4  00001706 R_386_GLOB_DAT    00000000   stderr@LIBC
+00005ef0  00003a06 R_386_GLOB_DAT    00000000   __stack_chk_guard@LIBC
+
+Relocation section '.rel.plt' at offset 0xf30 contains 63 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+00005f04  00000307 R_386_JUMP_SLOT   00000000   __libc_init@LIBC
+00005f08  00000407 R_386_JUMP_SLOT   00000000   __register_atfork@LIBC
+00005f0c  00001d07 R_386_JUMP_SLOT   00000000   strlen@LIBC
+00005f10  00001607 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005f14  00002907 R_386_JUMP_SLOT   00000000   _ZN7android7String8C1E
+00005f18  00000a07 R_386_JUMP_SLOT   00000000   _ZN7android10VectorImp
+00005f1c  00001207 R_386_JUMP_SLOT   00000000   strcmp@LIBC
+00005f20  00001407 R_386_JUMP_SLOT   00000000   strdup@LIBC
+00005f24  00001507 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005f28  00001907 R_386_JUMP_SLOT   00000000   strncmp@LIBC
+00005f2c  00001f07 R_386_JUMP_SLOT   00000000   _ZN7android7String85se
+00005f30  00003407 R_386_JUMP_SLOT   00000000   _ZNK7android7String86l
+00005f34  00002c07 R_386_JUMP_SLOT   00000000   getenv@LIBC
+00005f38  00002807 R_386_JUMP_SLOT   00000000   mkdir@LIBC
+00005f3c  00003907 R_386_JUMP_SLOT   00000000   __errno@LIBC
+00005f40  00001e07 R_386_JUMP_SLOT   00000000   chown@LIBC
+00005f44  00002407 R_386_JUMP_SLOT   00000000   chmod@LIBC
+00005f48  00002507 R_386_JUMP_SLOT   00000000   _ZN7android7String8C1E
+00005f4c  00000907 R_386_JUMP_SLOT   00000000   _ZN7android10VectorImp
+00005f50  00002b07 R_386_JUMP_SLOT   00000000   _ZN7android7String8D1E
+00005f54  00003b07 R_386_JUMP_SLOT   00000000   property_get
+00005f58  00002307 R_386_JUMP_SLOT   00000000   _ZN7android7String86ap
+00005f5c  00002107 R_386_JUMP_SLOT   00000000   _ZN7android7String85se
+00005f60  00001307 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005f64  00001007 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005f68  00000807 R_386_JUMP_SLOT   00000000   _ZN7android10VectorImp
+00005f6c  00000b07 R_386_JUMP_SLOT   00000000   _ZN7android10VectorImp
+00005f70  00001807 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005f74  00000607 R_386_JUMP_SLOT   00000000   __stack_chk_fail@LIBC
+00005f78  00002a07 R_386_JUMP_SLOT   00000000   fwrite@LIBC
+00005f7c  00003607 R_386_JUMP_SLOT   00000000   __android_log_assert
+00005f80  00001c07 R_386_JUMP_SLOT   00000000   strerror@LIBC
+00005f84  00003507 R_386_JUMP_SLOT   00000000   _ZdlPv
+00005f88  00000f07 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005f8c  00003807 R_386_JUMP_SLOT   00000000   __android_log_print
+00005f90  00002007 R_386_JUMP_SLOT   00000000   free@LIBC
+00005f94  00000d07 R_386_JUMP_SLOT   00000000   _ZN7android12ProcessSt
+00005f98  00000c07 R_386_JUMP_SLOT   00000000   _ZN7android12ProcessSt
+00005f9c  00000e07 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005fa0  00001107 R_386_JUMP_SLOT   00000000   _ZN7android14AndroidRu
+00005fa4  00001b07 R_386_JUMP_SLOT   00000000   _ZN7android14IPCThread
+00005fa8  00001a07 R_386_JUMP_SLOT   00000000   _ZN7android14IPCThread
+00005fac  00002f07 R_386_JUMP_SLOT   00000000   _ZN7android8hardware14
+00005fb0  00002d07 R_386_JUMP_SLOT   00000000   _ZN7android8hardware14
+00005fb4  00003307 R_386_JUMP_SLOT   00000000   _ZNK7android7RefBase9d
+00005fb8  00002207 R_386_JUMP_SLOT   00000000   __vsnprintf_chk@LIBC
+00005fbc  00002707 R_386_JUMP_SLOT   00000000   _ZN7android7String8C1E
+00005fc0  00002607 R_386_JUMP_SLOT   00000000   memmove@LIBC
+00005fc4  00003c07 R_386_JUMP_SLOT   00000000   _ZNSt3__111__call_once
+00005fc8  00002e07 R_386_JUMP_SLOT   00000000   pthread_getspecific@LIBC
+00005fcc  00004007 R_386_JUMP_SLOT   00000000   sigemptyset64@LIBC_P
+00005fd0  00004207 R_386_JUMP_SLOT   00000000   sigismember64@LIBC_P
+00005fd4  00003e07 R_386_JUMP_SLOT   00000000   sigaddset64@LIBC_P
+00005fd8  00003207 R_386_JUMP_SLOT   00000000   pthread_setspecific@LIBC
+00005fdc  00003707 R_386_JUMP_SLOT   00000000   abort@LIBC
+00005fe0  00003d07 R_386_JUMP_SLOT   00000000   __android_log_write
+00005fe4  00000207 R_386_JUMP_SLOT   00000000   sigemptyset@LIBC
+00005fe8  00000707 R_386_JUMP_SLOT   00000000   sigismember@LIBC
+00005fec  00000507 R_386_JUMP_SLOT   00000000   sigdelset@LIBC
+00005ff0  00003f07 R_386_JUMP_SLOT   00000000   sigdelset64@LIBC_P
+00005ff4  00004107 R_386_JUMP_SLOT   00000000   sigfillset64@LIBC_P
+00005ff8  00003007 R_386_JUMP_SLOT   00000000   pthread_key_create@LIBC
+00005ffc  00003107 R_386_JUMP_SLOT   00000000   dlsym@LIBC
+
+The decoding of unwind sections for machine type Intel 80386 is not currently supported.
+
+Symbol table '.dynsym' contains 76 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 00000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@LIBC (2)
+     2: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigemptyset@LIBC (2)
+     3: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_init@LIBC (2)
+     4: 00000000     0 FUNC    GLOBAL DEFAULT  UND __register_atfork@LIBC (2)
+     5: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigdelset@LIBC (2)
+     6: 00000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@LIBC (2)
+     7: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigismember@LIBC (2)
+     8: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImpl13
+     9: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImpl3a
+    10: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImplC2
+    11: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImplD2
+    12: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android12ProcessState
+    13: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android12ProcessState
+    14: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    15: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    16: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    17: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    18: 00000000     0 FUNC    GLOBAL DEFAULT  UND strcmp@LIBC (2)
+    19: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    20: 00000000     0 FUNC    GLOBAL DEFAULT  UND strdup@LIBC (2)
+    21: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    22: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    23: 00000000     0 OBJECT  GLOBAL DEFAULT  UND stderr@LIBC (2)
+    24: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    25: 00000000     0 FUNC    GLOBAL DEFAULT  UND strncmp@LIBC (2)
+    26: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14IPCThreadSta
+    27: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14IPCThreadSta
+    28: 00000000     0 FUNC    GLOBAL DEFAULT  UND strerror@LIBC (2)
+    29: 00000000     0 FUNC    GLOBAL DEFAULT  UND strlen@LIBC (2)
+    30: 00000000     0 FUNC    GLOBAL DEFAULT  UND chown@LIBC (2)
+    31: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String85setTo
+    32: 00000000     0 FUNC    GLOBAL DEFAULT  UND free@LIBC (2)
+    33: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String85setTo
+    34: 00000000     0 FUNC    GLOBAL DEFAULT  UND __vsnprintf_chk@LIBC (2)
+    35: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String86appen
+    36: 00000000     0 FUNC    GLOBAL DEFAULT  UND chmod@LIBC (2)
+    37: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8C1EPKc
+    38: 00000000     0 FUNC    GLOBAL DEFAULT  UND memmove@LIBC (2)
+    39: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8C1ERKS
+    40: 00000000     0 FUNC    GLOBAL DEFAULT  UND mkdir@LIBC (2)
+    41: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8C1Ev
+    42: 00000000     0 FUNC    GLOBAL DEFAULT  UND fwrite@LIBC (2)
+    43: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8D1Ev
+    44: 00000000     0 FUNC    GLOBAL DEFAULT  UND getenv@LIBC (2)
+    45: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android8hardware14IPC
+    46: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_getspecific@LIBC (2)
+    47: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android8hardware14IPC
+    48: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_key_create@LIBC (2)
+    49: 00000000     0 FUNC    GLOBAL DEFAULT  UND dlsym@LIBC (4)
+    50: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_setspecific@LIBC (2)
+    51: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZNK7android7RefBase9decS
+    52: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZNK7android7String86leng
+    53: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZdlPv
+    54: 00000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_assert
+    55: 00000000     0 FUNC    GLOBAL DEFAULT  UND abort@LIBC (2)
+    56: 00000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_print
+    57: 00000000     0 FUNC    GLOBAL DEFAULT  UND __errno@LIBC (2)
+    58: 00000000     0 OBJECT  GLOBAL DEFAULT  UND __stack_chk_guard@LIBC (2)
+    59: 00000000     0 FUNC    GLOBAL DEFAULT  UND property_get
+    60: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt3__111__call_onceERV
+    61: 00000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_write
+    62: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigaddset64@LIBC_P (3)
+    63: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigdelset64@LIBC_P (3)
+    64: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigemptyset64@LIBC_P (3)
+    65: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigfillset64@LIBC_P (3)
+    66: 00000000     0 FUNC    GLOBAL DEFAULT  UND sigismember64@LIBC_P (3)
+    67: 00003150   334 FUNC    GLOBAL PROTECTED   12 AddSpecialSignalHandlerFn
+    68: 00002d20   134 FUNC    GLOBAL PROTECTED   12 bsd_signal
+    69: 00002940   359 FUNC    GLOBAL PROTECTED   12 sigaction
+    70: 00002ab0   265 FUNC    GLOBAL PROTECTED   12 sigaction64
+    71: 00002db0   144 FUNC    GLOBAL PROTECTED   12 sigprocmask
+    72: 00002f80   144 FUNC    GLOBAL PROTECTED   12 sigprocmask64
+    73: 00002bc0   351 FUNC    GLOBAL PROTECTED   12 signal
+    74: 000032a0   244 FUNC    GLOBAL PROTECTED   12 RemoveSpecialSignalHandle
+    75: 000033a0   282 FUNC    GLOBAL PROTECTED   12 EnsureFrontOfChain
+
+Histogram for `.gnu.hash' bucket list length (total of 3 buckets):
+ Length  Number     % of total  Coverage
+      0  0          (  0.0%)
+      1  1          ( 33.3%)     11.1%
+      2  1          ( 33.3%)     33.3%
+      3  0          (  0.0%)     33.3%
+      4  0          (  0.0%)     33.3%
+      5  0          (  0.0%)     33.3%
+      6  1          ( 33.3%)    100.0%
+
+Version symbols section '.gnu.version' contains 76 entries:
+ Addr: 0000000000000dc0  Offset: 0x000dc0  Link: 4 (.dynsym)
+  000:   0 (*local*)       2 (LIBC)          2 (LIBC)          2 (LIBC)       
+  004:   2 (LIBC)          2 (LIBC)          2 (LIBC)          2 (LIBC)       
+  008:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  00c:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  010:   0 (*local*)       0 (*local*)       2 (LIBC)          0 (*local*)    
+  014:   2 (LIBC)          0 (*local*)       0 (*local*)       2 (LIBC)       
+  018:   0 (*local*)       2 (LIBC)          0 (*local*)       0 (*local*)    
+  01c:   2 (LIBC)          2 (LIBC)          2 (LIBC)          0 (*local*)    
+  020:   2 (LIBC)          0 (*local*)       2 (LIBC)          0 (*local*)    
+  024:   2 (LIBC)          0 (*local*)       2 (LIBC)          0 (*local*)    
+  028:   2 (LIBC)          0 (*local*)       2 (LIBC)          0 (*local*)    
+  02c:   2 (LIBC)          0 (*local*)       2 (LIBC)          0 (*local*)    
+  030:   2 (LIBC)          4 (LIBC)          2 (LIBC)          0 (*local*)    
+  034:   0 (*local*)       0 (*local*)       0 (*local*)       2 (LIBC)       
+  038:   0 (*local*)       2 (LIBC)          2 (LIBC)          0 (*local*)    
+  03c:   0 (*local*)       0 (*local*)       3 (LIBC_P)        3 (LIBC_P)     
+  040:   3 (LIBC_P)        3 (LIBC_P)        3 (LIBC_P)        1 (*global*)   
+  044:   1 (*global*)      1 (*global*)      1 (*global*)      1 (*global*)   
+  048:   1 (*global*)      1 (*global*)      1 (*global*)      1 (*global*)   
+
+Version needs section '.gnu.version_r' contains 2 entries:
+ Addr: 0x0000000000000e58  Offset: 0x000e58  Link: 5 (.dynstr)
+  000000: Version: 1  File: libc.so  Cnt: 2
+  0x0010:   Name: LIBC  Flags: none  Version: 2
+  0x0020:   Name: LIBC_P  Flags: none  Version: 3
+  0x0030: Version: 1  File: libdl.so  Cnt: 1
+  0x0040:   Name: LIBC  Flags: none  Version: 4
+
+String dump of section '.rodata':
+  [     0]  -cp
+  [     4]  -classpath
+  [     f]  --zygote
+  [    18]  --start-system-server
+  [    2e]  --application
+  [    3c]  --nice-name=
+  [    49]  --
+  [    4c]  application
+  [    58]  tool
+  [    5d]  start-system-server
+  [    71]  appproc
+  [    79]  app_process: Unable to determine ABI list from property %s.
+  [    b5]  --abi-list=
+  [    c1]  com.android.internal.os.ZygoteInit
+  [    e4]  com.android.internal.os.RuntimeInit
+  [   108]  Error: no class name or --zygote supplied.^J
+  [   134]  app_process: no class name or --zygote supplied.
+  [   165]  ERROR: could not find class '%s'^J
+  [   187]  ANDROID_DATA
+  [   194]  androidRoot == NULL
+  [   1a8]  ANDROID_DATA environment variable unset
+  [   1d0]  %s/dalvik-cache/%s
+  [   1e3]  (numChars >= PATH_MAX || numChars < 0)
+  [   20a]  Error constructing dalvik cache : %s
+  [   22f]  (result < 0 && errno != EEXIST)
+  [   24f]  Error creating cache dir %s : %s
+  [   270]  (result < 0)
+  [   27d]  Error changing dalvik-cache ownership : %s
+  [   2a8]  Error changing dalvik-cache permissions : %s
+  [   2d5]  Usage: app_process [java-options] cmd-dir start-class-name [options]^J
+  [   31b]  exiting due to SIG_DFL handler for signal %d
+  [   348]  Invalid signal %d
+  [   35a]  Warning: Unexpected sigaction action found %p^J
+  [   389]  failed to create sigchain pthread key: %s
+  [   3b3]  libsigchain
+  [   3bf]  too many special signal handlers
+  [   3e0]  failed to find special handler to remove
+  [   409]  sigaction
+  [   413]  sigprocmask
+  [   41f]  sigaction64
+  [   42b]  sigprocmask64
+  [   439]  Unable to find next %s in signal chain
+  [   460]  zygote
+  [   467]  ro.product.cpu.abilist32
+  [   480]  x86
+
+
+Displaying notes found in: .note.android.ident
+  Owner                 Data size	Description
+  Android              0x00000004	NT_VERSION (version)
+   description data: 1c 00 00 00 
+
+Displaying notes found in: .note.gnu.build-id
+  Owner                 Data size	Description
+  GNU                  0x00000010	NT_GNU_BUILD_ID (unique build ID bitstring)
+    Build ID: 2bb7d95d208fcf19b7cca6e41929753b
+
+Displaying notes found in: .note.gnu.gold-version
+  Owner                 Data size	Description
+  GNU                  0x00000009	NT_GNU_GOLD_VERSION (gold version)
+    Version: gold 1.12
diff --git a/libraries/compatibility-common-util/tests/assets/x86app_process64 b/libraries/compatibility-common-util/tests/assets/x86app_process64
new file mode 100644
index 0000000..4fbe6eb
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/x86app_process64
Binary files differ
diff --git a/libraries/compatibility-common-util/tests/assets/x86app_process64.txt b/libraries/compatibility-common-util/tests/assets/x86app_process64.txt
new file mode 100644
index 0000000..a517cbe
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/assets/x86app_process64.txt
@@ -0,0 +1,422 @@
+ELF Header:
+  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
+  Class:                             ELF64
+  Data:                              2's complement, little endian
+  Version:                           1 (current)
+  OS/ABI:                            UNIX - System V
+  ABI Version:                       0
+  Type:                              DYN (Shared object file)
+  Machine:                           Advanced Micro Devices X86-64
+  Version:                           0x1
+  Entry point address:               0x1c50
+  Start of program headers:          64 (bytes into file)
+  Start of section headers:          22168 (bytes into file)
+  Flags:                             0x0
+  Size of this header:               64 (bytes)
+  Size of program headers:           56 (bytes)
+  Number of program headers:         9
+  Size of section headers:           64 (bytes)
+  Number of section headers:         27
+  Section header string table index: 26
+
+Section Headers:
+  [Nr] Name              Type             Address           Offset
+       Size              EntSize          Flags  Link  Info  Align
+  [ 0]                   NULL             0000000000000000  00000000
+       0000000000000000  0000000000000000           0     0     0
+  [ 1] .interp           PROGBITS         0000000000000238  00000238
+       0000000000000015  0000000000000000   A       0     0     1
+  [ 2] .note.android.ide NOTE             0000000000000250  00000250
+       0000000000000018  0000000000000000   A       0     0     4
+  [ 3] .note.gnu.build-i NOTE             0000000000000268  00000268
+       0000000000000020  0000000000000000   A       0     0     4
+  [ 4] .dynsym           DYNSYM           0000000000000288  00000288
+       00000000000006a8  0000000000000018   A       5     1     8
+  [ 5] .dynstr           STRTAB           0000000000000930  00000930
+       00000000000006d1  0000000000000000   A       0     0     1
+  [ 6] .gnu.hash         GNU_HASH         0000000000001008  00001008
+       0000000000000044  0000000000000000   A       4     0     8
+  [ 7] .gnu.version      VERSYM           000000000000104c  0000104c
+       000000000000008e  0000000000000002   A       4     0     2
+  [ 8] .gnu.version_r    VERNEED          00000000000010dc  000010dc
+       0000000000000050  0000000000000000   A       5     2     4
+  [ 9] .rela.dyn         RELA             0000000000001130  00001130
+       00000000000001b0  0000000000000018   A       4     0     8
+  [10] .rela.plt         RELA             00000000000012e0  000012e0
+       00000000000005a0  0000000000000018  AI       4    22     8
+  [11] .plt              PROGBITS         0000000000001880  00001880
+       00000000000003d0  0000000000000010  AX       0     0     16
+  [12] .text             PROGBITS         0000000000001c50  00001c50
+       0000000000001d8f  0000000000000000  AX       0     0     16
+  [13] .rodata           PROGBITS         00000000000039e0  000039e0
+       0000000000000490  0000000000000000   A       0     0     16
+  [14] .eh_frame         PROGBITS         0000000000003e70  00003e70
+       0000000000000494  0000000000000000   A       0     0     8
+  [15] .eh_frame_hdr     PROGBITS         0000000000004304  00004304
+       000000000000011c  0000000000000000   A       0     0     4
+  [16] .preinit_array    PREINIT_ARRAY    0000000000005a78  00004a78
+       0000000000000010  0000000000000008  WA       0     0     8
+  [17] .init_array       INIT_ARRAY       0000000000005a88  00004a88
+       0000000000000018  0000000000000008  WA       0     0     8
+  [18] .fini_array       FINI_ARRAY       0000000000005aa0  00004aa0
+       0000000000000010  0000000000000008  WA       0     0     8
+  [19] .data.rel.ro      PROGBITS         0000000000005ab0  00004ab0
+       0000000000000090  0000000000000000  WA       0     0     8
+  [20] .dynamic          DYNAMIC          0000000000005b40  00004b40
+       00000000000002b0  0000000000000010  WA       5     0     8
+  [21] .got              PROGBITS         0000000000005df0  00004df0
+       0000000000000018  0000000000000000  WA       0     0     8
+  [22] .got.plt          PROGBITS         0000000000005e08  00004e08
+       00000000000001f8  0000000000000000  WA       0     0     8
+  [23] .bss              NOBITS           0000000000006000  00005000
+       00000000000016f0  0000000000000000  WA       0     0     16
+  [24] .note.gnu.gold-ve NOTE             0000000000000000  00005000
+       000000000000001c  0000000000000000           0     0     4
+  [25] .gnu_debugdata    PROGBITS         0000000000000000  0000501c
+       0000000000000558  0000000000000000           0     0     1
+  [26] .shstrtab         STRTAB           0000000000000000  00005574
+       0000000000000120  0000000000000000           0     0     1
+Key to Flags:
+  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
+  L (link order), O (extra OS processing required), G (group), T (TLS),
+  C (compressed), x (unknown), o (OS specific), E (exclude),
+  l (large), p (processor specific)
+
+There are no section groups in this file.
+
+Program Headers:
+  Type           Offset             VirtAddr           PhysAddr
+                 FileSiz            MemSiz              Flags  Align
+  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
+                 0x00000000000001f8 0x00000000000001f8  R      0x8
+  INTERP         0x0000000000000238 0x0000000000000238 0x0000000000000238
+                 0x0000000000000015 0x0000000000000015  R      0x1
+      [Requesting program interpreter: /system/bin/linker64]
+  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
+                 0x0000000000004420 0x0000000000004420  R E    0x1000
+  LOAD           0x0000000000004a78 0x0000000000005a78 0x0000000000005a78
+                 0x0000000000000588 0x0000000000001c78  RW     0x1000
+  DYNAMIC        0x0000000000004b40 0x0000000000005b40 0x0000000000005b40
+                 0x00000000000002b0 0x00000000000002b0  RW     0x8
+  NOTE           0x0000000000000250 0x0000000000000250 0x0000000000000250
+                 0x0000000000000038 0x0000000000000038  R      0x4
+  GNU_EH_FRAME   0x0000000000004304 0x0000000000004304 0x0000000000004304
+                 0x000000000000011c 0x000000000000011c  R      0x4
+  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
+                 0x0000000000000000 0x0000000000000000  RW     0x10
+  GNU_RELRO      0x0000000000004a78 0x0000000000005a78 0x0000000000005a78
+                 0x0000000000000588 0x0000000000000588  RW     0x8
+
+ Section to Segment mapping:
+  Segment Sections...
+   00     
+   01     .interp 
+   02     .interp .note.android.ident .note.gnu.build-id .dynsym .dynstr .gnu.hash .gnu.version .gnu.version_r .rela.dyn .rela.plt .plt .text .rodata .eh_frame .eh_frame_hdr 
+   03     .preinit_array .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .bss 
+   04     .dynamic 
+   05     .note.android.ident .note.gnu.build-id 
+   06     .eh_frame_hdr 
+   07     
+   08     .preinit_array .init_array .fini_array .data.rel.ro .dynamic .got .got.plt 
+
+Dynamic section at offset 0x4b40 contains 38 entries:
+  Tag        Type                         Name/Value
+ 0x0000000000000003 (PLTGOT)             0x5e08
+ 0x0000000000000002 (PLTRELSZ)           1440 (bytes)
+ 0x0000000000000017 (JMPREL)             0x12e0
+ 0x0000000000000014 (PLTREL)             RELA
+ 0x0000000000000007 (RELA)               0x1130
+ 0x0000000000000008 (RELASZ)             432 (bytes)
+ 0x0000000000000009 (RELAENT)            24 (bytes)
+ 0x000000006ffffff9 (RELACOUNT)          17
+ 0x0000000000000015 (DEBUG)              0x0
+ 0x0000000000000006 (SYMTAB)             0x288
+ 0x000000000000000b (SYMENT)             24 (bytes)
+ 0x0000000000000005 (STRTAB)             0x930
+ 0x000000000000000a (STRSZ)              1745 (bytes)
+ 0x000000006ffffef5 (GNU_HASH)           0x1008
+ 0x0000000000000001 (NEEDED)             Shared library: [libandroid_runtime.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libbinder.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libcutils.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libhwbinder.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [liblog.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libnativeloader.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libutils.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libwilhelm.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libc++.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
+ 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
+ 0x0000000000000020 (PREINIT_ARRAY)      0x5a78
+ 0x0000000000000021 (PREINIT_ARRAYSZ)    0x10
+ 0x0000000000000019 (INIT_ARRAY)         0x5a88
+ 0x000000000000001b (INIT_ARRAYSZ)       24 (bytes)
+ 0x000000000000001a (FINI_ARRAY)         0x5aa0
+ 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
+ 0x000000000000001e (FLAGS)              BIND_NOW
+ 0x000000006ffffffb (FLAGS_1)            Flags: NOW
+ 0x000000006ffffff0 (VERSYM)             0x104c
+ 0x000000006ffffffe (VERNEED)            0x10dc
+ 0x000000006fffffff (VERNEEDNUM)         2
+ 0x0000000000000000 (NULL)               0x0
+
+Relocation section '.rela.dyn' at offset 0x1130 contains 18 entries:
+  Offset          Info           Type           Sym. Value    Sym. Name + Addend
+000000005a90  000000000008 R_X86_64_RELATIVE                    28e0
+000000005ac0  000000000008 R_X86_64_RELATIVE                    2450
+000000005ac8  000000000008 R_X86_64_RELATIVE                    24a0
+000000005ad0  000000000008 R_X86_64_RELATIVE                    24f0
+000000005ad8  000000000008 R_X86_64_RELATIVE                    2580
+000000005ae0  000000000008 R_X86_64_RELATIVE                    2620
+000000005ae8  000000000008 R_X86_64_RELATIVE                    2680
+000000005b00  000000000008 R_X86_64_RELATIVE                    2430
+000000005b08  000000000008 R_X86_64_RELATIVE                    2790
+000000005b10  000000000008 R_X86_64_RELATIVE                    27c0
+000000005b18  000000000008 R_X86_64_RELATIVE                    27f0
+000000005b20  000000000008 R_X86_64_RELATIVE                    2820
+000000005b28  000000000008 R_X86_64_RELATIVE                    2860
+000000005b30  000000000008 R_X86_64_RELATIVE                    28a0
+000000005b38  000000000008 R_X86_64_RELATIVE                    28c0
+000000005df0  000000000008 R_X86_64_RELATIVE                    5a88
+000000005df8  000000000008 R_X86_64_RELATIVE                    5a78
+000000005e00  001900000006 R_X86_64_GLOB_DAT 0000000000000000 stderr@LIBC + 0
+
+Relocation section '.rela.plt' at offset 0x12e0 contains 60 entries:
+  Offset          Info           Type           Sym. Value    Sym. Name + Addend
+000000005e20  000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_init@LIBC + 0
+000000005e28  000300000007 R_X86_64_JUMP_SLO 0000000000000000 __register_atfork@LIBC + 0
+000000005e30  002000000007 R_X86_64_JUMP_SLO 0000000000000000 strlen@LIBC + 0
+000000005e38  001000000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005e40  002300000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android7String8C1E + 0
+000000005e48  000600000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android10VectorImp + 0
+000000005e50  001800000007 R_X86_64_JUMP_SLO 0000000000000000 strcmp@LIBC + 0
+000000005e58  002400000007 R_X86_64_JUMP_SLO 0000000000000000 strdup@LIBC + 0
+000000005e60  000f00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005e68  001e00000007 R_X86_64_JUMP_SLO 0000000000000000 strncmp@LIBC + 0
+000000005e70  001a00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android7String85se + 0
+000000005e78  002c00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZNK7android7String86l + 0
+000000005e80  001300000007 R_X86_64_JUMP_SLO 0000000000000000 getenv@LIBC + 0
+000000005e88  001c00000007 R_X86_64_JUMP_SLO 0000000000000000 mkdir@LIBC + 0
+000000005e90  003400000007 R_X86_64_JUMP_SLO 0000000000000000 __errno@LIBC + 0
+000000005e98  003a00000007 R_X86_64_JUMP_SLO 0000000000000000 chown@LIBC + 0
+000000005ea0  003800000007 R_X86_64_JUMP_SLO 0000000000000000 chmod@LIBC + 0
+000000005ea8  001f00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android7String8C1E + 0
+000000005eb0  000500000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android10VectorImp + 0
+000000005eb8  002500000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android7String8D1E + 0
+000000005ec0  003b00000007 R_X86_64_JUMP_SLO 0000000000000000 property_get + 0
+000000005ec8  001d00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android7String86ap + 0
+000000005ed0  001b00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android7String85se + 0
+000000005ed8  000e00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005ee0  000c00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005ee8  000400000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android10VectorImp + 0
+000000005ef0  000700000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android10VectorImp + 0
+000000005ef8  001200000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005f00  003500000007 R_X86_64_JUMP_SLO 0000000000000000 __stack_chk_fail@LIBC + 0
+000000005f08  001500000007 R_X86_64_JUMP_SLO 0000000000000000 fwrite@LIBC + 0
+000000005f10  003200000007 R_X86_64_JUMP_SLO 0000000000000000 __android_log_assert + 0
+000000005f18  002200000007 R_X86_64_JUMP_SLO 0000000000000000 strerror@LIBC + 0
+000000005f20  003000000007 R_X86_64_JUMP_SLO 0000000000000000 _ZdlPv + 0
+000000005f28  000b00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005f30  003300000007 R_X86_64_JUMP_SLO 0000000000000000 __android_log_print + 0
+000000005f38  001700000007 R_X86_64_JUMP_SLO 0000000000000000 free@LIBC + 0
+000000005f40  000900000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android12ProcessSt + 0
+000000005f48  000800000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android12ProcessSt + 0
+000000005f50  000a00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005f58  000d00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14AndroidRu + 0
+000000005f60  001600000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14IPCThread + 0
+000000005f68  001400000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android14IPCThread + 0
+000000005f70  002700000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android8hardware14 + 0
+000000005f78  002600000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android8hardware14 + 0
+000000005f80  002a00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZNK7android7RefBase9d + 0
+000000005f88  003700000007 R_X86_64_JUMP_SLO 0000000000000000 __vsnprintf_chk@LIBC + 0
+000000005f90  002100000007 R_X86_64_JUMP_SLO 0000000000000000 _ZN7android7String8C1E + 0
+000000005f98  001100000007 R_X86_64_JUMP_SLO 0000000000000000 memmove@LIBC + 0
+000000005fa0  003c00000007 R_X86_64_JUMP_SLO 0000000000000000 _ZNSt3__111__call_once + 0
+000000005fa8  002d00000007 R_X86_64_JUMP_SLO 0000000000000000 pthread_getspecific@LIBC + 0
+000000005fb0  003900000007 R_X86_64_JUMP_SLO 0000000000000000 sigemptyset@LIBC + 0
+000000005fb8  003600000007 R_X86_64_JUMP_SLO 0000000000000000 sigismember@LIBC + 0
+000000005fc0  003100000007 R_X86_64_JUMP_SLO 0000000000000000 sigaddset@LIBC + 0
+000000005fc8  002900000007 R_X86_64_JUMP_SLO 0000000000000000 pthread_setspecific@LIBC + 0
+000000005fd0  002800000007 R_X86_64_JUMP_SLO 0000000000000000 abort@LIBC + 0
+000000005fd8  003d00000007 R_X86_64_JUMP_SLO 0000000000000000 __android_log_write + 0
+000000005fe0  002f00000007 R_X86_64_JUMP_SLO 0000000000000000 sigdelset@LIBC + 0
+000000005fe8  003e00000007 R_X86_64_JUMP_SLO 0000000000000000 sigfillset64@LIBC_P + 0
+000000005ff0  002b00000007 R_X86_64_JUMP_SLO 0000000000000000 pthread_key_create@LIBC + 0
+000000005ff8  002e00000007 R_X86_64_JUMP_SLO 0000000000000000 dlsym@LIBC + 0
+
+The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
+
+Symbol table '.dynsym' contains 71 entries:
+   Num:    Value          Size Type    Bind   Vis      Ndx Name
+     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@LIBC (2)
+     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_init@LIBC (2)
+     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __register_atfork@LIBC (2)
+     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImpl13
+     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImpl3a
+     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImplC2
+     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android10VectorImplD2
+     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android12ProcessState
+     9: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android12ProcessState
+    10: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    11: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    12: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    13: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    14: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    15: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    16: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    17: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND memmove@LIBC (2)
+    18: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14AndroidRunti
+    19: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND getenv@LIBC (2)
+    20: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14IPCThreadSta
+    21: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fwrite@LIBC (2)
+    22: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android14IPCThreadSta
+    23: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND free@LIBC (2)
+    24: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcmp@LIBC (2)
+    25: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND stderr@LIBC (2)
+    26: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String85setTo
+    27: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String85setTo
+    28: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mkdir@LIBC (2)
+    29: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String86appen
+    30: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strncmp@LIBC (2)
+    31: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8C1EPKc
+    32: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strlen@LIBC (2)
+    33: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8C1ERKS
+    34: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strerror@LIBC (2)
+    35: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8C1Ev
+    36: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strdup@LIBC (2)
+    37: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android7String8D1Ev
+    38: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android8hardware14IPC
+    39: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZN7android8hardware14IPC
+    40: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND abort@LIBC (2)
+    41: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pthread_setspecific@LIBC (2)
+    42: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNK7android7RefBase9decS
+    43: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pthread_key_create@LIBC (2)
+    44: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNK7android7String86leng
+    45: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pthread_getspecific@LIBC (2)
+    46: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND dlsym@LIBC (4)
+    47: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sigdelset@LIBC (2)
+    48: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZdlPv
+    49: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sigaddset@LIBC (2)
+    50: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_assert
+    51: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_print
+    52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno@LIBC (2)
+    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@LIBC (2)
+    54: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sigismember@LIBC (2)
+    55: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __vsnprintf_chk@LIBC (2)
+    56: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND chmod@LIBC (2)
+    57: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sigemptyset@LIBC (2)
+    58: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND chown@LIBC (2)
+    59: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND property_get
+    60: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt3__111__call_onceERV
+    61: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_write
+    62: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sigfillset64@LIBC_P (3)
+    63: 00000000000034d0   320 FUNC    GLOBAL PROTECTED   12 AddSpecialSignalHandlerFn
+    64: 0000000000002eb0   322 FUNC    GLOBAL PROTECTED   12 sigaction
+    65: 0000000000003000   287 FUNC    GLOBAL PROTECTED   12 sigaction64
+    66: 0000000000003290   135 FUNC    GLOBAL PROTECTED   12 sigprocmask
+    67: 0000000000003440   135 FUNC    GLOBAL PROTECTED   12 sigprocmask64
+    68: 0000000000003120   361 FUNC    GLOBAL PROTECTED   12 signal
+    69: 0000000000003610   254 FUNC    GLOBAL PROTECTED   12 RemoveSpecialSignalHandle
+    70: 0000000000003710   263 FUNC    GLOBAL PROTECTED   12 EnsureFrontOfChain
+
+Histogram for `.gnu.hash' bucket list length (total of 3 buckets):
+ Length  Number     % of total  Coverage
+      0  0          (  0.0%)
+      1  1          ( 33.3%)     12.5%
+      2  1          ( 33.3%)     37.5%
+      3  0          (  0.0%)     37.5%
+      4  0          (  0.0%)     37.5%
+      5  1          ( 33.3%)    100.0%
+
+Version symbols section '.gnu.version' contains 71 entries:
+ Addr: 000000000000104c  Offset: 0x00104c  Link: 4 (.dynsym)
+  000:   0 (*local*)       2 (LIBC)          2 (LIBC)          2 (LIBC)       
+  004:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  008:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  00c:   0 (*local*)       0 (*local*)       0 (*local*)       0 (*local*)    
+  010:   0 (*local*)       2 (LIBC)          0 (*local*)       2 (LIBC)       
+  014:   0 (*local*)       2 (LIBC)          0 (*local*)       2 (LIBC)       
+  018:   2 (LIBC)          2 (LIBC)          0 (*local*)       0 (*local*)    
+  01c:   2 (LIBC)          0 (*local*)       2 (LIBC)          0 (*local*)    
+  020:   2 (LIBC)          0 (*local*)       2 (LIBC)          0 (*local*)    
+  024:   2 (LIBC)          0 (*local*)       0 (*local*)       0 (*local*)    
+  028:   2 (LIBC)          2 (LIBC)          0 (*local*)       2 (LIBC)       
+  02c:   0 (*local*)       2 (LIBC)          4 (LIBC)          2 (LIBC)       
+  030:   0 (*local*)       2 (LIBC)          0 (*local*)       0 (*local*)    
+  034:   2 (LIBC)          2 (LIBC)          2 (LIBC)          2 (LIBC)       
+  038:   2 (LIBC)          2 (LIBC)          2 (LIBC)          0 (*local*)    
+  03c:   0 (*local*)       0 (*local*)       3 (LIBC_P)        1 (*global*)   
+  040:   1 (*global*)      1 (*global*)      1 (*global*)      1 (*global*)   
+  044:   1 (*global*)      1 (*global*)      1 (*global*)   
+
+Version needs section '.gnu.version_r' contains 2 entries:
+ Addr: 0x00000000000010dc  Offset: 0x0010dc  Link: 5 (.dynstr)
+  000000: Version: 1  File: libc.so  Cnt: 2
+  0x0010:   Name: LIBC  Flags: none  Version: 2
+  0x0020:   Name: LIBC_P  Flags: none  Version: 3
+  0x0030: Version: 1  File: libdl.so  Cnt: 1
+  0x0040:   Name: LIBC  Flags: none  Version: 4
+
+String dump of section '.rodata':
+  [     0]  -cp
+  [     4]  -classpath
+  [     f]  --zygote
+  [    18]  --start-system-server
+  [    2e]  --application
+  [    3c]  --nice-name=
+  [    49]  --
+  [    4c]  application
+  [    58]  tool
+  [    5d]  start-system-server
+  [    71]  appproc
+  [    79]  app_process: Unable to determine ABI list from property %s.
+  [    b5]  --abi-list=
+  [    c1]  com.android.internal.os.ZygoteInit
+  [    e4]  com.android.internal.os.RuntimeInit
+  [   108]  Error: no class name or --zygote supplied.^J
+  [   134]  app_process: no class name or --zygote supplied.
+  [   165]  ERROR: could not find class '%s'^J
+  [   187]  ANDROID_DATA
+  [   194]  androidRoot == NULL
+  [   1a8]  ANDROID_DATA environment variable unset
+  [   1d0]  %s/dalvik-cache/%s
+  [   1e3]  (numChars >= PATH_MAX || numChars < 0)
+  [   20a]  Error constructing dalvik cache : %s
+  [   22f]  (result < 0 && errno != EEXIST)
+  [   24f]  Error creating cache dir %s : %s
+  [   270]  (result < 0)
+  [   27d]  Error changing dalvik-cache ownership : %s
+  [   2a8]  Error changing dalvik-cache permissions : %s
+  [   2d5]  Usage: app_process [java-options] cmd-dir start-class-name [options]^J
+  [   31b]  exiting due to SIG_DFL handler for signal %d
+  [   348]  Invalid signal %d
+  [   35a]  Warning: Unexpected sigaction action found %p^J
+  [   389]  failed to create sigchain pthread key: %s
+  [   3b3]  libsigchain
+  [   3bf]  too many special signal handlers
+  [   3e0]  failed to find special handler to remove
+  [   409]  sigaction
+  [   413]  sigprocmask
+  [   41f]  sigaction64
+  [   42b]  sigprocmask64
+  [   439]  Unable to find next %s in signal chain
+  [   460]  zygote64
+  [   470]  ro.product.cpu.abilist64
+  [   489]  x86_64
+
+
+Displaying notes found in: .note.android.ident
+  Owner                 Data size	Description
+  Android              0x00000004	NT_VERSION (version)
+   description data: 1c 00 00 00 
+
+Displaying notes found in: .note.gnu.build-id
+  Owner                 Data size	Description
+  GNU                  0x00000010	NT_GNU_BUILD_ID (unique build ID bitstring)
+    Build ID: 6c3eb89f506fa4c558af06eff220de26
+
+Displaying notes found in: .note.gnu.gold-version
+  Owner                 Data size	Description
+  GNU                  0x00000009	NT_GNU_GOLD_VERSION (gold version)
+    Version: gold 1.12
diff --git a/libraries/compatibility-common-util/tests/gen_elf_golden_files.sh b/libraries/compatibility-common-util/tests/gen_elf_golden_files.sh
new file mode 100755
index 0000000..4b9f29d
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/gen_elf_golden_files.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# This script generats readelf output file for compatibility-common-util-tests.
+# A typical flow is as follows:
+# 1. add the file name in targetFile if to add a new object test file in ./assets
+# 2. run: ./gen_elf_golden_files.sh
+# 3. update ReadElfTest to use the new files
+# 4. build: m release-parser compatibility-common-util-tests -j8
+# 5. test: ./run_tests.sh
+echo Generating ELF golden sample file for test via readelf
+targetFile="arm32_libdl.so arm64_libdl.so x86app_process32 x86app_process64"
+for file in $targetFile; do
+    echo Processing $file
+    readelf -a -p .rodata ./assets/$file > ./assets/${file/.so/}.txt
+done
\ No newline at end of file
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/BackupUtilsTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/BackupUtilsTest.java
new file mode 100644
index 0000000..84c177a
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/BackupUtilsTest.java
@@ -0,0 +1,533 @@
+/*
+ * 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.compatibility.common.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.tradefed.util.RunUtil;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit tests for {@link BackupUtils}
+ */
+@RunWith(JUnit4.class)
+public class BackupUtilsTest {
+    private static final int BACKUP_SERVICE_INIT_TIMEOUT_SECS = 1;
+    private static final int TEST_USER_ID = 10;
+
+    private boolean mIsDumpsysCommandCalled;
+    private boolean mIsEnableCommandCalled;
+    private boolean mIsActivateCommandCalled;
+
+    @Before
+    public void setUp() {
+        mIsDumpsysCommandCalled = false;
+        mIsEnableCommandCalled = false;
+    }
+
+    @Test
+    public void testEnableBackup_whenEnableTrueAndEnabled_returnsTrue() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    output = "Backup Manager currently enabled";
+                } else if (command.equals("bmgr enable true")) {
+                    output = "Backup Manager now enabled";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        assertTrue(backupUtils.enableBackup(true));
+        assertTrue(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenEnableTrueAndDisabled_returnsFalse() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    output = "Backup Manager currently disabled";
+                } else if (command.equals("bmgr enable true")) {
+                    output = "Backup Manager now enabled";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        assertFalse(backupUtils.enableBackup(true));
+        assertTrue(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenEnableFalseAndEnabled_returnsTrue() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    output = "Backup Manager currently enabled";
+                } else if (command.equals("bmgr enable false")) {
+                    output = "Backup Manager now disabled";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        assertTrue(backupUtils.enableBackup(false));
+        assertTrue(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenEnableFalseAndDisabled_returnsFalse() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    output = "Backup Manager currently disabled";
+                } else if (command.equals("bmgr enable false")) {
+                    output = "Backup Manager now disabled";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        assertFalse(backupUtils.enableBackup(false));
+        assertTrue(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenEnableTrueAndEnabledAndCommandsReturnMultipleLines()
+            throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    output = "Backup Manager currently enabled" + "\n...";
+                } else if (command.equals("bmgr enable true")) {
+                    output = "Backup Manager now enabled" + "\n...";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        assertTrue(backupUtils.enableBackup(true));
+        assertTrue(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenQueryCommandThrows_propagatesException() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    throw new IOException(String.format(
+                            "enableBackup: Failed to run command: %s", command));
+                } else if (command.equals("bmgr enable true")) {
+                    output = "Backup Manager now enabled";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+
+        boolean isExceptionHappened = false;
+        try {
+            backupUtils.enableBackup(true);
+        } catch (IOException e) {
+            // enableBackup: Failed to run command: bmgr enabled
+            isExceptionHappened = true;
+        }
+        assertTrue(isExceptionHappened);
+        assertFalse(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenSetCommandThrows_propagatesException() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    output = "Backup Manager currently enabled";
+                } else if (command.equals("bmgr enable true")) {
+                    mIsEnableCommandCalled = true;
+                    throw new IOException(String.format(
+                            "enableBackup: Failed to run command: %s", command));
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+
+        boolean isExceptionHappened = false;
+        try {
+            backupUtils.enableBackup(true);
+        } catch (IOException e) {
+            // enableBackup: Failed to run command: bmgr enable true
+            isExceptionHappened = true;
+        }
+        assertTrue(isExceptionHappened);
+        assertTrue(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenQueryCommandReturnsInvalidString_throwsException()
+            throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    output = "Backup Manager ???";
+                } else if (command.equals("bmgr enable true")) {
+                    output = "Backup Manager now enabled";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+
+        boolean isExceptionHappened = false;
+        try {
+            backupUtils.enableBackup(true);
+        } catch (RuntimeException e) {
+            // non-parsable output setting bmgr enabled: Backup Manager ???
+            isExceptionHappened = true;
+        }
+        assertTrue(isExceptionHappened);
+        assertFalse(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testEnableBackup_whenQueryCommandReturnsEmptyString_throwsException()
+            throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("bmgr enabled")) {
+                    // output is empty already
+                } else if (command.equals("bmgr enable true")) {
+                    output = "Backup Manager now enabled";
+                    mIsEnableCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+
+        boolean isExceptionHappened = false;
+        try {
+            backupUtils.enableBackup(true);
+        } catch (NullPointerException e) {
+            // null output by running command, bmgr enabled
+            isExceptionHappened = true;
+        }
+        assertTrue(isExceptionHappened);
+        assertFalse(mIsEnableCommandCalled);
+    }
+
+    @Test
+    public void testWaitForBackupInitialization_whenEnabled() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("dumpsys backup")) {
+                    output = "Backup Manager is enabled / provisioned / not pending init";
+                    mIsDumpsysCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        backupUtils.waitForBackupInitialization();
+        assertTrue(mIsDumpsysCommandCalled);
+    }
+
+    @Test
+    public void testWaitForBackupInitialization_whenDisabled() throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("dumpsys backup")) {
+                    output = "Backup Manager is disabled / provisioned / not pending init";
+                    mIsDumpsysCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        backupUtils.waitForBackupInitialization();
+        assertTrue(mIsDumpsysCommandCalled);
+    }
+
+    @Test
+    public void testWaitUntilBackupServiceIsRunning_whenRunning_doesntThrow() throws Exception {
+        BackupUtils backupUtils = constructDumpsysForBackupUsers(TEST_USER_ID);
+
+        try {
+            backupUtils.waitUntilBackupServiceIsRunning(
+                    TEST_USER_ID, BACKUP_SERVICE_INIT_TIMEOUT_SECS);
+        } catch (AssertionError e) {
+            fail("BackupUtils#waitUntilBackupServiceIsRunning threw an exception");
+        }
+        assertTrue(mIsDumpsysCommandCalled);
+    }
+
+    @Test
+    public void testWaitUntilBackupServiceIsRunning_whenNotRunning_throws() throws Exception {
+        // Pass in a different userId to not have the current one among running ids.
+        BackupUtils backupUtils = constructDumpsysForBackupUsers(TEST_USER_ID + 1);
+
+        boolean wasExceptionThrown = false;
+        try {
+            backupUtils.waitUntilBackupServiceIsRunning(
+                    TEST_USER_ID, BACKUP_SERVICE_INIT_TIMEOUT_SECS);
+        } catch (AssertionError e) {
+            wasExceptionThrown = true;
+        }
+
+        assertTrue(mIsDumpsysCommandCalled);
+        assertTrue(wasExceptionThrown);
+    }
+
+    private BackupUtils constructDumpsysForBackupUsers(int runningUserId) {
+        return new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("dumpsys backup users")) {
+                    output = "Backup Manager is running for users: " + runningUserId;
+                    mIsDumpsysCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+    }
+
+    @Test
+    public void testWaitForBackupInitialization_whenEnabledAndCommandReturnsMultipleLines()
+            throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("dumpsys backup")) {
+                    output = "Backup Manager is enabled / provisioned / not pending init" + "\n...";
+                    mIsDumpsysCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+        backupUtils.waitForBackupInitialization();
+        assertTrue(mIsDumpsysCommandCalled);
+    }
+
+    @Test
+    public void testWaitForBackupInitialization_whenCommandThrows_propagatesException()
+            throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("dumpsys backup")) {
+                    mIsDumpsysCommandCalled = true;
+                    throw new IOException(String.format(
+                            "waitForBackupInitialization: Failed to run command: %s", command));
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+
+        boolean isExceptionHappened = false;
+        try {
+            backupUtils.waitForBackupInitialization();
+        } catch (IOException e) {
+            // waitForBackupInitialization: Failed to run command: dumpsys backup
+            isExceptionHappened = true;
+        }
+        assertTrue(isExceptionHappened);
+        assertTrue(mIsDumpsysCommandCalled);
+    }
+
+    @Test
+    public void testWaitForBackupInitialization_whenCommandReturnsInvalidString()
+            throws Exception {
+        class TestRunnable implements Runnable {
+            @Override
+            public void run() {
+                try {
+                    BackupUtils backupUtils = new BackupUtils() {
+                        @Override
+                        protected InputStream executeShellCommand(String command)
+                                throws IOException {
+                            String output = "";
+                            if (command.equals("dumpsys backup")) {
+                                output = "Backup Manager ???";
+                                mIsDumpsysCommandCalled = true;
+                            }
+                            return new ByteArrayInputStream(output.getBytes("UTF-8"));
+                        }
+                    };
+                    backupUtils.waitForBackupInitialization();
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+        }
+
+        TestRunnable testRunnable = new TestRunnable();
+        Thread testThread = new Thread(testRunnable);
+
+        try {
+            testThread.start();
+            RunUtil.getDefault().sleep(100);
+            assertTrue(mIsDumpsysCommandCalled);
+            assertTrue(testThread.isAlive());
+        } catch (Exception e) {
+            // ignore
+        } finally {
+            testThread.interrupt();
+        }
+    }
+
+    @Test
+    public void testWaitForBackupInitialization_whenCommandReturnsEmptyString_throwsException()
+            throws Exception {
+        BackupUtils backupUtils = new BackupUtils() {
+            @Override
+            protected InputStream executeShellCommand(String command) throws IOException {
+                String output = "";
+                if (command.equals("dumpsys backup")) {
+                    // output is empty already
+                    mIsDumpsysCommandCalled = true;
+                }
+                return new ByteArrayInputStream(output.getBytes("UTF-8"));
+            }
+        };
+
+        boolean isExceptionHappened = false;
+        try {
+            backupUtils.waitForBackupInitialization();
+        } catch (NullPointerException e) {
+            // null output by running command, dumpsys backup
+            isExceptionHappened = true;
+        }
+        assertTrue(isExceptionHappened);
+        assertTrue(mIsDumpsysCommandCalled);
+    }
+
+    @Test
+    public void testActivateBackup_whenEnableTrueAndEnabled_returnsTrue() throws Exception {
+        BackupUtils backupUtils =
+                new BackupUtils() {
+                    @Override
+                    protected InputStream executeShellCommand(String command) throws IOException {
+                        String output = "";
+                        if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
+                            output = "Backup Manager currently activated";
+                        } else if (command.equals(getBmgrCommand("activate true", TEST_USER_ID))) {
+                            output = "Backup Manager now activated";
+                            mIsActivateCommandCalled = true;
+                        }
+                        return new ByteArrayInputStream(output.getBytes("UTF-8"));
+                    }
+                };
+        assertTrue(backupUtils.activateBackupForUser(true, TEST_USER_ID));
+        assertTrue(mIsActivateCommandCalled);
+    }
+
+    @Test
+    public void testActivateBackup_whenEnableTrueAndDisabled_returnsFalse() throws Exception {
+        BackupUtils backupUtils =
+                new BackupUtils() {
+                    @Override
+                    protected InputStream executeShellCommand(String command) throws IOException {
+                        String output = "";
+                        if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
+                            output = "Backup Manager currently deactivated";
+                        } else if (command.equals(getBmgrCommand("activate true", TEST_USER_ID))) {
+                            output = "Backup Manager now activated";
+                            mIsActivateCommandCalled = true;
+                        }
+                        return new ByteArrayInputStream(output.getBytes("UTF-8"));
+                    }
+                };
+        assertFalse(backupUtils.activateBackupForUser(true, TEST_USER_ID));
+        assertTrue(mIsActivateCommandCalled);
+    }
+
+    @Test
+    public void testActivateBackup_whenEnableFalseAndEnabled_returnsTrue() throws Exception {
+        BackupUtils backupUtils =
+                new BackupUtils() {
+                    @Override
+                    protected InputStream executeShellCommand(String command) throws IOException {
+                        String output = "";
+                        if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
+                            output = "Backup Manager currently activated";
+                        } else if (command.equals(getBmgrCommand("activate false", TEST_USER_ID))) {
+                            output = "Backup Manager now deactivated";
+                            mIsActivateCommandCalled = true;
+                        }
+                        return new ByteArrayInputStream(output.getBytes("UTF-8"));
+                    }
+                };
+        assertTrue(backupUtils.activateBackupForUser(false, TEST_USER_ID));
+        assertTrue(mIsActivateCommandCalled);
+    }
+
+    @Test
+    public void testActivateBackup_whenEnableFalseAndDisabled_returnsFalse() throws Exception {
+        BackupUtils backupUtils =
+                new BackupUtils() {
+                    @Override
+                    protected InputStream executeShellCommand(String command) throws IOException {
+                        String output = "";
+                        if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
+                            output = "Backup Manager currently deactivated";
+                        } else if (command.equals(getBmgrCommand("activate false", TEST_USER_ID))) {
+                            output = "Backup Manager now deactivated";
+                            mIsActivateCommandCalled = true;
+                        }
+                        return new ByteArrayInputStream(output.getBytes("UTF-8"));
+                    }
+                };
+        assertFalse(backupUtils.activateBackupForUser(false, TEST_USER_ID));
+        assertTrue(mIsActivateCommandCalled);
+    }
+
+    private String getBmgrCommand(String command, int userId) {
+        return "bmgr --user " + userId + " " + command;
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/BusinessLogicTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/BusinessLogicTest.java
new file mode 100644
index 0000000..fdb2150
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/BusinessLogicTest.java
@@ -0,0 +1,252 @@
+/*
+ * 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.compatibility.common.util;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.compatibility.common.util.BusinessLogic.BusinessLogicRule;
+import com.android.compatibility.common.util.BusinessLogic.BusinessLogicRuleAction;
+import com.android.compatibility.common.util.BusinessLogic.BusinessLogicRuleCondition;
+import com.android.tradefed.util.FileUtil;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Unit tests for {@link BusinessLogic}
+ */
+@RunWith(JUnit4.class)
+public class BusinessLogicTest {
+
+    private static final String CORRECT_LOGIC =
+            "{\n" +
+            "  \"name\": \"businessLogic/suites/gts\",\n" +
+            "  \"businessLogicRulesLists\": [\n" +
+            "    {\n" +
+            "      \"testName\": \"testCaseName1\",\n" +
+            "      \"description\": \"first test\",\n" +
+            "      \"businessLogicRules\": [\n" +
+            "        {\n" +
+            "          \"ruleConditions\": [\n" +
+            "            {\n" +
+            "              \"methodName\": \"conditionMethodName1\",\n" +
+            "              \"methodArgs\": [\n" +
+            "                \"arg1\"\n" +
+            "              ]\n" +
+            "            }\n" +
+            "          ],\n" +
+            "          \"ruleActions\": [\n" +
+            "            {\n" +
+            "              \"methodName\": \"actionMethodName1\",\n" +
+            "              \"methodArgs\": [\n" +
+            "                \"arg1\",\n" +
+            "                \"arg2\"\n" +
+            "              ]\n" +
+            "            }\n" +
+            "          ]\n" +
+            "        }\n" +
+            "      ]\n" +
+            "    },\n" +
+            "    {\n" +
+            "      \"testName\": \"testCaseName2\",\n" +
+            "      \"businessLogicRules\": [\n" +
+            "        {\n" +
+            "          \"ruleConditions\": [\n" +
+            "            {\n" +
+            "              \"methodName\": \"conditionMethodName1\",\n" +
+            "              \"methodArgs\": [\n" +
+            "                \"arg1\"\n" +
+            "              ]\n" +
+            "            }\n" +
+            "          ],\n" +
+            "          \"ruleActions\": [\n" +
+            "            {\n" +
+            "              \"methodName\": \"actionMethodName1\",\n" +
+            "              \"methodArgs\": [\n" +
+            "                \"arg1\",\n" +
+            "                \"arg2\"\n" +
+            "              ]\n" +
+            "            }\n" +
+            "          ]\n" +
+            "        },\n" +
+            "        {\n" +
+            "          \"ruleConditions\": [\n" +
+            "            {\n" +
+            "              \"methodName\": \"conditionMethodName1\",\n" +
+            "              \"methodArgs\": [\n" +
+            "                \"arg1\"\n" +
+            "              ]\n" +
+            "            },\n" +
+            "            {\n" +
+            "              \"methodName\": \"!conditionMethodName2\",\n" + // use negation
+            "              \"methodArgs\": [\n" +
+            "                \"arg2\"\n" +
+            "              ]\n" +
+            "            }\n" +
+            "          ],\n" +
+            "          \"ruleActions\": [\n" +
+            "            {\n" +
+            "              \"methodName\": \"actionMethodName1\",\n" +
+            "              \"methodArgs\": [\n" +
+            "                \"arg1\",\n" +
+            "                \"arg2\"\n" +
+            "              ]\n" +
+            "            },\n" +
+            "            {\n" +
+            "              \"methodName\": \"actionMethodName2\"\n" +
+            "            }\n" +
+            "          ]\n" +
+            "        }\n" +
+            "      ]\n" +
+            "    },\n" +
+            "    {\n" +
+            "      \"testName\": \"testCaseName3\"\n" +
+            "    }\n" +
+            "  ]\n" +
+            "}";
+
+    @Test
+    public void testCorrectLogic() throws Exception {
+        File file = createFileFromStr(CORRECT_LOGIC);
+        try {
+            BusinessLogic bl = BusinessLogicFactory.createFromFile(file);
+            assertEquals("Wrong number of business logic rule lists", 3, bl.mRules.size());
+            String description = bl.mRules.get("testCaseName1").get(0).getDescription();
+            assertEquals("Wrong or missing rule list description", "first test", description);
+            List<BusinessLogicRule> rulesList1 = bl.mRules.get("testCaseName1").get(0).getRules();
+            assertEquals("Wrong number of rules in first rule list", 1, rulesList1.size());
+            BusinessLogicRule rule1 = rulesList1.get(0);
+            List<BusinessLogicRuleCondition> rule1Conditions = rule1.mConditions;
+            assertEquals("Wrong number of conditions", 1, rule1Conditions.size());
+            BusinessLogicRuleCondition rule1Condition = rule1Conditions.get(0);
+            assertEquals("Wrong method name for business logic rule condition",
+                    "conditionMethodName1", rule1Condition.mMethodName);
+            assertFalse("Wrong negation value for business logic rule condition",
+                    rule1Condition.mNegated);
+            assertEquals("Wrong arg string count for business logic rule condition", 1,
+                    rule1Condition.mMethodArgs.size());
+            assertEquals("Wrong arg for business logic rule condition", "arg1",
+                    rule1Condition.mMethodArgs.get(0));
+            List<BusinessLogicRuleAction> rule1Actions = rule1.mActions;
+            assertEquals("Wrong number of actions", 1, rule1Actions.size());
+            BusinessLogicRuleAction rule1Action = rule1Actions.get(0);
+            assertEquals("Wrong method name for business logic rule action",
+                    "actionMethodName1", rule1Action.mMethodName);
+            assertEquals("Wrong arg string count for business logic rule action", 2,
+                    rule1Action.mMethodArgs.size());
+            assertEquals("Wrong arg for business logic rule action", "arg1",
+                    rule1Action.mMethodArgs.get(0));
+            assertEquals("Wrong arg for business logic rule action", "arg2",
+                    rule1Action.mMethodArgs.get(1));
+
+            List<BusinessLogicRule> rulesList2 = bl.mRules.get("testCaseName2").get(0).getRules();
+            assertEquals("Wrong number of rules in second rule list", 2, rulesList2.size());
+            BusinessLogicRule rule2 = rulesList2.get(0);
+            List<BusinessLogicRuleCondition> rule2Conditions = rule2.mConditions;
+            assertEquals("Wrong number of conditions", 1, rule2Conditions.size());
+            BusinessLogicRuleCondition rule2Condition = rule2Conditions.get(0);
+            assertEquals("Wrong method name for business logic rule condition",
+                    "conditionMethodName1", rule2Condition.mMethodName);
+            assertFalse("Wrong negation value for business logic rule condition",
+                    rule2Condition.mNegated);
+            assertEquals("Wrong arg string count for business logic rule condition", 1,
+                    rule2Condition.mMethodArgs.size());
+            assertEquals("Wrong arg for business logic rule condition", "arg1",
+                    rule2Condition.mMethodArgs.get(0));
+            List<BusinessLogicRuleAction> rule2Actions = rule2.mActions;
+            assertEquals("Wrong number of actions", 1, rule2Actions.size());
+            BusinessLogicRuleAction rule2Action = rule2Actions.get(0);
+            assertEquals("Wrong method name for business logic rule action",
+                    "actionMethodName1", rule2Action.mMethodName);
+            assertEquals("Wrong arg string count for business logic rule action", 2,
+                    rule2Action.mMethodArgs.size());
+            assertEquals("Wrong arg for business logic rule action", "arg1",
+                    rule2Action.mMethodArgs.get(0));
+            assertEquals("Wrong arg for business logic rule action", "arg2",
+                    rule2Action.mMethodArgs.get(1));
+            BusinessLogicRule rule3 = rulesList2.get(1);
+            List<BusinessLogicRuleCondition> rule3Conditions = rule3.mConditions;
+            assertEquals("Wrong number of conditions", 2, rule3Conditions.size());
+            BusinessLogicRuleCondition rule3Condition1 = rule3Conditions.get(0);
+            assertEquals("Wrong method name for business logic rule condition",
+                    "conditionMethodName1", rule3Condition1.mMethodName);
+            assertFalse("Wrong negation value for business logic rule condition",
+                    rule3Condition1.mNegated);
+            assertEquals("Wrong arg string count for business logic rule condition", 1,
+                    rule3Condition1.mMethodArgs.size());
+            assertEquals("Wrong arg for business logic rule condition", "arg1",
+                    rule3Condition1.mMethodArgs.get(0));
+            BusinessLogicRuleCondition rule3Condition2 = rule3Conditions.get(1);
+            assertEquals("Wrong method name for business logic rule condition",
+                    "conditionMethodName2", rule3Condition2.mMethodName);
+            assertTrue("Wrong negation value for business logic rule condition",
+                    rule3Condition2.mNegated);
+            assertEquals("Wrong arg string count for business logic rule condition", 1,
+                    rule3Condition2.mMethodArgs.size());
+            assertEquals("Wrong arg for business logic rule condition", "arg2",
+                    rule3Condition2.mMethodArgs.get(0));
+            List<BusinessLogicRuleAction> rule3Actions = rule3.mActions;
+            assertEquals("Wrong number of actions", 2, rule3Actions.size());
+            BusinessLogicRuleAction rule3Action1 = rule3Actions.get(0);
+            assertEquals("Wrong method name for business logic rule action",
+                    "actionMethodName1", rule3Action1.mMethodName);
+            assertEquals("Wrong arg string count for business logic rule action", 2,
+                    rule3Action1.mMethodArgs.size());
+            assertEquals("Wrong arg for business logic rule action", "arg1",
+                    rule3Action1.mMethodArgs.get(0));
+            assertEquals("Wrong arg for business logic rule action", "arg2",
+                    rule3Action1.mMethodArgs.get(1));
+            BusinessLogicRuleAction rule3Action2 = rule3Actions.get(1);
+            assertEquals("Wrong method name for business logic rule action",
+                    "actionMethodName2", rule3Action2.mMethodName);
+            assertEquals("Wrong arg string count for business logic rule action", 0,
+                    rule3Action2.mMethodArgs.size());
+
+            List<BusinessLogicRule> rulesList3 = bl.mRules.get("testCaseName3").get(0).getRules();
+            assertEquals("Wrong number of rules in third rule list", 0, rulesList3.size());
+        } finally {
+            FileUtil.deleteFile(file);
+        }
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void testLogicWithWrongNodeName() throws Exception {
+        File file = createFileFromStr(CORRECT_LOGIC.replace("testName", "testNam3"));
+        try {
+            BusinessLogicFactory.createFromFile(file);
+        } finally {
+            FileUtil.deleteFile(file);
+        }
+    }
+
+    private static File createFileFromStr(String blString) throws IOException {
+        File file = File.createTempFile("test", "bl");
+        FileOutputStream stream = new FileOutputStream(file);
+        stream.write(blString.getBytes());
+        stream.flush();
+        stream.close();
+        return file;
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/CaseResultTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/CaseResultTest.java
new file mode 100644
index 0000000..c8b74c0
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/CaseResultTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 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.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link CaseResult}
+ */
+public class CaseResultTest extends TestCase {
+
+    private static final String CLASS = "android.test.FoorBar";
+    private static final String METHOD_1 = "testBlah1";
+    private static final String METHOD_2 = "testBlah2";
+    private static final String METHOD_3 = "testBlah3";
+    private static final String MESSAGE = "Something small is not alright";
+    private static final String STACK_TRACE = "Something small is not alright\n " +
+            "at four.big.insects.Marley.sing(Marley.java:10)";
+    private CaseResult mResult;
+
+    @Override
+    public void setUp() throws Exception {
+        mResult = new CaseResult(CLASS);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mResult = null;
+    }
+
+    public void testAccessors() throws Exception {
+        assertEquals("Incorrect case name", CLASS, mResult.getName());
+    }
+
+    public void testResultCreation() throws Exception {
+        ITestResult testResult = mResult.getOrCreateResult(METHOD_1);
+        // Should create one
+        assertEquals("Expected one result", 1, mResult.getResults().size());
+        assertTrue("Expected test result", mResult.getResults().contains(testResult));
+        // Should not create another one
+        ITestResult testResult2 = mResult.getOrCreateResult(METHOD_1);
+        assertEquals("Expected the same result", testResult, testResult2);
+        assertEquals("Expected one result", 1, mResult.getResults().size());
+    }
+
+    public void testResultReporting() throws Exception {
+        ITestResult testResult = mResult.getOrCreateResult(METHOD_1);
+        testResult.failed(STACK_TRACE);
+        assertEquals("Expected status to be set", TestStatus.FAIL, testResult.getResultStatus());
+        assertEquals("Expected message to be set", MESSAGE, testResult.getMessage());
+        assertEquals("Expected stack to be set", STACK_TRACE, testResult.getStackTrace());
+        testResult = mResult.getOrCreateResult(METHOD_2);
+        testResult.passed(null);
+        assertEquals("Expected status to be set", TestStatus.PASS, testResult.getResultStatus());
+        assertEquals("Expected two results", 2, mResult.getResults().size());
+    }
+
+    public void testCountResults() throws Exception {
+        mResult.getOrCreateResult(METHOD_1).failed(STACK_TRACE);
+        mResult.getOrCreateResult(METHOD_2).failed(STACK_TRACE);
+        mResult.getOrCreateResult(METHOD_3).passed(null);
+        assertEquals("Expected two failures", 2, mResult.countResults(TestStatus.FAIL));
+        assertEquals("Expected one pass", 1, mResult.countResults(TestStatus.PASS));
+    }
+
+    public void testMergeCase() throws Exception {
+        mResult.getOrCreateResult(METHOD_1).failed(STACK_TRACE);
+        mResult.getOrCreateResult(METHOD_2).passed(null);
+
+        // Same case another test and passing results in method 2
+        CaseResult otherResult = new CaseResult(CLASS);
+        otherResult.getOrCreateResult(METHOD_1).passed(null);
+        otherResult.getOrCreateResult(METHOD_2).passed(null);
+        otherResult.getOrCreateResult(METHOD_3).failed(STACK_TRACE);
+
+        mResult.mergeFrom(otherResult);
+        assertEquals("Expected one result", 3, mResult.getResults().size());
+        assertEquals("Expected one failures", 1, mResult.countResults(TestStatus.FAIL));
+        assertEquals("Expected two pass", 2, mResult.countResults(TestStatus.PASS));
+    }
+
+     public void testMergeCase_passToFail() throws Exception {
+        mResult.getOrCreateResult(METHOD_1).passed(null);
+
+        // Same case another test and passing results in method 2
+        CaseResult otherResult = new CaseResult(CLASS);
+        otherResult.getOrCreateResult(METHOD_1).passed(null);
+        otherResult.getOrCreateResult(METHOD_2).passed(null);
+        otherResult.getOrCreateResult(METHOD_3).failed(STACK_TRACE);
+
+        mResult.mergeFrom(otherResult);
+
+        assertEquals("Expected one result", 3, mResult.getResults().size());
+        assertEquals("Expected one failures", 1, mResult.countResults(TestStatus.FAIL));
+        assertEquals("Expected two pass", 2, mResult.countResults(TestStatus.PASS));
+    }
+
+    public void testMergeCase_mismatchedModuleName() throws Exception {
+
+        CaseResult otherResult = new CaseResult(CLASS + "foo");
+        try {
+            mResult.mergeFrom(otherResult);
+            fail("Expected IlleglArgumentException");
+        } catch (IllegalArgumentException expected) {}
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
new file mode 100644
index 0000000..2d80509
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2019 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.compatibility.common.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import java.util.regex.Pattern;
+
+/** Unit tests for {@link CrashUtils}. */
+@RunWith(JUnit4.class)
+public class CrashUtilsTest {
+
+    private JSONArray mCrashes;
+
+    @Before
+    public void setUp() throws IOException {
+        try (BufferedReader txtReader =
+                new BufferedReader(
+                        new InputStreamReader(
+                                getClass().getClassLoader().getResourceAsStream("logcat.txt")))) {
+            StringBuffer input = new StringBuffer();
+            String tmp;
+            while ((tmp = txtReader.readLine()) != null) {
+                input.append(tmp + "\n");
+            }
+            mCrashes = CrashUtils.addAllCrashes(input.toString(), new JSONArray());
+        }
+    }
+
+    @Test
+    public void testGetAllCrashes() throws Exception {
+        JSONArray expectedResults = new JSONArray();
+        expectedResults.put(createCrashJson(
+                11071, 11189, "AudioOut_D", "/system/bin/audioserver", "e9380000", "SIGSEGV", null));
+        expectedResults.put(createCrashJson(
+                12736, 12761, "Binder:12736_2", "/system/bin/audioserver", "0", "SIGSEGV", null));
+        expectedResults.put(createCrashJson(
+                26201, 26227, "Binder:26201_3", "/system/bin/audioserver", "0", "SIGSEGV", null));
+        expectedResults.put(createCrashJson(
+                26246, 26282, "Binder:26246_5", "/system/bin/audioserver", "0", "SIGSEGV", null));
+        expectedResults.put(createCrashJson(
+                245, 245, "installd", "/system/bin/installd", null, "SIGABRT",
+                "'utils.cpp:67] Check failed: is_valid_package_name(package_name) == 0 '"));
+        expectedResults.put(createCrashJson(
+                6371, 8072, "media.codec", "omx@1.0-service", "ed000000", "SIGSEGV", null));
+        expectedResults.put(createCrashJson(
+                8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
+                "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
+        expectedResults.put(createCrashJson(
+                8080, 11665, "generic", "/system/bin/mediaserver", null, "SIGABRT",
+                "'frameworks/av/media/libstagefright/MPEG4Extractor.cpp:6853 CHECK_EQ( (unsigned)ptr[0],1u) failed: 129 vs. 1'"));
+        expectedResults.put(createCrashJson(
+                11071, 11189, "synthetic_thread", "synthetic_process_0", "e9380000", "SIGSEGV", null));
+        expectedResults.put(createCrashJson(
+                12736, 12761, "synthetic_thread", "synthetic_process_1", "0", "SIGSEGV", null));
+
+        Assert.assertEquals(expectedResults.toString() + "\n" +  mCrashes.toString() + "\n", expectedResults.toString(), mCrashes.toString());
+    }
+
+    public JSONObject createCrashJson(
+                int pid,
+                int tid,
+                String name,
+                String process,
+                String faultaddress,
+                String signal,
+                String abortMessage) {
+        JSONObject json = new JSONObject();
+        try {
+            json.put(CrashUtils.PID, pid);
+            json.put(CrashUtils.TID, tid);
+            json.put(CrashUtils.NAME, name);
+            json.put(CrashUtils.PROCESS, process);
+            json.put(CrashUtils.FAULT_ADDRESS, faultaddress);
+            json.put(CrashUtils.SIGNAL, signal);
+            json.put(CrashUtils.ABORT_MESSAGE, abortMessage);
+        } catch (JSONException e) {}
+        return json;
+    }
+
+    @Test
+    public void testValidCrash() throws Exception {
+        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("synthetic_process_0"))));
+    }
+
+    @Test
+    public void testMissingName() throws Exception {
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile(""))));
+    }
+
+    @Test
+    public void testSIGABRT() throws Exception {
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("installd"))));
+    }
+
+    @Test
+    public void testFaultAddressBelowMin() throws Exception {
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("synthetic_process_1"))));
+    }
+
+    @Test
+    public void testIgnoreMinAddressCheck() throws Exception {
+        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(false)
+                .setProcessPatterns(Pattern.compile("synthetic_process_1"))));
+    }
+
+    @Test
+    public void testBadAbortMessage() throws Exception {
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("generic"))));
+    }
+
+    @Test
+    public void testGoodAndBadCrashes() throws Exception {
+        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(
+                        Pattern.compile("synthetic_process_0"),
+                        Pattern.compile("generic"))));
+    }
+
+    @Test
+    public void testNullFaultAddress() throws Exception {
+        JSONArray crashes = new JSONArray();
+        crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGSEGV", ""));
+        Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+    }
+
+    @Test
+    public void testAbortMessageInclude() throws Exception {
+        JSONArray crashes = new JSONArray();
+        crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
+              "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
+        Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageIncludes("Check failed:")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageIncludes("include not matches")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+    }
+
+    @Test
+    public void testAbortMessageExclude() throws Exception {
+        JSONArray crashes = new JSONArray();
+        crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
+              "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageExcludes("Check failed:")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+
+        Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageExcludes("exclude not matches")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+    }
+
+    @Test
+    public void testAbortMessageExcludeCannotLink() throws Exception {
+        JSONArray crashes = new JSONArray();
+        crashes.put(createCrashJson(
+                18959, 18959, "CVE-2020-0073", "/data/local/tmp/CVE-2020-0073", null, "SIGABRT",
+                "'CANNOT LINK EXECUTABLE \"/data/local/tmp/CVE-2020-0073\": library "
+                + "\"libnfc-nci.so\" (\"(default)\", \"/data/local/tmp/CVE-2020-0073\", \"\") "
+                + "not found'"));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .setProcessPatterns(Pattern.compile("CVE-2020-0073"))));
+
+        crashes.put(createCrashJson(
+                5105, 5105, "CVE-2015-6616-2", "/data/local/tmp/CVE-2015-6616-2", null, "SIGABRT",
+                "'CANNOT LINK EXECUTABLE \"/data/local/tmp/CVE-2015-6616-2\": "
+                + "cannot locate symbol \""
+                + "_ZN7android14MediaExtractor17CreateFromServiceERKNS_2spINS_10DataSourceEEEPKc"
+                + "\" referenced by \"/data/local/tmp/CVE-2015-6616-2\"...'"));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .setProcessPatterns(Pattern.compile("CVE-2015-6616-2"))));
+
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java
new file mode 100644
index 0000000..954c1ce
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 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.compatibility.common.util;
+
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Unit tests for {@link DynamicConfig}
+ */
+public class DynamicConfigTest extends TestCase {
+    private static final String CORRECT_CONFIG =
+            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+            "<dynamicConfig>\n" +
+            "    <entry key=\"remote_config_required\">\n" +
+            "        <value>false</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"test-config-1\">\n" +
+            "        <value>test config 1</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"test-config-2\">\n" +
+            "        <value>testconfig2</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"config-list\">\n" +
+            "        <value>config0</value>\n" +
+            "        <value>config1</value>\n" +
+            "        <value>config2</value>\n" +
+            "        <value>config3</value>\n" +
+            "        <value>config4</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"config-list-2\">\n" +
+            "        <value>A</value>\n" +
+            "        <value>B</value>\n" +
+            "        <value>C</value>\n" +
+            "        <value>D</value>\n" +
+            "        <value>E</value>\n" +
+            "    </entry>\n" +
+            "</dynamicConfig>\n";
+
+    private static final String CONFIG_WRONG_NODE_NAME =
+            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+            "<dynamicCsonfig>\n" +  //The node name dynamicConfig is intentionally mistyped
+            "    <entry key=\"remote_config_required\">\n" +
+            "        <value>false</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"test-config-1\">\n" +
+            "        <value>test config 1</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"test-config-2\">\n" +
+            "        <value>testconfig2</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"config-list\">\n" +
+            "        <value>Nevermore</value>\n" +
+            "        <value>Puck</value>\n" +
+            "        <value>Zeus</value>\n" +
+            "        <value>Earth Shaker</value>\n" +
+            "        <value>Vengeful Spirit</value>\n" +
+            "    </entry>\n" +
+            "    <entry key=\"config-list-2\">\n" +
+            "        <value>A</value>\n" +
+            "        <value>B</value>\n" +
+            "        <value>C</value>\n" +
+            "        <value>D</value>\n" +
+            "        <value>E</value>\n" +
+            "    </entry>\n" +
+            "</dynamicConfig>\n";
+
+    public void testCorrectConfig() throws Exception {
+        DynamicConfig config = new DynamicConfig();
+        File file = createFileFromStr(CORRECT_CONFIG);
+        try {
+            config.initializeConfig(file);
+            assertEquals("Wrong Config", config.getValue("test-config-1"), "test config 1");
+            assertEquals("Wrong Config", config.getValue("test-config-2"), "testconfig2");
+            assertEquals("Wrong Config List", config.getValues("config-list").get(0), "config0");
+            assertEquals("Wrong Config List", config.getValues("config-list").get(2), "config2");
+            assertEquals("Wrong Config List", config.getValues("config-list-2").get(2), "C");
+        } finally {
+            FileUtil.deleteFile(file);
+        }
+    }
+
+    public void testConfigWithWrongNodeName() throws Exception {
+        DynamicConfig config = new DynamicConfig();
+        File file = createFileFromStr(CONFIG_WRONG_NODE_NAME);
+        try {
+            config.initializeConfig(file);
+            fail("Cannot detect error when config file has wrong node name");
+        } catch (XmlPullParserException e) {
+            //expected
+        } finally {
+            FileUtil.deleteFile(file);
+        }
+    }
+
+    private File createFileFromStr(String configStr) throws IOException {
+        File file = File.createTempFile("test", "dynamic");
+        FileOutputStream stream = new FileOutputStream(file);
+        stream.write(configStr.getBytes());
+        stream.flush();
+        stream.close();
+        return file;
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/LightInvocationResultTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/LightInvocationResultTest.java
new file mode 100644
index 0000000..8a87277
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/LightInvocationResultTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.compatibility.common.util;
+
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+
+/**
+ * Unit tests for {@link LightInvocationResult}
+ */
+public class LightInvocationResultTest extends TestCase {
+
+    private File resultsDir;
+
+    @Override
+    public void setUp() throws Exception {
+        resultsDir = FileUtil.createTempDir("results");
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        FileUtil.recursiveDelete(resultsDir);
+    }
+
+    public void testLightInvocationResultInstatiate() throws Exception {
+        File resultDir = ResultHandlerTest.writeResultDir(resultsDir, false);
+        IInvocationResult fullResult = ResultHandler.getResultFromDir(resultDir);
+        LightInvocationResult lightResult = new LightInvocationResult(fullResult);
+        // Ensure that light result implementation does not use a reference to the full result
+        fullResult = null;
+        ResultHandlerTest.checkLightResult(lightResult);
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
new file mode 100644
index 0000000..dbbb479
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014 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.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+//TODO(stuartscott): Delete file for v2, ReportLog can serialize itself.
+/**
+ * Unit tests for {@link MetricsXmlSerializer}
+ */
+public class MetricsXmlSerializerTest extends TestCase {
+
+    static class LocalReportLog extends ReportLog {}
+    private static final double[] VALUES = new double[] {1, 11, 21, 1211, 111221};
+    private static final String HEADER = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>";
+    private static final String EXPECTED_XML = HEADER
+            + "<Summary message=\"Sample\" scoreType=\"higher_better\" unit=\"byte\">1.0</Summary>";
+
+    private LocalReportLog mLocalReportLog;
+    private MetricsXmlSerializer mMetricsXmlSerializer;
+    private ByteArrayOutputStream mByteArrayOutputStream;
+    private XmlSerializer xmlSerializer;
+
+    @Override
+    public void setUp() throws Exception {
+        mLocalReportLog = new LocalReportLog();
+        mByteArrayOutputStream = new ByteArrayOutputStream();
+        XmlPullParserFactory factory = XmlPullParserFactory.newInstance(null, null);
+        xmlSerializer = factory.newSerializer();
+        xmlSerializer.setOutput(mByteArrayOutputStream, "utf-8");
+
+        this.mMetricsXmlSerializer = new MetricsXmlSerializer(xmlSerializer);
+    }
+
+    public void testSerialize_null() throws IOException {
+        xmlSerializer.startDocument("utf-8", true);
+        mMetricsXmlSerializer.serialize(null);
+        xmlSerializer.endDocument();
+
+        assertEquals(HEADER.length(), mByteArrayOutputStream.toByteArray().length);
+    }
+
+    public void testSerialize_noData() throws IOException {
+        xmlSerializer.startDocument("utf-8", true);
+        mMetricsXmlSerializer.serialize(mLocalReportLog);
+        xmlSerializer.endDocument();
+
+        assertEquals(HEADER.length(), mByteArrayOutputStream.toByteArray().length);
+    }
+
+    public void testSerialize() throws IOException {
+        mLocalReportLog.setSummary("Sample", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        mLocalReportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
+
+        xmlSerializer.startDocument("utf-8", true);
+        mMetricsXmlSerializer.serialize(mLocalReportLog);
+        xmlSerializer.endDocument();
+
+        assertEquals(EXPECTED_XML, mByteArrayOutputStream.toString("utf-8"));
+    }
+}
\ No newline at end of file
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/MultipartFormTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/MultipartFormTest.java
new file mode 100644
index 0000000..dd96308
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/MultipartFormTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link MultipartForm}
+ */
+public class MultipartFormTest extends TestCase {
+
+    private static final String SERVER_URL = "http://127.0.0.1:5555";
+    private static final byte[] ZIP_ARRAY = {
+            0xa, 0x2d, 0x2d, 0x43, 0x37, 0x35, 0x49, 0x35, 0x35, 0x75, 0x33, 0x52, 0x33, 0x70, 0x30,
+            0x72, 0x37, 0x33, 0x72, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69,
+            0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+            0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x3b, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22,
+            0x66, 0x6f, 0x6f, 0x22, 0xa, 0xa, 0x62, 0x61, 0x72, 0xa, 0x2d, 0x2d, 0x43, 0x37, 0x35,
+            0x49, 0x35, 0x35, 0x75, 0x33, 0x52, 0x33, 0x70, 0x30, 0x72, 0x37, 0x33, 0x72, 0xa, 0x43,
+            0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69,
+            0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74,
+            0x61, 0x3b, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x68, 0x22,
+            0x3b, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x6c,
+            0x61, 0x68, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x67, 0x7a, 0x22, 0xa, 0x43, 0x6f, 0x6e, 0x74,
+            0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c,
+            0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x7a, 0x69, 0x70, 0xa,
+            0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66,
+            0x65, 0x72, 0x2d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x62,
+            0x69, 0x6e, 0x61, 0x72, 0x79, 0xa, 0xa, 0x62, 0x6c, 0x61, 0x68, 0xa, 0x2d, 0x2d, 0x43,
+            0x37, 0x35, 0x49, 0x35, 0x35, 0x75, 0x33, 0x52, 0x33, 0x70, 0x30, 0x72, 0x37, 0x33,
+            0x72, 0x2d, 0x2d, 0xa,
+    };
+
+    public void testContentBody() throws Exception {
+        MultipartForm form = new MultipartForm(SERVER_URL);
+        form.addFormValue("foo", "bar");
+        form.addFormFile("blah", "blah.xml.gz", "blah".getBytes());
+        byte[] data = form.getContentBody();
+        assertTrue("No data", data.length > 0);
+        assertTrue("Wrong data", Arrays.equals(ZIP_ARRAY, data));
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ReadElfTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ReadElfTest.java
new file mode 100644
index 0000000..cd2e681
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ReadElfTest.java
@@ -0,0 +1,302 @@
+/*
+ * 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.compatibility.common.util;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests if {@link ReadElf} parses Executable and Linkable Format files properly.
+ *
+ * <p>These tests validate content, parsed by {@link ReadElf} is the same with the golden sample
+ * files. The golden sample files are the outputs from Linux cmd: readelf -a elf-file
+ *
+ * <p>
+ */
+@RunWith(JUnit4.class)
+public class ReadElfTest {
+    private static final String THIS_CLASS = "com.android.compatibility.common.util.ReadElfTest";
+    private static final String TEST_SO_ARM32B = "arm32_libdl.so";
+    private static final String TEST_SO_ARM32B_READELF = "arm32_libdl.txt";
+    private static final String TEST_SO_ARM64B = "arm64_libdl.so";
+    private static final String TEST_SO_ARM64B_READELF = "arm64_libdl.txt";
+    private static final String TEST_EXE_X8664B = "x86app_process64";
+    private static final String TEST_EXE_X8664B_READELF = "x86app_process64.txt";
+    private static final String TEST_EXE_X8632B = "x86app_process32";
+    private static final String TEST_EXE_X8632B_READELF = "x86app_process32.txt";
+
+    /**
+     * Test {@link ReadElf} for an ARM 32-bit Shared Object
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testReadElfArm32b() throws Exception {
+        checkReadElf(TEST_SO_ARM32B, TEST_SO_ARM32B_READELF, ReadElf.ARCH_ARM, 32, ReadElf.ET_DYN);
+    }
+
+    /**
+     * Test {@link ReadElf} for an ARM 64-bit Shared Object
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testReadElfArm64b() throws Exception {
+        checkReadElf(TEST_SO_ARM64B, TEST_SO_ARM64B_READELF, ReadElf.ARCH_ARM, 64, ReadElf.ET_DYN);
+    }
+
+    /**
+     * Test {@link ReadElf} for an x86 32-bit Executable
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testReadElfX8632b() throws Exception {
+        checkReadElf(
+                TEST_EXE_X8632B, TEST_EXE_X8632B_READELF, ReadElf.ARCH_X86, 32, ReadElf.ET_DYN);
+    }
+
+    /**
+     * Test {@link ReadElf} for an x86 64-bit Executable
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testReadElfX8664b() throws Exception {
+        checkReadElf(
+                TEST_EXE_X8664B, TEST_EXE_X8664B_READELF, ReadElf.ARCH_X86, 64, ReadElf.ET_DYN);
+    }
+
+    /**
+     * Compares {@link ReadElf} returns same results with Linux readelf cmd on the same ELF file
+     *
+     * @param elfFileName the name of an ELF file in Resource to be checked
+     * @param elfOutputFileName the name of the golden sample file in Resource
+     * @param bits the expected bits of the ELF file
+     * @param arch the expected Instruction Set Architecture of the ELF file
+     * @param type the expected object file type of the ELF file
+     */
+    private void checkReadElf(
+            String elfFileName, String elfOutputFileName, String arch, int bits, int type)
+            throws Exception {
+        File targetFile = getResrouceFile(elfFileName);
+        assertEquals("ReadElf.isElf() " + elfFileName, true, ReadElf.isElf(targetFile));
+        ReadElf elf = ReadElf.read(targetFile);
+        assertEquals("getBits() ", bits, elf.getBits());
+        assertEquals("getArchitecture() ", arch, elf.getArchitecture());
+        assertEquals("isDynamic() ", true, elf.isDynamic());
+        assertEquals("getType() ", type, elf.getType());
+
+        File elfOutputFile = getResrouceFile(elfOutputFileName);
+        assertEquals("ReadElf.isElf() " + elfOutputFileName, false, ReadElf.isElf(elfOutputFile));
+
+        final ReadElf.Symbol[] dynSymbolArr = elf.getDynSymArr();
+        chkDynSymbol(elfOutputFile, dynSymbolArr);
+
+        assertEquals(
+                "ReadElf.getDynamicDependencies() " + elfFileName,
+                getDynamicDependencies(elfOutputFile),
+                elf.getDynamicDependencies());
+
+        assertEquals(
+                "ReadElf.getRoStrings() " + elfFileName,
+                getRoStrings(elfOutputFile),
+                elf.getRoStrings());
+    }
+
+    /**
+     * Gets a list of needed libraries from a Linux readelf cmd output file
+     *
+     * @param elfOutputFileName a {@link File} object of an golden sample file
+     * @return a name list of needed libraries
+     */
+    private List<String> getDynamicDependencies(File elfOutputFile) throws IOException {
+        List<String> result = new ArrayList<>();
+
+        FileReader fileReader = new FileReader(elfOutputFile);
+        BufferedReader buffReader = new BufferedReader(fileReader);
+
+        String line;
+        boolean keepGoing = true;
+        while ((line = buffReader.readLine()) != null && keepGoing) {
+            // readelf output as: Dynamic section at offset 0xfdf0 contains 17 entries:
+            if (line.startsWith("Dynamic section")) {
+                String dsLine;
+                while ((dsLine = buffReader.readLine()) != null) {
+                    String trimLine = dsLine.trim();
+                    if (trimLine.isEmpty()) {
+                        // End of the block
+                        keepGoing = false;
+                        break;
+                    }
+
+                    // 0x0000000000000001 (NEEDED)             Shared library: [ld-android.so]
+                    if (trimLine.contains("1 (NEEDED)")) {
+                        result.add(
+                                trimLine.substring(
+                                        trimLine.indexOf("[") + 1, trimLine.indexOf("]")));
+                    }
+                }
+            }
+        }
+        fileReader.close();
+        return result;
+    }
+
+    /**
+     * Checks if all Dynamic Symbols in a golden sample file are in the symbol array
+     *
+     * @param targetFile a {@link File} object of an golden sample file
+     * @param dynSymbolArr a Dynamic Symbol array to be validated
+     */
+    private void chkDynSymbol(File targetFile, ReadElf.Symbol[] dynSymbolArr) throws IOException {
+        FileReader fileReader = new FileReader(targetFile);
+        BufferedReader buffReader = new BufferedReader(fileReader);
+
+        String line;
+        boolean keepGoing = true;
+        while ((line = buffReader.readLine()) != null && keepGoing) {
+            // readelf output as: Symbol table '.dynsym' contains 44 entries:
+            if (line.startsWith("Symbol table '.dynsym'")) {
+                // Skip the header:   Num:    Value  Size Type    Bind   Vis      Ndx Name
+                buffReader.readLine();
+                // Skip the 1st line:     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
+                buffReader.readLine();
+
+                int i = 1;
+
+                String dsLine;
+                while ((dsLine = buffReader.readLine()) != null) {
+                    // readelf output as:
+                    //    20: 0000000000000ff8    24 FUNC    WEAK   DEFAULT    9
+                    // android_init_anonymous_na@@LIBC_PLATFORM
+                    String trimLine = dsLine.trim();
+                    if (trimLine.isEmpty()) {
+                        // End of the block
+                        keepGoing = false;
+                        break;
+                    }
+
+                    // Removes tailing (x) for an executable
+                    //      1: 00000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@LIBC (2)
+                    int idx = trimLine.indexOf("(");
+                    if (idx > 0) {
+                        trimLine = trimLine.substring(0, idx);
+                    }
+
+                    String phases[] = trimLine.split("\\s+");
+                    String symName = dynSymbolArr[i].name;
+                    String name = phases[phases.length - 1].split("@")[0];
+                    // readelf may truncate a long name
+                    assertTrue(
+                            String.format("chkDynSymbol name %d: %s vs %s", i, symName, name),
+                            symName.startsWith(name));
+                    assertEquals("chkDynSymbol type :", dynSymbolArr[i].toType(), phases[3]);
+                    assertEquals("chkDynSymbol bind :", dynSymbolArr[i].toBind(), phases[4]);
+                    assertEquals("chkDynSymbol ndx :", dynSymbolArr[i].toShndx(), phases[6]);
+                    i++;
+                }
+            }
+        }
+        fileReader.close();
+    }
+
+    /**
+     * Gets a list of Read Only Strings from a Linux readelf -p .rodata cmd output file
+     *
+     * @param elfOutputFileName a {@link File} object of an golden sample file
+     * @return a list of RO Strings
+     */
+    private List<String> getRoStrings(File elfOutputFile) throws IOException {
+        List<String> result = new ArrayList<>();
+
+        FileReader fileReader = new FileReader(elfOutputFile);
+        BufferedReader buffReader = new BufferedReader(fileReader);
+
+        String line;
+        boolean keepGoing = true;
+        while ((line = buffReader.readLine()) != null && keepGoing) {
+            // readelf output as: String dump of section '.rodata':
+            if (line.startsWith("String dump of section '.rodata':")) {
+                String dsLine;
+                while ((dsLine = buffReader.readLine()) != null) {
+                    String trimLine = dsLine.trim();
+                    if (trimLine.isEmpty()) {
+                        // End of the block
+                        keepGoing = false;
+                        break;
+                    }
+
+                    //  [   108]  Error: no class name or --zygote supplied.^J
+                    if (trimLine.contains("[")) {
+                        result.add(
+                                trimLine.substring(trimLine.indexOf("]") + 1, trimLine.length())
+                                        .trim()
+                                        .replace("^J", "\n"));
+                    }
+                }
+            }
+        }
+        fileReader.close();
+        return result;
+    }
+
+    /**
+     * Reads a file from Resource and write to a tmp file
+     *
+     * @param fileName the name of a file in Resource
+     * @return the File object of a tmp file
+     */
+    private File getResrouceFile(String fileName) throws IOException {
+        File tempFile = File.createTempFile(fileName, "tmp");
+        tempFile.deleteOnExit();
+        try (InputStream input = openResourceAsStream(fileName);
+             OutputStream output = new FileOutputStream(tempFile)) {
+            byte[] buffer = new byte[4096];
+            int length;
+            while ((length = input.read(buffer)) > 0) {
+                output.write(buffer, 0, length);
+            }
+        }
+        return tempFile;
+    }
+
+    /**
+     * Gets an InputStrem of a file from Resource
+     *
+     * @param fileName the name of a file in Resrouce
+     * @return the (@link InputStream} object of the file
+     */
+    private InputStream openResourceAsStream(String fileName) {
+        InputStream input = getClass().getResourceAsStream("/" + fileName);
+        assertNotNull(input);
+        return input;
+    }
+}
\ No newline at end of file
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ReportLogTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
new file mode 100644
index 0000000..0da5f2d
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015 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.compatibility.common.util;
+
+import com.android.compatibility.common.util.ReportLog.Metric;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link ReportLog}
+ */
+public class ReportLogTest extends TestCase {
+
+    private static final String SOURCE = "Source";
+    private static final String MESSAGE = "Message";
+    private static final double[] VALUES = new double[] {.1, 124, 4736, 835.683, 98, 395};
+    private static final String HEADER_XML =
+            "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>";
+    private static final String SUMMARY_XML =
+            HEADER_XML + "\r\n" +
+            "<Summary>\r\n" +
+            "  <Metric source=\"com.android.compatibility.common.util.ReportLogTest#%s\" "
+            + "message=\"Sample\" score_type=\"higher_better\" score_unit=\"byte\">\r\n" +
+            "    <Value>1.0</Value>\r\n" +
+            "  </Metric>\r\n" +
+            "</Summary>";
+    private static final String FULL_XML = SUMMARY_XML;
+
+    private ReportLog mReportLog;
+
+    @Override
+    protected void setUp() throws Exception {
+        mReportLog = new ReportLog();
+    }
+
+    public void testSerialize_null() throws Exception {
+        try {
+            ReportLog.serialize(null);
+            fail("Expected IllegalArgumentException when serializing an empty report");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    public void testSerialize_noData() throws Exception {
+        ReportLog.serialize(mReportLog);
+    }
+
+    public void testSerialize_summaryOnly() throws Exception {
+        mReportLog.setSummary("Sample", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        assertEquals(String.format(SUMMARY_XML, "testSerialize_summaryOnly:66"),
+                ReportLog.serialize(mReportLog));
+    }
+
+    public void testSerialize_detailOnly() throws Exception {
+        mReportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
+        assertEquals(HEADER_XML, ReportLog.serialize(mReportLog));
+    }
+
+    public void testSerialize_full() throws Exception {
+        mReportLog.setSummary("Sample", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        mReportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
+        assertEquals(String.format(FULL_XML, "testSerialize_full:77"),
+                ReportLog.serialize(mReportLog));
+    }
+
+    public void testParse_null() throws Exception {
+        try {
+            ReportLog.parse((String) null);
+            fail("Expected IllegalArgumentException when passing a null report");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    public void testParse_noData() throws Exception {
+        ReportLog report = ReportLog.parse(HEADER_XML);
+        assertNull(report.getSummary());
+    }
+
+    public void testParse_summaryOnly() throws Exception {
+        ReportLog report = ReportLog.parse(String.format(SUMMARY_XML, "testParse_summaryOnly:125"));
+        assertNotNull(report);
+        assertEquals("Sample", report.getSummary().getMessage());
+    }
+
+    public void testParse_full() throws Exception {
+        ReportLog report = ReportLog.parse(String.format(FULL_XML, "testParse_full:140"));
+        assertNotNull(report);
+        assertEquals("Sample", report.getSummary().getMessage());
+    }
+
+    public void testLimits_source() throws Exception {
+        // Should pass with a short source.
+        Metric metric = new Metric(SOURCE, MESSAGE, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        assertEquals("Expected message to be ok", SOURCE, metric.getSource());
+        // Make a long source.
+        StringBuilder sb = new StringBuilder();
+        // 40 x "Source" = 240 character string
+        for (int i = 0; i < 40; i++) sb.append(SOURCE);
+        String source = sb.toString();
+        // Should be trimmed because source is too long.
+        metric = new Metric(source, MESSAGE, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        assertEquals("Expected source to be trimmed", source.substring(source.length() - 200),
+                metric.getSource());
+    }
+
+    public void testLimits_message() throws Exception {
+        // Should pass with a short message.
+        Metric metric = new Metric(SOURCE, MESSAGE, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        assertEquals("Expected message to be ok", MESSAGE, metric.getMessage());
+        // Make a long message.
+        StringBuilder sb = new StringBuilder();
+        // 40 x "Message" = 280 character string
+        for (int i = 0; i < 40; i++) sb.append(MESSAGE);
+        String message = sb.toString();
+        // Should be trimmed because message is too long.
+        metric = new Metric(SOURCE, message, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        assertEquals("Expected message to be trimmed", message.substring(0, 200),
+                metric.getMessage());
+    }
+
+    public void testLimits_values() throws Exception {
+        // Should pass with a small array.
+        Metric metric = new Metric(SOURCE, MESSAGE, VALUES, ResultType.HIGHER_BETTER,
+                ResultUnit.BYTE);
+        assertTrue("Expected values to be ok", Arrays.equals(VALUES, metric.getValues()));
+        // Make a big array.
+        double[] values = new double[1001];
+        for (int i = 0; i < values.length; i++) values[i] = i;
+        // Should be trimmed because array is too big.
+        metric = new Metric(SOURCE, MESSAGE, values, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+        assertTrue("Expected values to be trimmed", Arrays.equals(Arrays.copyOf(values, 1000),
+                metric.getValues()));
+    }
+
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
new file mode 100644
index 0000000..581e201
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
@@ -0,0 +1,750 @@
+/*
+ * Copyright (C) 2015 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.compatibility.common.util;
+
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.AbiUtils;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringReader;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+/**
+ * Unit tests for {@link ResultHandler}
+ */
+public class ResultHandlerTest extends TestCase {
+
+    private static final String SUITE_NAME = "CTS";
+    private static final String SUITE_VERSION = "5.0";
+    private static final String SUITE_PLAN = "cts";
+    private static final String SUITE_BUILD = "12345";
+    private static final String REPORT_VERSION = "5.0";
+    private static final String OS_NAME = System.getProperty("os.name");
+    private static final String OS_VERSION = System.getProperty("os.version");
+    private static final String OS_ARCH = System.getProperty("os.arch");
+    private static final String JAVA_VENDOR = System.getProperty("java.vendor");
+    private static final String JAVA_VERSION = System.getProperty("java.version");
+    private static final String NAME_A = "ModuleA";
+    private static final String NAME_B = "ModuleB";
+    private static final String DONE_A = "false";
+    private static final String DONE_B = "true";
+    private static final String RUNTIME_A = "100";
+    private static final String RUNTIME_B = "200";
+    private static final String ABI = "mips64";
+    private static final String ID_A = AbiUtils.createId(ABI, NAME_A);
+    private static final String ID_B = AbiUtils.createId(ABI, NAME_B);
+
+    private static final String BUILD_FINGERPRINT = "build_fingerprint";
+    private static final String BUILD_FINGERPRINT_UNALTERED = "build_fingerprint_unaltered";
+    private static final String BUILD_ID = "build_id";
+    private static final String BUILD_PRODUCT = "build_product";
+    private static final String RUN_HISTORY = "run_history";
+    private static final String EXAMPLE_BUILD_ID = "XYZ";
+    private static final String EXAMPLE_BUILD_PRODUCT = "wolverine";
+    private static final String EXAMPLE_BUILD_FINGERPRINT = "example_build_fingerprint";
+    private static final String EXAMPLE_BUILD_FINGERPRINT_UNALTERED = "example_build_fingerprint_unaltered";
+    private static final String EXAMPLE_RUN_HISTORY =
+            "[{\"startTime\":10000000000000,\"endTime\":10000000000001},"
+                    + "{\"startTime\":10000000000002,\"endTime\":10000000000003}]";
+
+    private static final String DEVICE_A = "device123";
+    private static final String DEVICE_B = "device456";
+    private static final String DEVICES = "device456,device123";
+    private static final String CLASS_A = "android.test.Foor";
+    private static final String CLASS_B = "android.test.Bar";
+    private static final String METHOD_1 = "testBlah1";
+    private static final String METHOD_2 = "testBlah2";
+    private static final String METHOD_3 = "testBlah3";
+    private static final String METHOD_4 = "testBlah4";
+    private static final String METHOD_5 = "testBlah5";
+    private static final String METHOD_6_BRACKETS = "testBlah6[suffix]";
+    private static final String SUB_METHOD_3 = "subTestBlah3";
+    private static final String SUB_METHOD_6_BRACKETS = "subTestBlah6[suffix]";
+    private static final String SUMMARY_SOURCE = String.format("%s#%s:20", CLASS_B, METHOD_4);
+    private static final String SUMMARY_MESSAGE = "Headline";
+    private static final double SUMMARY_VALUE = 9001;
+    private static final String MESSAGE = "Something small is not alright";
+    private static final String STACK_TRACE = "Something small is not alright\n " +
+            "at four.big.insects.Marley.sing(Marley.java:10)";
+    private static final String BUG_REPORT = "https://cnsviewer.corp.google.com/cns/bugreport.txt";
+    private static final String LOGCAT = "https://cnsviewer.corp.google.com/cns/logcat.gz";
+    private static final String SCREENSHOT = "https://cnsviewer.corp.google.com/screenshot.png";
+    private static final long START_MS = 1431586801000L;
+    private static final long END_MS = 1431673199000L;
+    private static final String START_DISPLAY = "Fri Aug 20 15:13:03 PDT 2010";
+    private static final String END_DISPLAY = "Fri Aug 20 15:13:04 PDT 2010";
+    private static final long TEST_START_MS = 1000000000011L;
+    private static final long TEST_END_MS = 1000000000012L;
+    private static final boolean TEST_IS_AUTOMATED = false;
+
+    private static final String REFERENCE_URL = "http://android.com";
+    private static final String LOG_URL = "file:///path/to/logs";
+    private static final String COMMAND_LINE_ARGS = "cts -m CtsMyModuleTestCases";
+    private static final String XML_BASE =
+            "<?xml version='1.0' encoding='UTF-8' standalone='no' ?>" +
+            "<?xml-stylesheet type=\"text/xsl\" href=\"compatibility_result.xsl\"?>\n" +
+            "<Result start=\"%d\" end=\"%d\" start_display=\"%s\"" +
+            "end_display=\"%s\" suite_name=\"%s\" suite_version=\"%s\" " +
+            "suite_plan=\"%s\" suite_build_number=\"%s\" report_version=\"%s\" " +
+            "devices=\"%s\" host_name=\"%s\"" +
+            "os_name=\"%s\" os_version=\"%s\" os_arch=\"%s\" java_vendor=\"%s\"" +
+            "java_version=\"%s\" reference_url=\"%s\" log_url=\"%s\"" +
+            "command_line_args=\"%s\">\n" +
+            "%s%s%s" +
+            "</Result>";
+    private static final String XML_BUILD_INFO =
+            "  <Build " +
+                    BUILD_FINGERPRINT + "=\"%s\" " +
+                    BUILD_ID + "=\"%s\" " +
+                    BUILD_PRODUCT + "=\"%s\" " +
+            "  />\n";
+    private static final String XML_BUILD_INFO_WITH_UNALTERED_BUILD_FINGERPRINT =
+            "  <Build " +
+                    BUILD_FINGERPRINT + "=\"%s\" " +
+                    BUILD_FINGERPRINT_UNALTERED + "=\"%s\" " +
+                    BUILD_ID + "=\"%s\" " +
+                    BUILD_PRODUCT + "=\"%s\" " +
+            "  />\n";
+    private static final String XML_SUMMARY =
+            "  <Summary pass=\"%d\" failed=\"%d\" " +
+            "modules_done=\"1\" modules_total=\"1\" />\n";
+    private static final String XML_MODULE =
+            "  <Module name=\"%s\" abi=\"%s\" device=\"%s\" runtime=\"%s\" done=\"%s\">\n" +
+            "%s" +
+            "  </Module>\n";
+    private static final String XML_CASE =
+            "    <TestCase name=\"%s\">\n" +
+            "%s" +
+            "    </TestCase>\n";
+    private static final String XML_TEST_PASS =
+            "      <Test result=\"pass\" name=\"%s\"/>\n";
+    private static final String XML_TEST_SKIP =
+            "      <Test result=\"pass\" name=\"%s\" skipped=\"true\"/>\n";
+    private static final String XML_TEST_FAIL =
+            "      <Test result=\"fail\" name=\"%s\">\n" +
+            "        <Failure message=\"%s\">\n" +
+            "          <StackTrace>%s</StackTrace>\n" +
+            "        </Failure>\n" +
+            "        <BugReport>%s</BugReport>\n" +
+            "        <Logcat>%s</Logcat>\n" +
+            "        <Screenshot>%s</Screenshot>\n" +
+            "      </Test>\n";
+    private static final String XML_TEST_RESULT =
+            "      <Test result=\"pass\" name=\"%s\">\n" +
+            "        <Summary>\n" +
+            "          <Metric source=\"%s\" message=\"%s\" score_type=\"%s\" score_unit=\"%s\">\n" +
+            "             <Value>%s</Value>\n" +
+            "          </Metric>\n" +
+            "        </Summary>\n" +
+            "      </Test>\n";
+    private static final String NEW_XML_TEST_RESULT =
+            "      <Test result=\"pass\" name=\"%s\">\n"
+                    + "        <Metric key=\"%s\">%s</Metric>\n"
+                    + "      </Test>\n";
+
+    private File resultsDir = null;
+    private File resultDir = null;
+
+    @Override
+    public void setUp() throws Exception {
+        resultsDir = FileUtil.createTempDir("results");
+        resultDir = FileUtil.createTempDir("12345", resultsDir);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        FileUtil.recursiveDelete(resultsDir);
+    }
+
+    public void testSerialization() throws Exception {
+        IInvocationResult result = new InvocationResult();
+        result.setStartTime(START_MS);
+        result.setTestPlan(SUITE_PLAN);
+        result.addDeviceSerial(DEVICE_A);
+        result.addDeviceSerial(DEVICE_B);
+        result.addInvocationInfo(BUILD_FINGERPRINT, EXAMPLE_BUILD_FINGERPRINT);
+        result.addInvocationInfo(BUILD_ID, EXAMPLE_BUILD_ID);
+        result.addInvocationInfo(BUILD_PRODUCT, EXAMPLE_BUILD_PRODUCT);
+        result.addInvocationInfo(RUN_HISTORY, EXAMPLE_RUN_HISTORY);
+        Collection<InvocationResult.RunHistory> runHistories =
+                ((InvocationResult) result).getRunHistories();
+        InvocationResult.RunHistory runHistory1 = new InvocationResult.RunHistory();
+        runHistory1.startTime = 10000000000000L;
+        runHistory1.endTime = 10000000000001L;
+        runHistories.add(runHistory1);
+        InvocationResult.RunHistory runHistory2 = new InvocationResult.RunHistory();
+        runHistory2.startTime = 10000000000002L;
+        runHistory2.endTime = 10000000000003L;
+        runHistories.add(runHistory2);
+
+        // Module A: test1 passes, test2 not executed
+        IModuleResult moduleA = result.getOrCreateModule(ID_A);
+        moduleA.setDone(false);
+        moduleA.addRuntime(Integer.parseInt(RUNTIME_A));
+        ICaseResult moduleACase = moduleA.getOrCreateResult(CLASS_A);
+        ITestResult moduleATest1 = moduleACase.getOrCreateResult(METHOD_1);
+        moduleATest1.setResultStatus(TestStatus.PASS);
+        ITestResult moduleATest2 = moduleACase.getOrCreateResult(METHOD_2);
+        moduleATest2.setResultStatus(null); // not executed test
+        // Module B: test3 fails, test4 passes with report log, test5 passes with skip
+        IModuleResult moduleB = result.getOrCreateModule(ID_B);
+        moduleB.setDone(true);
+        moduleB.addRuntime(Integer.parseInt(RUNTIME_B));
+        ICaseResult moduleBCase = moduleB.getOrCreateResult(CLASS_B);
+        ITestResult moduleBTest3 = moduleBCase.getOrCreateResult(METHOD_3);
+        moduleBTest3.setResultStatus(TestStatus.FAIL);
+        moduleBTest3.setMessage(MESSAGE);
+        moduleBTest3.setStackTrace(STACK_TRACE);
+        moduleBTest3.setBugReport(BUG_REPORT);
+        moduleBTest3.setLog(LOGCAT);
+        moduleBTest3.setScreenshot(SCREENSHOT);
+        ITestResult moduleBTest4 = moduleBCase.getOrCreateResult(METHOD_4);
+        moduleBTest4.setResultStatus(TestStatus.PASS);
+        ReportLog report = new ReportLog();
+        ReportLog.Metric summary = new ReportLog.Metric(SUMMARY_SOURCE, SUMMARY_MESSAGE,
+                SUMMARY_VALUE, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+        report.setSummary(summary);
+        moduleBTest4.setReportLog(report);
+        ITestResult moduleBTest5 = moduleBCase.getOrCreateResult(METHOD_5);
+        moduleBTest5.skipped();
+
+        Map<String, String> testAttributes = new HashMap<String, String>();
+        testAttributes.put("foo1", "bar1");
+        testAttributes.put("foo2", "bar2");
+        // Serialize to file
+        File res =
+                ResultHandler.writeResults(
+                        SUITE_NAME,
+                        SUITE_VERSION,
+                        SUITE_PLAN,
+                        SUITE_BUILD,
+                        result,
+                        resultDir,
+                        START_MS,
+                        END_MS,
+                        REFERENCE_URL,
+                        LOG_URL,
+                        COMMAND_LINE_ARGS,
+                        testAttributes);
+        String content = FileUtil.readStringFromFile(res);
+        assertXmlContainsAttribute(content, "Result", "foo1", "bar1");
+        assertXmlContainsAttribute(content, "Result", "foo2", "bar2");
+        assertXmlContainsAttribute(content, "Result/Build", "run_history", EXAMPLE_RUN_HISTORY);
+        assertXmlContainsNode(content, "Result/RunHistory");
+        assertXmlContainsAttribute(content, "Result/RunHistory/Run", "start", "10000000000000");
+        assertXmlContainsAttribute(content, "Result/RunHistory/Run", "end", "10000000000001");
+        assertXmlContainsAttribute(content, "Result/RunHistory/Run", "start", "10000000000002");
+        assertXmlContainsAttribute(content, "Result/RunHistory/Run", "end", "10000000000003");
+
+        // Parse the results and assert correctness
+        result = ResultHandler.getResultFromDir(resultDir);
+        checkResult(result, false);
+        checkRunHistory(result);
+    }
+
+    /*
+     * Test serialization for CTS Verifier since test results with test result history is only in
+     * CTS Verifier and was not parsed by suite harness.
+     */
+    public void testSerialization_whenTestResultWithTestResultHistoryWithoutParsing()
+            throws Exception {
+        IInvocationResult result = new InvocationResult();
+        result.setStartTime(START_MS);
+        result.setTestPlan(SUITE_PLAN);
+        result.addDeviceSerial(DEVICE_A);
+        result.addDeviceSerial(DEVICE_B);
+        result.addInvocationInfo(BUILD_FINGERPRINT, EXAMPLE_BUILD_FINGERPRINT);
+        result.addInvocationInfo(BUILD_ID, EXAMPLE_BUILD_ID);
+        result.addInvocationInfo(BUILD_PRODUCT, EXAMPLE_BUILD_PRODUCT);
+
+        // Module A: test1 passes, test2 not executed
+        IModuleResult moduleA = result.getOrCreateModule(ID_A);
+        moduleA.setDone(false);
+        moduleA.addRuntime(Integer.parseInt(RUNTIME_A));
+        ICaseResult moduleACase = moduleA.getOrCreateResult(CLASS_A);
+        ITestResult moduleATest1 = moduleACase.getOrCreateResult(METHOD_1);
+        moduleATest1.setResultStatus(TestStatus.PASS);
+        // Module B: test3 fails with test result history, test4 passes with report log,
+        // test5 passes with skip
+        IModuleResult moduleB = result.getOrCreateModule(ID_B);
+        moduleB.setDone(true);
+        moduleB.addRuntime(Integer.parseInt(RUNTIME_B));
+        ICaseResult moduleBCase = moduleB.getOrCreateResult(CLASS_B);
+        Set<TestResultHistory.ExecutionRecord> executionRecords =
+                new HashSet<TestResultHistory.ExecutionRecord>();
+        executionRecords.add(
+                new TestResultHistory.ExecutionRecord(
+                        TEST_START_MS, TEST_END_MS, TEST_IS_AUTOMATED));
+
+        ITestResult moduleBTest3 = moduleBCase.getOrCreateResult(METHOD_3);
+        moduleBTest3.setResultStatus(TestStatus.FAIL);
+        moduleBTest3.setMessage(MESSAGE);
+        moduleBTest3.setStackTrace(STACK_TRACE);
+        moduleBTest3.setBugReport(BUG_REPORT);
+        moduleBTest3.setLog(LOGCAT);
+        moduleBTest3.setScreenshot(SCREENSHOT);
+        List<TestResultHistory> resultHistories = new ArrayList<TestResultHistory>();
+        TestResultHistory resultHistory =
+                new TestResultHistory(METHOD_3 + ":" + SUB_METHOD_3, executionRecords);
+        resultHistories.add(resultHistory);
+        moduleBTest3.setTestResultHistories(resultHistories);
+        ITestResult moduleBTest4 = moduleBCase.getOrCreateResult(METHOD_4);
+        moduleBTest4.setResultStatus(TestStatus.PASS);
+        ReportLog report = new ReportLog();
+        ReportLog.Metric summary =
+                new ReportLog.Metric(
+                        SUMMARY_SOURCE,
+                        SUMMARY_MESSAGE,
+                        SUMMARY_VALUE,
+                        ResultType.HIGHER_BETTER,
+                        ResultUnit.SCORE);
+        report.setSummary(summary);
+        moduleBTest4.setReportLog(report);
+        ITestResult moduleBTest5 = moduleBCase.getOrCreateResult(METHOD_5);
+        moduleBTest5.skipped();
+        // For test name with bracket as suffix in CTS Verifier.
+        ITestResult moduleBTest6 = moduleBCase.getOrCreateResult(METHOD_6_BRACKETS);
+        moduleBTest6.setResultStatus(TestStatus.FAIL);
+        List<TestResultHistory> resultHistories2 = new ArrayList<TestResultHistory>();
+        TestResultHistory resultHistory2 =
+                new TestResultHistory(
+                        METHOD_6_BRACKETS + ":" + SUB_METHOD_6_BRACKETS, executionRecords);
+        resultHistories2.add(resultHistory2);
+        moduleBTest6.setTestResultHistories(resultHistories2);
+
+        // Serialize to file
+        File res =
+                ResultHandler.writeResults(
+                        SUITE_NAME,
+                        SUITE_VERSION,
+                        SUITE_PLAN,
+                        SUITE_BUILD,
+                        result,
+                        resultDir,
+                        START_MS,
+                        END_MS,
+                        REFERENCE_URL,
+                        LOG_URL,
+                        COMMAND_LINE_ARGS,
+                        null);
+        String content = FileUtil.readStringFromFile(res);
+        assertXmlContainsNode(content, "Result/Module/TestCase/Test/RunHistory");
+        assertXmlContainsAttribute(
+                content,
+                "Result/Module/TestCase/Test/RunHistory/Run",
+                "start",
+                Long.toString(TEST_START_MS));
+        assertXmlContainsAttribute(
+                content,
+                "Result/Module/TestCase/Test/RunHistory/Run",
+                "end",
+                Long.toString(TEST_END_MS));
+        assertXmlContainsAttribute(
+                content,
+                "Result/Module/TestCase/Test/RunHistory/Run",
+                "isAutomated",
+                Boolean.toString(TEST_IS_AUTOMATED));
+        checkResult(result, EXAMPLE_BUILD_FINGERPRINT, false, false);
+    }
+
+    public void testParsing() throws Exception {
+        File resultDir = writeResultDir(resultsDir, false);
+        // Parse the results and assert correctness
+        checkResult(ResultHandler.getResultFromDir(resultDir), false);
+    }
+
+    public void testParsing_newTestFormat() throws Exception {
+        File resultDir = writeResultDir(resultsDir, true);
+        // Parse the results and assert correctness
+        checkResult(ResultHandler.getResultFromDir(resultDir), true);
+    }
+
+    public void testParsing_usesUnalteredBuildFingerprintWhenPresent() throws Exception {
+        String buildInfo = String.format(XML_BUILD_INFO_WITH_UNALTERED_BUILD_FINGERPRINT,
+                EXAMPLE_BUILD_FINGERPRINT, EXAMPLE_BUILD_FINGERPRINT_UNALTERED,
+                EXAMPLE_BUILD_ID, EXAMPLE_BUILD_PRODUCT);
+        File resultDir = writeResultDir(resultsDir, buildInfo, false);
+        checkResult(
+                ResultHandler.getResultFromDir(resultDir),
+                EXAMPLE_BUILD_FINGERPRINT_UNALTERED,
+                false,
+                true);
+    }
+
+    public void testParsing_whenUnalteredBuildFingerprintIsEmpty_usesRegularBuildFingerprint() throws Exception {
+        String buildInfo = String.format(XML_BUILD_INFO_WITH_UNALTERED_BUILD_FINGERPRINT,
+                EXAMPLE_BUILD_FINGERPRINT, "", EXAMPLE_BUILD_ID, EXAMPLE_BUILD_PRODUCT);
+        File resultDir = writeResultDir(resultsDir, buildInfo, false);
+        checkResult(
+                ResultHandler.getResultFromDir(resultDir), EXAMPLE_BUILD_FINGERPRINT, false, true);
+    }
+
+    public void testGetLightResults() throws Exception {
+        File resultDir = writeResultDir(resultsDir, false);
+        List<IInvocationResult> lightResults = ResultHandler.getLightResults(resultsDir);
+        assertEquals("Expected one result", 1, lightResults.size());
+        IInvocationResult lightResult = lightResults.get(0);
+        checkLightResult(lightResult);
+    }
+
+    static File writeResultDir(File resultsDir, boolean newTestFormat) throws IOException {
+        String buildInfo = String.format(XML_BUILD_INFO, EXAMPLE_BUILD_FINGERPRINT,
+                EXAMPLE_BUILD_ID, EXAMPLE_BUILD_PRODUCT);
+        return writeResultDir(resultsDir, buildInfo, newTestFormat);
+    }
+
+    /*
+     * Helper to write a result to the results dir, for testing.
+     * @return the written resultDir
+     */
+    static File writeResultDir(File resultsDir, String buildInfo, boolean newTestFormat)
+            throws IOException {
+        File resultDir = null;
+        FileWriter writer = null;
+        try {
+            resultDir = FileUtil.createTempDir("12345", resultsDir);
+            // Create the result file
+            File resultFile = new File(resultDir, ResultHandler.TEST_RESULT_FILE_NAME);
+            writer = new FileWriter(resultFile);
+            String summary = String.format(XML_SUMMARY, 2, 1);
+            String moduleATest = String.format(XML_TEST_PASS, METHOD_1);
+            String moduleACases = String.format(XML_CASE, CLASS_A, moduleATest);
+            String moduleA = String.format(XML_MODULE, NAME_A, ABI, DEVICE_A, RUNTIME_A, DONE_A,
+                    moduleACases);
+            String moduleBTest3 = String.format(XML_TEST_FAIL, METHOD_3, MESSAGE, STACK_TRACE,
+                    BUG_REPORT, LOGCAT, SCREENSHOT);
+            String moduleBTest4 = "";
+            if (newTestFormat) {
+                moduleBTest4 =
+                        String.format(
+                                NEW_XML_TEST_RESULT,
+                                METHOD_4,
+                                SUMMARY_MESSAGE,
+                                Double.toString(SUMMARY_VALUE));
+            } else {
+                moduleBTest4 =
+                        String.format(
+                                XML_TEST_RESULT,
+                                METHOD_4,
+                                SUMMARY_SOURCE,
+                                SUMMARY_MESSAGE,
+                                ResultType.HIGHER_BETTER.toReportString(),
+                                ResultUnit.SCORE.toReportString(),
+                                Double.toString(SUMMARY_VALUE));
+            }
+
+            String moduleBTest5 = String.format(XML_TEST_SKIP, METHOD_5);
+            String moduleBTests = String.join("", moduleBTest3, moduleBTest4, moduleBTest5);
+            String moduleBCases = String.format(XML_CASE, CLASS_B, moduleBTests);
+            String moduleB = String.format(XML_MODULE, NAME_B, ABI, DEVICE_B, RUNTIME_B, DONE_B,
+                    moduleBCases);
+            String modules = String.join("", moduleA, moduleB);
+            String hostName = "";
+            try {
+                hostName = InetAddress.getLocalHost().getHostName();
+            } catch (UnknownHostException ignored) {}
+            String output = String.format(XML_BASE, START_MS, END_MS, START_DISPLAY, END_DISPLAY,
+                    SUITE_NAME, SUITE_VERSION, SUITE_PLAN, SUITE_BUILD, REPORT_VERSION, DEVICES,
+                    hostName, OS_NAME, OS_VERSION, OS_ARCH, JAVA_VENDOR,
+                    JAVA_VERSION, REFERENCE_URL, LOG_URL, COMMAND_LINE_ARGS,
+                    buildInfo, summary, modules);
+            writer.write(output);
+            writer.flush();
+        } finally {
+            if (writer != null) {
+                writer.close();
+            }
+        }
+        return resultDir;
+    }
+
+    static void checkLightResult(IInvocationResult lightResult) throws Exception {
+        assertEquals("Expected 3 passes", 3, lightResult.countResults(TestStatus.PASS));
+        assertEquals("Expected 1 failure", 1, lightResult.countResults(TestStatus.FAIL));
+
+        Map<String, String> buildInfo = lightResult.getInvocationInfo();
+        assertEquals("Incorrect Build ID", EXAMPLE_BUILD_ID, buildInfo.get(BUILD_ID));
+        assertEquals("Incorrect Build Product",
+            EXAMPLE_BUILD_PRODUCT, buildInfo.get(BUILD_PRODUCT));
+
+        Set<String> serials = lightResult.getDeviceSerials();
+        assertTrue("Missing device", serials.contains(DEVICE_A));
+        assertTrue("Missing device", serials.contains(DEVICE_B));
+        assertEquals("Expected 2 devices", 2, serials.size());
+        assertTrue("Incorrect devices", serials.contains(DEVICE_A) && serials.contains(DEVICE_B));
+        assertEquals("Incorrect start time", START_MS, lightResult.getStartTime());
+        assertEquals("Incorrect test plan", SUITE_PLAN, lightResult.getTestPlan());
+        List<IModuleResult> modules = lightResult.getModules();
+        assertEquals("Expected 1 completed module", 1, lightResult.getModuleCompleteCount());
+        assertEquals("Expected 2 total modules", 2, modules.size());
+    }
+
+    static void checkResult(IInvocationResult result, boolean newTestFormat) throws Exception {
+        checkResult(result, EXAMPLE_BUILD_FINGERPRINT, newTestFormat, true);
+    }
+
+    static void checkRunHistory(IInvocationResult result) {
+        Map<String, String> buildInfo = result.getInvocationInfo();
+        assertEquals("Incorrect run history", EXAMPLE_RUN_HISTORY, buildInfo.get(RUN_HISTORY));
+    }
+
+    static void checkResult(
+            IInvocationResult result, String expectedBuildFingerprint, boolean newTestFormat,
+            boolean checkResultHistories) throws Exception {
+        assertEquals("Expected 3 passes", 3, result.countResults(TestStatus.PASS));
+        if (checkResultHistories) {
+            assertEquals("Expected 1 failure", 1, result.countResults(TestStatus.FAIL));
+        } else {
+            // CTS Verifier needs to check the condition of the test name with bracket,
+            // so adds one more test with failure result.
+            assertEquals("Expected 2 failure", 2, result.countResults(TestStatus.FAIL));
+        }
+
+        Map<String, String> buildInfo = result.getInvocationInfo();
+        assertEquals("Incorrect Build Fingerprint", expectedBuildFingerprint, result.getBuildFingerprint());
+        assertEquals("Incorrect Build ID", EXAMPLE_BUILD_ID, buildInfo.get(BUILD_ID));
+        assertEquals("Incorrect Build Product",
+            EXAMPLE_BUILD_PRODUCT, buildInfo.get(BUILD_PRODUCT));
+
+        Set<String> serials = result.getDeviceSerials();
+        assertTrue("Missing device", serials.contains(DEVICE_A));
+        assertTrue("Missing device", serials.contains(DEVICE_B));
+        assertEquals("Expected 2 devices", 2, serials.size());
+        assertTrue("Incorrect devices", serials.contains(DEVICE_A) && serials.contains(DEVICE_B));
+        assertEquals("Incorrect start time", START_MS, result.getStartTime());
+        assertEquals("Incorrect test plan", SUITE_PLAN, result.getTestPlan());
+
+        List<IModuleResult> modules = result.getModules();
+        assertEquals("Expected 2 modules", 2, modules.size());
+
+        IModuleResult moduleA = modules.get(0);
+        assertEquals("Expected 1 pass", 1, moduleA.countResults(TestStatus.PASS));
+        assertEquals("Expected 0 failures", 0, moduleA.countResults(TestStatus.FAIL));
+        assertEquals("Incorrect ABI", ABI, moduleA.getAbi());
+        assertEquals("Incorrect name", NAME_A, moduleA.getName());
+        assertEquals("Incorrect ID", ID_A, moduleA.getId());
+        assertEquals("Incorrect runtime", Integer.parseInt(RUNTIME_A), moduleA.getRuntime());
+        List<ICaseResult> moduleACases = moduleA.getResults();
+        assertEquals("Expected 1 test case", 1, moduleACases.size());
+        ICaseResult moduleACase = moduleACases.get(0);
+        assertEquals("Incorrect name", CLASS_A, moduleACase.getName());
+        List<ITestResult> moduleAResults = moduleACase.getResults();
+        assertEquals("Expected 1 result", 1, moduleAResults.size());
+        ITestResult moduleATest1 = moduleAResults.get(0);
+        assertEquals("Incorrect name", METHOD_1, moduleATest1.getName());
+        assertEquals("Incorrect result", TestStatus.PASS, moduleATest1.getResultStatus());
+        assertNull("Unexpected bugreport", moduleATest1.getBugReport());
+        assertNull("Unexpected log", moduleATest1.getLog());
+        assertNull("Unexpected screenshot", moduleATest1.getScreenshot());
+        assertNull("Unexpected message", moduleATest1.getMessage());
+        assertNull("Unexpected stack trace", moduleATest1.getStackTrace());
+        assertNull("Unexpected report", moduleATest1.getReportLog());
+
+        IModuleResult moduleB = modules.get(1);
+        assertEquals("Expected 2 passes", 2, moduleB.countResults(TestStatus.PASS));
+        if (checkResultHistories) {
+            assertEquals("Expected 1 failure", 1, moduleB.countResults(TestStatus.FAIL));
+        } else {
+            // CTS Verifier needs to check the condition of the test name with bracket,
+            // so adds one more test with failure result.
+            assertEquals("Expected 2 failure", 2, moduleB.countResults(TestStatus.FAIL));
+        }
+        assertEquals("Incorrect ABI", ABI, moduleB.getAbi());
+        assertEquals("Incorrect name", NAME_B, moduleB.getName());
+        assertEquals("Incorrect ID", ID_B, moduleB.getId());
+        assertEquals("Incorrect runtime", Integer.parseInt(RUNTIME_B), moduleB.getRuntime());
+        List<ICaseResult> moduleBCases = moduleB.getResults();
+        assertEquals("Expected 1 test case", 1, moduleBCases.size());
+        ICaseResult moduleBCase = moduleBCases.get(0);
+        assertEquals("Incorrect name", CLASS_B, moduleBCase.getName());
+        List<ITestResult> moduleBResults = moduleBCase.getResults();
+        if (checkResultHistories) {
+            assertEquals("Expected 3 results", 3, moduleBResults.size());
+        } else {
+            // CTS Verifier needs to check the condition of the test name with bracket,
+            // so adds one more test with failure result.
+            assertEquals("Expected 4 results", 4, moduleBResults.size());
+        }
+        ITestResult moduleBTest3 = moduleBResults.get(0);
+        assertEquals("Incorrect name", METHOD_3, moduleBTest3.getName());
+        assertEquals("Incorrect result", TestStatus.FAIL, moduleBTest3.getResultStatus());
+        assertEquals("Incorrect bugreport", BUG_REPORT, moduleBTest3.getBugReport());
+        assertEquals("Incorrect log", LOGCAT, moduleBTest3.getLog());
+        assertEquals("Incorrect screenshot", SCREENSHOT, moduleBTest3.getScreenshot());
+        assertEquals("Incorrect message", MESSAGE, moduleBTest3.getMessage());
+        assertEquals("Incorrect stack trace", STACK_TRACE, moduleBTest3.getStackTrace());
+        assertNull("Unexpected report", moduleBTest3.getReportLog());
+        List<TestResultHistory> resultHistories = moduleBTest3.getTestResultHistories();
+        // Check if unit tests do parsing result, because tests for CTS Verifier do not parse it.
+        if (checkResultHistories) {
+            // For xTS except CTS Verifier.
+            assertNull("Unexpected test result history list", resultHistories);
+        } else {
+            // For CTS Verifier.
+            assertNotNull("Expected test result history list", resultHistories);
+            assertEquals("Expected 1 test result history", 1, resultHistories.size());
+            for (TestResultHistory resultHistory : resultHistories) {
+                assertNotNull("Expected test result history", resultHistory);
+                assertEquals(
+                        "Incorrect test name",
+                        SUB_METHOD_3,
+                        resultHistory.getSubTestName(METHOD_3, resultHistory.getTestName()));
+                for (TestResultHistory.ExecutionRecord execRecord :
+                        resultHistory.getExecutionRecords()) {
+                    assertEquals(
+                            "Incorrect test start time", TEST_START_MS, execRecord.getStartTime());
+                    assertEquals("Incorrect test end time", TEST_END_MS, execRecord.getEndTime());
+                    assertEquals(
+                            "Incorrect test is automated",
+                            TEST_IS_AUTOMATED,
+                            execRecord.getIsAutomated());
+                }
+            }
+        }
+        ITestResult moduleBTest4 = moduleBResults.get(1);
+        assertEquals("Incorrect name", METHOD_4, moduleBTest4.getName());
+        assertEquals("Incorrect result", TestStatus.PASS, moduleBTest4.getResultStatus());
+        assertNull("Unexpected bugreport", moduleBTest4.getBugReport());
+        assertNull("Unexpected log", moduleBTest4.getLog());
+        assertNull("Unexpected screenshot", moduleBTest4.getScreenshot());
+        assertNull("Unexpected message", moduleBTest4.getMessage());
+        assertNull("Unexpected stack trace", moduleBTest4.getStackTrace());
+        if (!newTestFormat) {
+            ReportLog report = moduleBTest4.getReportLog();
+            assertNotNull("Expected report", report);
+            ReportLog.Metric summary = report.getSummary();
+            assertNotNull("Expected report summary", summary);
+            assertEquals("Incorrect source", SUMMARY_SOURCE, summary.getSource());
+            assertEquals("Incorrect message", SUMMARY_MESSAGE, summary.getMessage());
+            assertEquals("Incorrect type", ResultType.HIGHER_BETTER, summary.getType());
+            assertEquals("Incorrect unit", ResultUnit.SCORE, summary.getUnit());
+            assertTrue(
+                    "Incorrect values",
+                    Arrays.equals(new double[] {SUMMARY_VALUE}, summary.getValues()));
+        }
+        ITestResult moduleBTest5 = moduleBResults.get(2);
+        assertEquals("Incorrect name", METHOD_5, moduleBTest5.getName());
+        assertEquals("Incorrect result", TestStatus.PASS, moduleBTest5.getResultStatus());
+        assertTrue("Expected skipped", moduleBTest5.isSkipped());
+        assertNull("Unexpected bugreport", moduleBTest5.getBugReport());
+        assertNull("Unexpected log", moduleBTest5.getLog());
+        assertNull("Unexpected screenshot", moduleBTest5.getScreenshot());
+        assertNull("Unexpected message", moduleBTest5.getMessage());
+        assertNull("Unexpected stack trace", moduleBTest5.getStackTrace());
+        assertNull("Unexpected report", moduleBTest5.getReportLog());
+        if (!checkResultHistories) {
+            // CTS Verifier needs to check the condition of the test name with bracket,
+            // so adds one more test with failure result.
+            ITestResult moduleBTest6 = moduleBResults.get(3);
+            assertEquals("Incorrect name", METHOD_6_BRACKETS, moduleBTest6.getName());
+            assertEquals("Incorrect result", TestStatus.FAIL, moduleBTest6.getResultStatus());
+            List<TestResultHistory> resultHistories2 = moduleBTest6.getTestResultHistories();
+            assertNotNull("Expected test result history list", resultHistories2);
+            assertEquals("Expected 1 test result history", 1, resultHistories2.size());
+            for (TestResultHistory resultHistory : resultHistories2) {
+                assertNotNull("Expected test result history", resultHistory);
+                assertEquals(
+                        "Incorrect test name",
+                        SUB_METHOD_6_BRACKETS,
+                        resultHistory.getSubTestName(
+                                METHOD_6_BRACKETS, resultHistory.getTestName()));
+                for (TestResultHistory.ExecutionRecord execRecord :
+                        resultHistory.getExecutionRecords()) {
+                    assertEquals(
+                            "Incorrect test start time", TEST_START_MS, execRecord.getStartTime());
+                    assertEquals("Incorrect test end time", TEST_END_MS, execRecord.getEndTime());
+                    assertEquals(
+                            "Incorrect test is automated",
+                            TEST_IS_AUTOMATED,
+                            execRecord.getIsAutomated());
+                }
+            }
+        }
+    }
+
+    /** Return all XML nodes that match the given xPathExpression. */
+    private NodeList getXmlNodes(String xml, String xPathExpression)
+            throws XPathExpressionException {
+
+        InputSource inputSource = new InputSource(new StringReader(xml));
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        return (NodeList) xpath.evaluate(xPathExpression, inputSource, XPathConstants.NODESET);
+    }
+
+    /** Assert that the XML contains a node matching the given xPathExpression. */
+    private NodeList assertXmlContainsNode(String xml, String xPathExpression)
+            throws XPathExpressionException {
+        NodeList nodes = getXmlNodes(xml, xPathExpression);
+        assertNotNull(
+                String.format("XML '%s' returned null for xpath '%s'.", xml, xPathExpression),
+                nodes);
+        assertTrue(
+                String.format(
+                        "XML '%s' should have returned at least 1 node for xpath '%s', "
+                                + "but returned %s nodes instead.",
+                        xml, xPathExpression, nodes.getLength()),
+                nodes.getLength() >= 1);
+        return nodes;
+    }
+
+    /**
+     * Assert that the XML contains a node matching the given xPathExpression and that the node has
+     * a given value.
+     */
+    private void assertXmlContainsAttribute(
+            String xml, String xPathExpression, String attributeName, String attributeValue)
+            throws XPathExpressionException {
+        NodeList nodes = assertXmlContainsNode(xml, xPathExpression);
+        boolean found = false;
+
+        for (int i = 0; i < nodes.getLength(); i++) {
+            Element element = (Element) nodes.item(i);
+            String value = element.getAttribute(attributeName);
+            if (attributeValue.equals(value)) {
+                found = true;
+                break;
+            }
+        }
+
+        assertTrue(
+                String.format(
+                        "xPath '%s' should contain attribute '%s' but does not. XML: '%s'",
+                        xPathExpression, attributeName, xml),
+                found);
+    }
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/StatTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/StatTest.java
new file mode 100644
index 0000000..6e53d48
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/StatTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 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.compatibility.common.util;
+
+import com.android.compatibility.common.util.Stat;
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for the {@link Stat} class.
+ */
+public class StatTest extends TestCase {
+
+    /**
+     * Test {@link Stat#get95PercentileValue(double[])}.
+     */
+    public void testGet95PercentileValue() {
+        double[] values = new double[100];
+        for (int i = 0; i < 100; i++) {
+            values[i] = i;
+        }
+        assertEquals(95, (int) Stat.get95PercentileValue(values));
+
+        values = new double[1000];
+        for (int i = 0; i < 1000; i++) {
+            values[i] = i;
+        }
+        assertEquals(950, (int) Stat.get95PercentileValue(values));
+
+        values = new double[100];
+        for (int i = 0; i < 100; i++) {
+            values[i] = i * i;
+        }
+        assertEquals(95 * 95, (int) Stat.get95PercentileValue(values));
+    }
+
+    /**
+     * Test {@link Stat#getAverage(double[])}.
+     */
+    public void testGetAverage() {
+        double[] values = new double[]{0, 1, 2, 3, 4};
+        double average = Stat.getAverage(values);
+        assertEquals(2.0, average, 0.00001);
+
+        values = new double[]{1, 2, 3, 4, 5};
+        average = Stat.getAverage(values);
+        assertEquals(3.0, average, 0.00001);
+
+        values = new double[]{0, 1, 4, 9, 16};
+        average = Stat.getAverage(values);
+        assertEquals(6.0, average, 0.00001);
+    }
+
+    /**
+     * Test standard deviation.
+     */
+    public void testGetStandardDeviation() {
+        double[] values = new double[]{0, 1, 2, 3, 4};
+        double stddev = Stat.getStat(values).mStddev;
+        assertEquals(Math.sqrt(2.5), stddev, 0.00001);
+
+        values = new double[]{1, 2, 3, 4, 5};
+        stddev = Stat.getStat(values).mStddev;
+        assertEquals(Math.sqrt(2.5), stddev, 0.00001);
+
+        values = new double[]{0, 2, 4, 6, 8};
+        stddev = Stat.getStat(values).mStddev;
+        assertEquals(Math.sqrt(10.0), stddev, 0.00001);
+    }
+
+
+}
diff --git a/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/TestResultTest.java b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/TestResultTest.java
new file mode 100644
index 0000000..5e4431e
--- /dev/null
+++ b/libraries/compatibility-common-util/tests/src/com/android/compatibility/common/util/TestResultTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 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.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link TestResult}
+ */
+public class TestResultTest extends TestCase {
+
+    private static final String CLASS = "android.test.FoorBar";
+    private static final String METHOD_1 = "testBlah1";
+    private static final String TEST_1 = String.format("%s#%s", CLASS, METHOD_1);
+    private CaseResult mCase;
+    private TestResult mResult;
+
+    @Override
+    public void setUp() throws Exception {
+        mCase = new CaseResult(CLASS);
+        mResult = new TestResult(mCase, METHOD_1);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mResult = null;
+    }
+
+    public void testAccessors() throws Exception {
+        assertEquals("Incorrect test name", METHOD_1, mResult.getName());
+        assertEquals("Incorrect full name", TEST_1, mResult.getFullName());
+    }
+
+}
\ No newline at end of file