Merge "Add support for analysis of OTA package."
diff --git a/python-packages/gdbrunner/__init__.py b/python-packages/gdbrunner/__init__.py
index b69069d..4446fcb 100644
--- a/python-packages/gdbrunner/__init__.py
+++ b/python-packages/gdbrunner/__init__.py
@@ -197,7 +197,7 @@
         gdbserver_output_path = os.path.join(tempfile.gettempdir(),
                                              "gdbclient.log")
         print("Redirecting gdbserver output to {}".format(gdbserver_output_path))
-    gdbserver_output = file(gdbserver_output_path, 'w')
+    gdbserver_output = open(gdbserver_output_path, 'w')
     return device.shell_popen(gdbserver_cmd, stdout=gdbserver_output,
                               stderr=gdbserver_output)
 
@@ -275,7 +275,7 @@
 
     for path, found_locally in generate_files():
         if os.path.isfile(path):
-            return (open(path, "r"), found_locally)
+            return (open(path, "rb"), found_locally)
     raise RuntimeError('Could not find executable {}'.format(executable_path))
 
 def find_executable_path(device, executable_name, run_as_cmd=None):
@@ -318,14 +318,14 @@
         binary = binary_file.read(0x14)
     except IOError:
         raise RuntimeError("failed to read binary file")
-    ei_class = ord(binary[0x4]) # 1 = 32-bit, 2 = 64-bit
-    ei_data = ord(binary[0x5]) # Endianness
+    ei_class = binary[0x4] # 1 = 32-bit, 2 = 64-bit
+    ei_data = binary[0x5] # Endianness
 
     assert ei_class == 1 or ei_class == 2
     if ei_data != 1:
         raise RuntimeError("binary isn't little-endian?")
 
-    e_machine = ord(binary[0x13]) << 8 | ord(binary[0x12])
+    e_machine = binary[0x13] << 8 | binary[0x12]
     if e_machine == 0x28:
         assert ei_class == 1
         return "arm"
@@ -338,11 +338,6 @@
     elif e_machine == 0x3E:
         assert ei_class == 2
         return "x86_64"
-    elif e_machine == 0x08:
-        if ei_class == 1:
-            return "mips"
-        else:
-            return "mips64"
     else:
         raise RuntimeError("unknown architecture: 0x{:x}".format(e_machine))
 
@@ -368,7 +363,7 @@
 
     # Windows disallows opening the file while it's open for writing.
     script_fd, script_path = tempfile.mkstemp()
-    os.write(script_fd, gdb_commands)
+    os.write(script_fd, gdb_commands.encode())
     os.close(script_fd)
     if lldb:
         script_parameter = "--source"
diff --git a/samples/ApiDemos/Android.bp b/samples/ApiDemos/Android.bp
new file mode 100644
index 0000000..32ae196
--- /dev/null
+++ b/samples/ApiDemos/Android.bp
@@ -0,0 +1,21 @@
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+    name: "ApiDemos",
+    // Only compile source java files in this apk.
+    srcs: [
+        "src/**/*.java",
+        "src/com/example/android/apis/app/IRemoteService.aidl",
+        "src/com/example/android/apis/app/IRemoteServiceCallback.aidl",
+        "src/com/example/android/apis/app/ISecondary.aidl",
+    ],
+    static_libs: ["androidx.legacy_legacy-support-v4"],
+    sdk_version: "current",
+    dex_preopt: {
+        enabled: false,
+    },
+    test_suites: ["device-tests"],
+}
diff --git a/samples/ApiDemos/Android.mk b/samples/ApiDemos/Android.mk
deleted file mode 100644
index 9bc1ba0..0000000
--- a/samples/ApiDemos/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := samples tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    src/com/example/android/apis/app/IRemoteService.aidl \
-    src/com/example/android/apis/app/IRemoteServiceCallback.aidl \
-    src/com/example/android/apis/app/ISecondary.aidl \
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.legacy_legacy-support-v4
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PACKAGE_NAME := ApiDemos
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
-# Use the folloing include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/ApiDemos/tests/Android.bp b/samples/ApiDemos/tests/Android.bp
new file mode 100644
index 0000000..abb7fd7
--- /dev/null
+++ b/samples/ApiDemos/tests/Android.bp
@@ -0,0 +1,21 @@
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+    name: "ApiDemosTests",
+    // We only want this apk build for tests.
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    static_libs: ["junit"],
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    // Notice that we don't have to include the src files of ApiDemos because, by
+    // running the tests using an instrumentation targeting ApiDemos, we
+    // automatically get all of its classes loaded into our environment.
+    instrumentation_for: "ApiDemos",
+    sdk_version: "current",
+}
diff --git a/samples/ApiDemos/tests/Android.mk b/samples/ApiDemos/tests/Android.mk
deleted file mode 100644
index ed37fbe..0000000
--- a/samples/ApiDemos/tests/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Notice that we don't have to include the src files of ApiDemos because, by
-# running the tests using an instrumentation targeting ApiDemos, we
-# automatically get all of its classes loaded into our environment.
-
-LOCAL_PACKAGE_NAME := ApiDemosTests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-
-LOCAL_INSTRUMENTATION_FOR := ApiDemos
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/scripts/Android.bp b/scripts/Android.bp
index a3fb2c7..143fdfd 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -24,17 +24,6 @@
 }
 
 python_test_host {
-    name: "python-native_heapdump_viewer_test",
-    main: "native_heapdump_viewer_tests.py",
-    srcs: [
-        "native_heapdump_viewer.py",
-        "native_heapdump_viewer_tests.py",
-    ],
-    test_config: "native_heapdump_viewer-tests.xml",
-    test_suites: ["general-tests"],
-}
-
-python_test_host {
     name: "python-symbol_test",
     main: "symbol.py",
     // Would be nice to use the library above, but as it's single-source
diff --git a/scripts/TEST_MAPPING b/scripts/TEST_MAPPING
index 1d2b9d0..b052da9 100644
--- a/scripts/TEST_MAPPING
+++ b/scripts/TEST_MAPPING
@@ -1,9 +1,6 @@
 {
   "presubmit": [
     {
-      "name": "python-native_heapdump_viewer_test"
-    },
-    {
       "name": "python-symbol_test"
     }
   ]
diff --git a/scripts/gdb/dalvik.gdb b/scripts/gdb/dalvik.gdb
deleted file mode 100644
index 0bedf64..0000000
--- a/scripts/gdb/dalvik.gdb
+++ /dev/null
@@ -1,72 +0,0 @@
-#
-# 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.
-
-# ART debugging.  ART uses SIGSEGV signals for internal purposes.  To allow
-# gdb to debug programs using ART we need to treat this signal specially.  We
-# also set a breakpoint in a libart.so function to stop when the program
-# hits an unexpected breakpoint
-set $art_debug_enabled = 0
-define art-on
-    if $art_debug_enabled == 0
-        # deal with SIGSEGV signals
-        handle SIGSEGV noprint nostop pass
-
-        # set a breakpoint and record its number
-        set breakpoint pending on
-        break art_sigsegv_fault
-        set $art_bpnum = $bpnum
-        commands $art_bpnum
-        silent
-        printf "Caught SIGSEGV in user program\n"
-        end
-        set breakpoint pending auto
-
-        printf "ART debugging mode is enabled.\n"
-        printf "If you are debugging a native only process, you need to\n"
-        printf "re-enable normal SIGSEGV handling using this command:\n"
-        printf "  handle SIGSEGV print stop\n"
-        set $art_debug_enabled = 1
-    else
-        printf "ART debugging mode is already enabled.\n"
-    end
-end
-
-document art-on
-    Enter ART debugging mode. In ART debugging mode, SIGSEGV signals are ignored
-    by gdb unless they are not handled by ART itself.  A breakpoint is
-    set to stop the program when an unexpected SIGSEGV signal is
-    encountered.
-
-    To switch ART debugging mode off, use "art-off"
-end
-
-define art-off
-    if $art_debug_enabled == 1
-        # restore SIGSEGV to its default
-        handle SIGSEGV print stop pass
-
-        # delete our breakpoint
-        delete $art_bpnum
-
-        set $art_debug_enabled = 0
-        printf "ART debugging mode is disabled.\n"
-    end
-end
-
-document art-off
-    Leave ART debugging mode.  Signal handling is restored to default settings.
-
-    Use the command "art-on" to enable ART debugging mode.
-end
diff --git a/scripts/gdbclient.py b/scripts/gdbclient.py
index 61fac40..5d4475a 100755
--- a/scripts/gdbclient.py
+++ b/scripts/gdbclient.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2015 The Android Open Source Project
 #
diff --git a/scripts/native_heapdump_viewer-tests.xml b/scripts/native_heapdump_viewer-tests.xml
deleted file mode 100644
index 25d5623..0000000
--- a/scripts/native_heapdump_viewer-tests.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<configuration description="Config for python tradefed symbol test">
-    <option name="test-suite-tag" value="python-native_heapdump_viewer_test" />
-    <test class="com.android.tradefed.testtype.python.PythonBinaryHostTest" >
-        <option name="par-file-name" value="python-native_heapdump_viewer_test" />
-        <option name="test-timeout" value="2m" />
-    </test>
-</configuration>
diff --git a/scripts/native_heapdump_viewer.py b/scripts/native_heapdump_viewer.py
deleted file mode 100755
index 9b2a6e5..0000000
--- a/scripts/native_heapdump_viewer.py
+++ /dev/null
@@ -1,482 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-
-"""Generates a human-interpretable view of a native heap dump from 'am dumpheap -n'."""
-
-import logging
-import os
-import os.path
-import re
-import subprocess
-import sys
-import zipfile
-
-class Args:
-  _usage = """
-Usage:
-1. Collect a native heap dump from the device. For example:
-   $ adb shell stop
-   $ adb shell setprop libc.debug.malloc.program app_process
-   $ adb shell setprop libc.debug.malloc.options backtrace=64
-   $ adb shell start
-    (launch and use app)
-   $ adb shell am dumpheap -n <pid> /data/local/tmp/native_heap.txt
-   $ adb pull /data/local/tmp/native_heap.txt
-
-2. Run the viewer:
-   $ python native_heapdump_viewer.py [options] native_heap.txt
-      [--verbose]: verbose output
-      [--html]: interactive html output
-      [--reverse]: reverse the backtraces (start the tree from the leaves)
-      [--symbols SYMBOL_DIR] SYMBOL_DIR is the directory containing the .so files with symbols.
-                 Defaults to $ANDROID_PRODUCT_OUT/symbols
-      [--app-symbols SYMBOL_DIR] SYMBOL_DIR is the directory containing the app APK and so files.
-                 Defaults to the current directory.
-   This outputs a file with lines of the form:
-
-      5831776  29.09% 100.00%    10532     71b07bc0b0 /system/lib64/libandroid_runtime.so Typeface_createFromArray frameworks/base/core/jni/android/graphics/Typeface.cpp:68
-
-   5831776 is the total number of bytes allocated at this stack frame, which
-   is 29.09% of the total number of bytes allocated and 100.00% of the parent
-   frame's bytes allocated. 10532 is the total number of allocations at this
-   stack frame. 71b07bc0b0 is the address of the stack frame.
-"""
-
-  def __init__(self):
-    self.verbose = False
-    self.html_output = False
-    self.reverse_frames = False
-    product_out = os.getenv("ANDROID_PRODUCT_OUT")
-    if product_out:
-      self.symboldir = product_out + "/symbols"
-    else:
-      self.symboldir = "./symbols"
-    self.app_symboldir = ""
-
-    i = 1
-    extra_args = []
-    while i < len(sys.argv):
-      if sys.argv[i] == "--symbols":
-        i += 1
-        self.symboldir = sys.argv[i] + "/"
-      elif sys.argv[i] == "--app-symbols":
-        i += 1
-        self.app_symboldir = sys.argv[i] + "/"
-      elif sys.argv[i] == "--verbose":
-        self.verbose = True
-      elif sys.argv[i] == "--html":
-        self.html_output = True
-      elif sys.argv[i] == "--reverse":
-        self.reverse_frames = True
-      elif sys.argv[i][0] == '-':
-        print("Invalid option %s" % (sys.argv[i]))
-      else:
-        extra_args.append(sys.argv[i])
-      i += 1
-
-    if len(extra_args) != 1:
-      print(self._usage)
-      sys.exit(1)
-
-    self.native_heap = extra_args[0]
-
-class Backtrace:
-  def __init__(self, is_zygote, size, num_allocs, frames):
-    self.is_zygote = is_zygote
-    self.size = size
-    self.num_allocs = num_allocs
-    self.frames = frames
-
-class Mapping:
-  def __init__(self, start, end, offset, name):
-    self.start = start
-    self.end = end
-    self.offset = offset
-    self.name = name
-
-class FrameDescription:
-  def __init__(self, function, location, library):
-    self.function = function
-    self.location = location
-    self.library = library
-
-def GetVersion(native_heap):
-  """Get the version of the native heap dump."""
-
-  re_line = re.compile("Android\s+Native\s+Heap\s+Dump\s+(?P<version>v\d+\.\d+)\s*$")
-  matched = 0
-  with open(native_heap, "r") as f:
-    for line in f:
-      m = re_line.match(line)
-      if m:
-        return m.group('version')
-  return None
-
-def GetNumFieldValidByParsingLines(native_heap):
-  """Determine if the num field is valid by parsing the backtrace lines.
-
-  Malloc debug for N incorrectly set the num field to the number of
-  backtraces instead of the number of allocations with the same size and
-  backtrace. Read the file and if at least three lines all have the field
-  set to the number of backtraces values, then consider this generated by
-  the buggy malloc debug and indicate the num field is not valid.
-
-  Returns:
-    True if the num field is valid.
-    False if the num field is not valid and should be ignored.
-  """
-
-  re_backtrace = re.compile("Backtrace\s+size:\s+(?P<backtrace_size>\d+)")
-
-  re_line = re.compile("z\s+(?P<zygote>\d+)\s+sz\s+(?P<size>\d+)\s+num\s+(?P<num_allocations>\d+)")
-  matched = 0
-  backtrace_size = 0
-  with open(native_heap, "r") as f:
-    for line in f:
-      if backtrace_size == 0:
-        m = re_backtrace.match(line)
-        if m:
-          backtrace_size = int(m.group('backtrace_size'))
-      parts = line.split()
-      if len(parts) > 7 and parts[0] == "z" and parts[2] == "sz":
-        m = re_line.match(line)
-        if m:
-          num_allocations = int(m.group('num_allocations'))
-          if num_allocations == backtrace_size:
-            # At least three lines must match this pattern before
-            # considering this the old buggy version of malloc debug.
-            matched += 1
-            if matched == 3:
-              return False
-          else:
-            return True
-  return matched == 0
-
-def GetNumFieldValid(native_heap):
-  version = GetVersion(native_heap)
-  if not version or version == "v1.0":
-    # Version v1.0 was produced by a buggy version of malloc debug where the
-    # num field was set incorrectly.
-    # Unfortunately, Android P produced a v1.0 version that does set the
-    # num field. Do one more check to see if this is the broken version.
-    return GetNumFieldValidByParsingLines(native_heap)
-  else:
-    return True
-
-def GetMappingFromOffset(mapping, app_symboldir):
-  """
-  If the input mapping is a zip file, translate the contained uncompressed files and add mapping
-  entries.
-
-  This is done to handle symbols for the uncompressed .so files inside APKs. With the replaced
-  mappings, the script looks up the .so files as separate files.
-  """
-  basename = os.path.basename(mapping.name)
-  zip_name = app_symboldir + basename
-  if os.path.isfile(zip_name):
-    opened_zip = zipfile.ZipFile(zip_name)
-    if opened_zip:
-      # For all files in the zip, add mappings for the internal files.
-      for file_info in opened_zip.infolist():
-        # Only add stored files since it doesn't make sense to have PC into compressed ones.
-        if file_info.compress_type == zipfile.ZIP_STORED:
-          zip_header_entry_size = 30
-          data_offset = (file_info.header_offset
-              + zip_header_entry_size
-              + len(file_info.filename)
-              + len(file_info.extra)
-              + len(file_info.comment))
-          end_offset = data_offset + file_info.file_size
-          if mapping.offset >= data_offset and mapping.offset < end_offset:
-            # Round up the data_offset to the nearest page since the .so must be aligned.
-            so_file_alignment = 4096
-            data_offset += so_file_alignment - 1;
-            data_offset -= data_offset % so_file_alignment;
-            mapping.name = file_info.filename
-            mapping.offset -= data_offset
-            break
-  return mapping
-
-def ParseNativeHeap(native_heap, reverse_frames, num_field_valid, app_symboldir):
-  """Parse the native heap into backtraces, maps.
-
-  Returns two lists, the first is a list of all of the backtraces, the
-  second is the sorted list of maps.
-  """
-
-  backtraces = []
-  mappings = []
-
-  re_map = re.compile("(?P<start>[0-9a-f]+)-(?P<end>[0-9a-f]+) .... (?P<offset>[0-9a-f]+) [0-9a-f]+:[0-9a-f]+ [0-9]+ +(?P<name>.*)")
-
-  with open(native_heap, "r") as f:
-    for line in f:
-      # Format of line:
-      #   z 0  sz       50  num    1  bt 000000000000a100 000000000000b200
-      parts = line.split()
-      if len(parts) > 7 and parts[0] == "z" and parts[2] == "sz":
-        is_zygote = parts[1] != "1"
-        size = int(parts[3])
-        if num_field_valid:
-          num_allocs = int(parts[5])
-        else:
-          num_allocs = 1
-        frames = list(map(lambda x: int(x, 16), parts[7:]))
-        if reverse_frames:
-          frames = list(reversed(frames))
-        backtraces.append(Backtrace(is_zygote, size, num_allocs, frames))
-      else:
-        # Parse map line:
-        #   720de01000-720ded7000 r-xp 00000000 fd:00 495  /system/lib64/libc.so
-        m = re_map.match(line)
-        if m:
-          # Offset of mapping start
-          start = int(m.group('start'), 16)
-          # Offset of mapping end
-          end = int(m.group('end'), 16)
-          # Offset within file that is mapped
-          offset = int(m.group('offset'), 16)
-          name = m.group('name')
-          mappings.append(GetMappingFromOffset(Mapping(start, end, offset, name), app_symboldir))
-  return backtraces, mappings
-
-def FindMapping(mappings, addr):
-  """Find the mapping given addr.
-
-  Returns the mapping that contains addr.
-  Returns None if there is no such mapping.
-  """
-
-  min = 0
-  max = len(mappings) - 1
-  while True:
-    if max < min:
-      return None
-    mid = (min + max) // 2
-    if mappings[mid].end <= addr:
-      min = mid + 1
-    elif mappings[mid].start > addr:
-      max = mid - 1
-    else:
-      return mappings[mid]
-
-
-def ResolveAddrs(html_output, symboldir, app_symboldir, backtraces, mappings):
-  """Resolve address libraries and offsets.
-
-  addr_offsets maps addr to .so file offset
-  addrs_by_lib maps library to list of addrs from that library
-  Resolved addrs maps addr to FrameDescription
-
-  Returns the resolved_addrs hash.
-  """
-
-  addr_offsets = {}
-  addrs_by_lib = {}
-  resolved_addrs = {}
-  empty_frame_description = FrameDescription("???", "???", "???")
-  for backtrace in backtraces:
-    for addr in backtrace.frames:
-      if addr in addr_offsets:
-        continue
-      mapping = FindMapping(mappings, addr)
-      if mapping:
-        addr_offsets[addr] = addr - mapping.start + mapping.offset
-        if not (mapping.name in addrs_by_lib):
-          addrs_by_lib[mapping.name] = []
-        addrs_by_lib[mapping.name].append(addr)
-      else:
-        resolved_addrs[addr] = empty_frame_description
-
-  # Resolve functions and line numbers.
-  if html_output == False:
-    print("Resolving symbols using directory %s..." % symboldir)
-
-  for lib in addrs_by_lib:
-    sofile = app_symboldir + lib
-    if not os.path.isfile(sofile):
-      sofile = symboldir + lib
-    if os.path.isfile(sofile):
-      file_offset = 0
-      result = subprocess.check_output(["objdump", "-w", "-j", ".text", "-h", sofile])
-      for line in result.split("\n"):
-        splitted = line.split()
-        if len(splitted) > 5 and splitted[1] == ".text":
-          file_offset = int(splitted[5], 16)
-          break
-
-      input_addrs = ""
-      for addr in addrs_by_lib[lib]:
-        input_addrs += "%s\n" % hex(addr_offsets[addr] - file_offset)
-
-      p = subprocess.Popen(["addr2line", "-C", "-j", ".text", "-e", sofile, "-f"], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
-      result = p.communicate(input_addrs)[0]
-      addr2line_rc = p.returncode
-      if addr2line_rc and (addr2line_rc < 0):
-        logging.warn("addr2line on " + sofile + " terminated by signal " + str(-1 * addr2line_rc))
-      splitted = result.split("\n")
-      for x in range(0, len(addrs_by_lib[lib])):
-        try:
-          function = splitted[2*x];
-          location = splitted[2*x+1];
-          resolved_addrs[addrs_by_lib[lib][x]] = FrameDescription(function, location, lib)
-        except Exception:
-          logging.warn("exception while resolving symbols", exc_info=True)
-          resolved_addrs[addrs_by_lib[lib][x]] = FrameDescription("---", "---", lib)
-    else:
-      if html_output == False:
-        print("%s not found for symbol resolution" % lib)
-
-      fd = FrameDescription("???", "???", lib)
-      for addr in addrs_by_lib[lib]:
-        resolved_addrs[addr] = fd
-
-  return resolved_addrs
-
-def Addr2Line(resolved_addrs, addr):
-  if addr == "ZYGOTE" or addr == "APP":
-    return FrameDescription("", "", "")
-
-  return resolved_addrs[int(addr, 16)]
-
-class AddrInfo:
-  def __init__(self, addr):
-    self.addr = addr
-    self.size = 0
-    self.number = 0
-    self.num_allocs = 0
-    self.children = {}
-
-  def addStack(self, size, num_allocs, stack):
-    self.size += size * num_allocs
-    self.number += num_allocs
-    if len(stack) > 0:
-      child = stack[0]
-      if not (child.addr in self.children):
-        self.children[child.addr] = child
-      self.children[child.addr].addStack(size, num_allocs, stack[1:])
-
-def Display(resolved_addrs, indent, total, parent_total, node):
-  fd = Addr2Line(resolved_addrs, node.addr)
-  total_percent = 0
-  if total != 0:
-    total_percent = 100 * node.size / float(total)
-  parent_percent = 0
-  if parent_total != 0:
-    parent_percent = 100 * node.size / float(parent_total)
-  print("%9d %6.2f%% %6.2f%% %8d %s%s %s %s %s" % (node.size, total_percent, parent_percent, node.number, indent, node.addr, fd.library, fd.function, fd.location))
-  children = sorted(node.children.values(), key=lambda x: x.size, reverse=True)
-  for child in children:
-    Display(resolved_addrs, indent + "  ", total, node.size, child)
-
-def DisplayHtml(verbose, resolved_addrs, total, node, extra, label_count):
-  fd = Addr2Line(resolved_addrs, node.addr)
-  if verbose:
-    lib = fd.library
-  else:
-    lib = os.path.basename(fd.library)
-  total_percent = 0
-  if total != 0:
-    total_percent = 100 * node.size / float(total)
-  label = "%d %6.2f%% %6d %s%s %s %s" % (node.size, total_percent, node.number, extra, lib, fd.function, fd.location)
-  label = label.replace("&", "&amp;")
-  label = label.replace("'", "&apos;")
-  label = label.replace('"', "&quot;")
-  label = label.replace("<", "&lt;")
-  label = label.replace(">", "&gt;")
-  children = sorted(node.children.values(), key=lambda x: x.size, reverse=True)
-  print('<li>')
-  if len(children) > 0:
-    print('<label for="' + str(label_count) + '">' + label + '</label>')
-    print('<input type="checkbox" id="' + str(label_count) + '"/>')
-    print('<ol>')
-    label_count += 1
-    for child in children:
-      label_count = DisplayHtml(verbose, resolved_addrs, total, child, "", label_count)
-    print('</ol>')
-  else:
-    print(label)
-  print('</li>')
-
-  return label_count
-
-def CreateHtml(verbose, app, zygote, resolved_addrs):
-  print("""
-<!DOCTYPE html>
-<html><head><style>
-li input {
-    display: none;
-}
-li input:checked + ol > li {
-    display: block;
-}
-li input + ol > li {
-    display: none;
-}
-li {
-    font-family: Roboto Mono,monospace;
-}
-label {
-    font-family: Roboto Mono,monospace;
-    cursor: pointer
-}
-</style></head><body>Native allocation HTML viewer<br><br>
-Click on an individual line to expand/collapse to see the details of the
-allocation data<ol>
-""")
-
-  label_count = 0
-  label_count = DisplayHtml(verbose, resolved_addrs, app.size, app, "app ", label_count)
-  if zygote.size > 0:
-    DisplayHtml(verbose, resolved_addrs, zygote.size, zygote, "zygote ", label_count)
-  print("</ol></body></html>")
-
-def main():
-  args = Args()
-
-  num_field_valid = GetNumFieldValid(args.native_heap)
-
-  backtraces, mappings = ParseNativeHeap(args.native_heap, args.reverse_frames, num_field_valid,
-      args.app_symboldir)
-  # Resolve functions and line numbers
-  resolved_addrs = ResolveAddrs(args.html_output, args.symboldir, args.app_symboldir, backtraces,
-      mappings)
-
-  app = AddrInfo("APP")
-  zygote = AddrInfo("ZYGOTE")
-
-  for backtrace in backtraces:
-    stack = []
-    for addr in backtrace.frames:
-      stack.append(AddrInfo("%x" % addr))
-    stack.reverse()
-    if backtrace.is_zygote:
-      zygote.addStack(backtrace.size, backtrace.num_allocs, stack)
-    else:
-      app.addStack(backtrace.size, backtrace.num_allocs, stack)
-
-  if args.html_output:
-    CreateHtml(args.verbose, app, zygote, resolved_addrs)
-  else:
-    print("")
-    print("%9s %6s %6s %8s    %s %s %s %s" % ("BYTES", "%TOTAL", "%PARENT", "COUNT", "ADDR", "LIBRARY", "FUNCTION", "LOCATION"))
-    Display(resolved_addrs, "", app.size, app.size + zygote.size, app)
-    print("")
-    Display(resolved_addrs, "", zygote.size, app.size + zygote.size, zygote)
-    print("")
-
-if __name__ == '__main__':
-  main()
diff --git a/scripts/native_heapdump_viewer_tests.py b/scripts/native_heapdump_viewer_tests.py
deleted file mode 100755
index 423d1c8..0000000
--- a/scripts/native_heapdump_viewer_tests.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-
-"""Tests for the native_heapdump_viewer script."""
-
-import native_heapdump_viewer
-import os
-import sys
-import tempfile
-import unittest
-
-class NativeHeapdumpViewerTest(unittest.TestCase):
-  _tmp_file_name = None
-
-  def CreateTmpFile(self, contents):
-    fd, self._tmp_file_name = tempfile.mkstemp()
-    os.write(fd, contents.encode())
-    os.close(fd)
-    return self._tmp_file_name
-
-  def tearDown(self):
-    if self._tmp_file_name:
-      try:
-        os.unlink(self._tmp_file_name)
-      except Exception:
-        print("Failed to delete %s" % (heap))
-
-class GetNumFieldValidTest(NativeHeapdumpViewerTest):
-  _map_data = """
-MAPS
-1000-10000 r-xp 00000000 fd:00 495                            /data/does_not_exist.so
-END
-"""
-
-  _heap_num_field_valid_version10 = """
-Android Native Heap Dump v1.0
-
-Total memory: 33800
-Allocation records: 13
-Backtrace size: 16
-
-z 1  sz   1000  num    4  bt 1000 2000 3000
-z 1  sz   2000  num    6  bt 1100 2100 3100
-z 0  sz   1200  num    1  bt 1200 2200 3200
-z 0  sz   8300  num    2  bt 1300 2300 3300
-"""
-
-  _heap_num_field_invalid_version10 = """
-Android Native Heap Dump v1.0
-
-Total memory: 12500
-Allocation records: 4
-Backtrace size: 16
-
-z 1  sz   1000  num    16  bt 1000 2000 3000
-z 1  sz   2000  num    16  bt 1100 2100 3100
-z 0  sz   1200  num    16  bt 1200 2200 3200
-z 0  sz   8300  num    16  bt 1300 2300 3300
-"""
-
-  _heap_data = """
-
-Total memory: 200000
-Allocation records: 64
-Backtrace size: 16
-
-z 1  sz   1000  num    16  bt 1000 2000 3000
-z 1  sz   2000  num    16  bt 1100 2100 3100
-z 0  sz   1200  num    16  bt 1200 2200 3200
-z 0  sz   8300  num    16  bt 1300 2300 3300
-"""
-
-  def test_version10_valid(self):
-    heap = self.CreateTmpFile(self._heap_num_field_valid_version10 + self._map_data)
-    self.assertTrue(native_heapdump_viewer.GetNumFieldValid(heap))
-
-  def test_version10_invalid(self):
-    heap = self.CreateTmpFile(self._heap_num_field_invalid_version10 + self._map_data)
-    self.assertFalse(native_heapdump_viewer.GetNumFieldValid(heap))
-
-  def test_version11_valid(self):
-    heap = self.CreateTmpFile("Android Native Heap Dump v1.1" + self._heap_data + self._map_data)
-    self.assertTrue(native_heapdump_viewer.GetNumFieldValid(heap))
-
-  def test_version12_valid(self):
-    heap = self.CreateTmpFile("Android Native Heap Dump v1.2" + self._heap_data + self._map_data)
-    self.assertTrue(native_heapdump_viewer.GetNumFieldValid(heap))
-
-class ParseNativeHeapTest(NativeHeapdumpViewerTest):
-  _backtrace_data = """
-z 1  sz   1000  num    4  bt 1000 2000 3000
-z 0  sz   8300  num    5  bt 1300 2300 3300
-"""
-
-
-  def test_backtrace_num_field_valid(self):
-    heap = self.CreateTmpFile(self._backtrace_data)
-    backtraces, mapppings = native_heapdump_viewer.ParseNativeHeap(heap, False, True, "")
-    self.assertTrue(backtraces)
-    self.assertEqual(2, len(backtraces))
-
-    self.assertFalse(backtraces[0].is_zygote)
-    self.assertEqual(1000, backtraces[0].size)
-    self.assertEqual(4, backtraces[0].num_allocs)
-    self.assertEqual([0x1000, 0x2000, 0x3000], backtraces[0].frames)
-
-    self.assertTrue(backtraces[1].is_zygote)
-    self.assertEqual(8300, backtraces[1].size)
-    self.assertEqual(5, backtraces[1].num_allocs)
-    self.assertEqual([0x1300, 0x2300, 0x3300], backtraces[1].frames)
-
-  def test_backtrace_num_field_invalid(self):
-    heap = self.CreateTmpFile(self._backtrace_data)
-    backtraces, mapppings = native_heapdump_viewer.ParseNativeHeap(heap, False, False, "")
-    self.assertTrue(backtraces)
-    self.assertEqual(2, len(backtraces))
-
-    self.assertFalse(backtraces[0].is_zygote)
-    self.assertEqual(1000, backtraces[0].size)
-    self.assertEqual(1, backtraces[0].num_allocs)
-    self.assertEqual([0x1000, 0x2000, 0x3000], backtraces[0].frames)
-
-    self.assertTrue(backtraces[1].is_zygote)
-    self.assertEqual(8300, backtraces[1].size)
-    self.assertEqual(1, backtraces[1].num_allocs)
-    self.assertEqual([0x1300, 0x2300, 0x3300], backtraces[1].frames)
-
-  def test_backtrace_reverse_field_valid(self):
-    heap = self.CreateTmpFile(self._backtrace_data)
-    backtraces, mapppings = native_heapdump_viewer.ParseNativeHeap(heap, True, True, "")
-    self.assertTrue(backtraces)
-    self.assertEqual(2, len(backtraces))
-
-    self.assertFalse(backtraces[0].is_zygote)
-    self.assertEqual(1000, backtraces[0].size)
-    self.assertEqual(4, backtraces[0].num_allocs)
-    self.assertEqual([0x3000, 0x2000, 0x1000], backtraces[0].frames)
-
-    self.assertTrue(backtraces[1].is_zygote)
-    self.assertEqual(8300, backtraces[1].size)
-    self.assertEqual(5, backtraces[1].num_allocs)
-    self.assertEqual([0x3300, 0x2300, 0x1300], backtraces[1].frames)
-
-  def test_mappings(self):
-    map_data = """
-MAPS
-1000-4000 r-xp 00000000 fd:00 495    /system/lib64/libc.so
-6000-8000 r-xp 00000000 fd:00 495
-a000-f000 r-xp 0000b000 fd:00 495    /system/lib64/libutils.so
-END
-"""
-
-    heap = self.CreateTmpFile(map_data)
-    backtraces, mappings = native_heapdump_viewer.ParseNativeHeap(heap, True, True, "")
-
-    self.assertTrue(mappings)
-    self.assertEqual(2, len(mappings))
-
-    self.assertEqual(0x1000, mappings[0].start)
-    self.assertEqual(0x4000, mappings[0].end)
-    self.assertEqual(0, mappings[0].offset)
-    self.assertEqual("/system/lib64/libc.so", mappings[0].name)
-
-    self.assertEqual(0xa000, mappings[1].start)
-    self.assertEqual(0xf000, mappings[1].end)
-    self.assertEqual(0xb000, mappings[1].offset)
-    self.assertEqual("/system/lib64/libutils.so", mappings[1].name)
-
-if __name__ == '__main__':
-  unittest.main(verbosity=2)
diff --git a/scripts/symbol.py b/scripts/symbol.py
index 821da8e..d74d506 100755
--- a/scripts/symbol.py
+++ b/scripts/symbol.py
@@ -438,8 +438,8 @@
   if not _CACHED_CXX_FILT:
     toolchains = None
     # TODO(b/187231324) do not hard-code prebuilt version number below
-    if os.path.exists('./clang-r416183b/bin/llvm-cxxfilt'):
-      toolchains = ["./clang-r416183b/bin/llvm-cxxfilt"]
+    if os.path.exists('./clang-r416183b1/bin/llvm-cxxfilt'):
+      toolchains = ["./clang-r416183b1/bin/llvm-cxxfilt"]
     if not toolchains:
       raise Exception("Could not find llvm-cxxfilt tool")
     _CACHED_CXX_FILT = sorted(toolchains)[-1]
diff --git a/sdk/plat_tools_source.prop_template b/sdk/plat_tools_source.prop_template
index cdbfd93..ae94420 100644
--- a/sdk/plat_tools_source.prop_template
+++ b/sdk/plat_tools_source.prop_template
@@ -1,2 +1,2 @@
 Pkg.UserSrc=false
-Pkg.Revision=31.0.2
+Pkg.Revision=31.0.3