Merge "ART: Continue adding override annotations"
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 34a6469..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,56 +0,0 @@
-// TODO: These should be handled with transitive static library dependencies
-art_static_dependencies = [
-    // Note: the order is important because of static linking resolution.
-    "libziparchive",
-    "libnativehelper",
-    "libnativebridge",
-    "libnativeloader",
-    "libsigchain_dummy",
-    "liblog",
-    "libz",
-    "libbacktrace",
-    "libcutils",
-    "libunwindstack",
-    "libutils",
-    "libbase",
-    "liblz4",
-    "liblzma",
-    "libmetricslogger_static",
-]
-
-subdirs = [
-    "adbconnection",
-    "benchmark",
-    "build",
-    "cmdline",
-    "compiler",
-    "dalvikvm",
-    "dex2oat",
-    "dexdump",
-    "dexlayout",
-    "dexlist",
-    "dexoptanalyzer",
-    "disassembler",
-    "dt_fd_forward",
-    "dt_fd_forward/export",
-    "imgdiag",
-    "libartbase",
-    "libdexfile",
-    "libprofile",
-    "oatdump",
-    "openjdkjvm",
-    "openjdkjvmti",
-    "patchoat",
-    "profman",
-    "runtime",
-    "sigchainlib",
-    "simulator",
-    "test",
-    "tools",
-    "tools/breakpoint-logger",
-    "tools/cpp-define-generator",
-    "tools/dmtracedump",
-    "tools/hiddenapi",
-    "tools/titrace",
-    "tools/wrapagentproperties",
-]
diff --git a/build/art.go b/build/art.go
index 61b1a4e..6c08486 100644
--- a/build/art.go
+++ b/build/art.go
@@ -283,6 +283,7 @@
 	android.RegisterModuleType("art_cc_test_library", artTestLibrary)
 	android.RegisterModuleType("art_cc_defaults", artDefaultsFactory)
 	android.RegisterModuleType("libart_cc_defaults", libartDefaultsFactory)
+	android.RegisterModuleType("libart_static_cc_defaults", libartStaticDefaultsFactory)
 	android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory)
 	android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory)
 }
@@ -336,6 +337,33 @@
 	return module
 }
 
+func libartStaticDefaultsFactory() android.Module {
+	c := &codegenProperties{}
+	module := cc.DefaultsFactory(c)
+	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+		codegen(ctx, c, true)
+
+		type props struct {
+			Target struct {
+				Android struct {
+					Static_libs []string
+				}
+			}
+		}
+
+		p := &props{}
+		// TODO: express this in .bp instead b/79671158
+		if !envTrue(ctx, "ART_TARGET_LINUX") {
+			p.Target.Android.Static_libs = []string{
+				"libmetricslogger_static",
+			}
+		}
+		ctx.AppendProperties(p)
+	})
+
+	return module
+}
+
 func artLibrary() android.Module {
 	m, _ := cc.NewLibrary(android.HostAndDeviceSupported)
 	module := m.Init()
diff --git a/compiler/Android.bp b/compiler/Android.bp
index c365537..c2f8e3c 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -191,6 +191,15 @@
     export_include_dirs: ["."],
 }
 
+cc_defaults {
+    name: "libart-compiler_static_base_defaults",
+    static_libs: [
+        "libbase",
+        "libcutils",
+        "liblzma",
+    ],
+}
+
 gensrcs {
     name: "art_compiler_operator_srcs",
     cmd: "$(location generate_operator_out) art/compiler $(in) > $(out)",
@@ -260,6 +269,18 @@
     },
 }
 
+cc_defaults {
+    name: "libart-compiler_static_defaults",
+    defaults: [
+        "libart-compiler_static_base_defaults",
+        "libart_static_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
+    ],
+    static_libs: ["libart-compiler"],
+}
+
 art_cc_library {
     name: "libartd-compiler",
     defaults: [
@@ -302,6 +323,18 @@
     ],
 }
 
+cc_defaults {
+    name: "libartd-compiler_static_defaults",
+    defaults: [
+        "libart-compiler_static_base_defaults",
+        "libartd_static_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
+    ],
+    static_libs: ["libartd-compiler"],
+}
+
 art_cc_library {
     name: "libart-compiler-gtest",
     defaults: ["libart-gtest-defaults"],
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index 88e69cd..666db42 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -89,6 +89,20 @@
     },
 }
 
+cc_defaults {
+    name: "libart-dex2oat_static_base_defaults",
+    target: {
+        android: {
+            static_libs: ["libcutils"],
+        },
+    },
+    static_libs: [
+        "libbase",
+        "liblz4",
+        "liblzma",
+    ],
+}
+
 gensrcs {
     name: "art_dex2oat_operator_srcs",
     cmd: "$(location generate_operator_out) art/dex2oat $(in) > $(out)",
@@ -110,6 +124,20 @@
     ],
 }
 
+cc_defaults {
+    name: "libart-dex2oat_static_defaults",
+    defaults: [
+        "libart-dex2oat_static_base_defaults",
+        "libart_static_defaults",
+        "libprofile_static_defaults",
+    ],
+    static_libs: [
+        "libart-compiler",
+        "libart-dexlayout",
+        "libart-dex2oat",
+    ],
+}
+
 art_cc_static_library {
     name: "libartd-dex2oat",
     defaults: [
@@ -124,6 +152,20 @@
     ],
 }
 
+cc_defaults {
+    name: "libartd-dex2oat_static_defaults",
+    defaults: [
+        "libart-dex2oat_static_base_defaults",
+        "libartd_static_defaults",
+        "libprofiled_static_defaults",
+    ],
+    static_libs: [
+        "libartd-compiler",
+        "libartd-dexlayout",
+        "libartd-dex2oat",
+    ],
+}
+
 cc_library_headers {
     name: "dex2oat_headers",
     host_supported: true,
@@ -255,7 +297,9 @@
     name: "dex2oats-defaults",
     device_supported: false,
     static_executable: true,
-    defaults: ["dex2oat-defaults"],
+    defaults: [
+        "dex2oat-defaults",
+    ],
     target: {
         darwin: {
             enabled: false,
@@ -269,22 +313,24 @@
         // Try to get rid of it.
         "-z muldefs",
     ],
-    static_libs: art_static_dependencies,
+    static_libs: [
+        "libbase",
+        "liblz4",
+        "libsigchain_dummy",
+    ],
 }
 
 art_cc_binary {
     name: "dex2oats",
-    defaults: ["dex2oats-defaults"],
-    static_libs: [
-        "libart-dex2oat",
-        "libart-compiler",
-        "libart-dexlayout",
-        "libart",
-        "libartbase",
-        "libdexfile",
-        "libprofile",
-        "libvixl-arm",
-        "libvixl-arm64",
+    defaults: [
+        "dex2oats-defaults",
+        "libart_static_defaults",
+        "libart-compiler_static_defaults",
+        "libart-dexlayout_static_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
+        "libart-dex2oat_static_defaults",
     ],
 }
 
@@ -293,6 +339,13 @@
     defaults: [
         "art_debug_defaults",
         "dex2oats-defaults",
+        "libartd_static_defaults",
+        "libartd-compiler_static_defaults",
+        "libartd-dexlayout_static_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
+        "libartd-dex2oat_static_defaults",
     ],
     target: {
         linux_glibc_x86_64: {
@@ -301,17 +354,6 @@
     },
     // b/79417743, oatdump 32-bit tests failed with clang lld
     use_clang_lld: false,
-    static_libs: [
-        "libartd-dex2oat",
-        "libartd-compiler",
-        "libartd-dexlayout",
-        "libartd",
-        "libartbased",
-        "libprofiled",
-        "libdexfiled",
-        "libvixld-arm",
-        "libvixld-arm64",
-    ],
 }
 
 art_cc_test {
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
index ac9a9a2..3e576c8 100644
--- a/dexdump/Android.bp
+++ b/dexdump/Android.bp
@@ -38,13 +38,13 @@
 
 art_cc_binary {
     name: "dexdumps",
-    defaults: ["dexdump_defaults"],
+    defaults: [
+        "dexdump_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+    ],
     host_supported: true,
     device_supported: false,
-    static_libs: [
-        "libdexfile",
-        "libartbase",
-    ] + art_static_dependencies,
     target: {
         darwin: {
             enabled: false,
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 147af0c..24ee5f8 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -32,6 +32,14 @@
     static_libs: ["libz"],
 }
 
+cc_defaults {
+    name: "libart-dexlayout_static_base_defaults",
+    static_libs: [
+        "libbase",
+        "libz",
+    ],
+}
+
 art_cc_library {
     name: "libart-dexlayout",
     defaults: [
@@ -53,6 +61,17 @@
     },
 }
 
+cc_defaults {
+    name: "libart-dexlayout_static_defaults",
+    defaults: [
+        "libart-dexlayout_static_base_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
+    ],
+    static_libs: ["libart-dexlayout"],
+}
+
 art_cc_library {
     name: "libartd-dexlayout",
     defaults: [
@@ -67,6 +86,17 @@
 }
 
 cc_defaults {
+    name: "libartd-dexlayout_static_defaults",
+    defaults: [
+        "libart-dexlayout_static_base_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
+    ],
+    static_libs: ["libartd-dexlayout"],
+}
+
+cc_defaults {
     name: "dexlayout-defaults",
     defaults: ["art_defaults"],
     host_supported: true,
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 4ee48da..1b603b5 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -79,6 +79,30 @@
     export_shared_lib_headers: ["libbase"],
 }
 
+cc_defaults {
+    name: "libartbase_static_base_defaults",
+    static_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libz",
+        "libziparchive",
+    ],
+}
+
+cc_defaults {
+    name: "libartbase_static_defaults",
+    defaults: ["libartbase_static_base_defaults"],
+    static_libs: ["libartbase"],
+}
+
+cc_defaults {
+    name: "libartbased_static_defaults",
+    defaults: ["libartbase_static_base_defaults"],
+    static_libs: ["libartbased"],
+}
+
 gensrcs {
     name: "art_libartbase_operator_srcs",
     cmd: "$(location generate_operator_out) art/libartbase $(in) > $(out)",
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 06fd19e..49b1278 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -72,6 +72,36 @@
     ],
 }
 
+cc_defaults {
+    name: "libdexfile_static_base_defaults",
+    static_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libz",
+        "libziparchive",
+    ],
+}
+
+cc_defaults {
+    name: "libdexfile_static_defaults",
+    defaults: [
+        "libartbase_static_defaults",
+        "libdexfile_static_base_defaults",
+    ],
+    static_libs: ["libdexfile"],
+}
+
+cc_defaults {
+    name: "libdexfiled_static_defaults",
+    defaults: [
+        "libartbased_static_defaults",
+        "libdexfile_static_base_defaults",
+    ],
+    static_libs: ["libdexfiled"],
+}
+
 gensrcs {
     name: "dexfile_operator_srcs",
     cmd: "$(location generate_operator_out) art/libdexfile $(in) > $(out)",
diff --git a/libprofile/Android.bp b/libprofile/Android.bp
index b9883f6..edd9fa8 100644
--- a/libprofile/Android.bp
+++ b/libprofile/Android.bp
@@ -56,6 +56,37 @@
     export_shared_lib_headers: ["libbase"],
 }
 
+cc_defaults {
+    name: "libprofile_static_base_defaults",
+    static_libs: [
+        "libbase",
+        "libcutils",
+        "libutils",
+        "libz",
+        "libziparchive",
+    ],
+}
+
+cc_defaults {
+    name: "libprofile_static_defaults",
+    defaults: [
+        "libprofile_static_base_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+    ],
+    static_libs: ["libprofile"],
+}
+
+cc_defaults {
+    name: "libprofiled_static_defaults",
+    defaults: [
+        "libprofile_static_base_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+    ],
+    static_libs: ["libprofiled"],
+}
+
 art_cc_library {
     name: "libprofile",
     defaults: ["libprofile_defaults"],
diff --git a/oatdump/Android.bp b/oatdump/Android.bp
index 3cd8ae0..0704499 100644
--- a/oatdump/Android.bp
+++ b/oatdump/Android.bp
@@ -66,7 +66,9 @@
     name: "oatdumps-defaults",
     device_supported: false,
     static_executable: true,
-    defaults: ["oatdump-defaults"],
+    defaults: [
+        "oatdump-defaults",
+    ],
     target: {
         darwin: {
             enabled: false,
@@ -80,18 +82,20 @@
         // Try to get rid of it.
         "-z muldefs",
     ],
-    static_libs: art_static_dependencies,
+    static_libs: ["libsigchain_dummy"],
 }
 
 art_cc_binary {
     name: "oatdumps",
-    defaults: ["oatdumps-defaults"],
+    defaults: [
+        "libart_static_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
+        "libart-compiler_static_defaults",
+        "oatdumps-defaults",
+    ],
     static_libs: [
-        "libart",
-        "libdexfile",
-        "libprofile",
-        "libartbase",
-        "libart-compiler",
         "libart-disassembler",
         "libvixl-arm",
         "libvixl-arm64",
@@ -102,6 +106,11 @@
     name: "oatdumpds",
     defaults: [
         "art_debug_defaults",
+        "libartd_static_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
+        "libartd-compiler_static_defaults",
         "oatdumps-defaults",
     ],
     target: {
@@ -110,11 +119,6 @@
         },
     },
     static_libs: [
-        "libartd",
-        "libdexfiled",
-        "libprofiled",
-        "libartbased",
-        "libartd-compiler",
         "libartd-disassembler",
         "libvixld-arm",
         "libvixld-arm64",
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 6ec6265..1cebb06 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -408,6 +408,49 @@
     export_shared_lib_headers: ["libbase"],
 }
 
+libart_static_cc_defaults {
+    name: "libart_static_base_defaults",
+    target: {
+        android: {
+            static_libs: ["libtombstoned_client_static"],
+        },
+    },
+    static_libs: [
+        "libbacktrace",
+        "libbase",
+        "libcutils",
+        "liblog",
+        "liblz4",
+        "liblzma",
+        "libnativebridge",
+        "libnativeloader",
+        "libunwindstack",
+        "libz",
+    ],
+}
+
+cc_defaults {
+    name: "libart_static_defaults",
+    defaults: [
+        "libart_static_base_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
+    ],
+    static_libs: ["libart"],
+}
+
+cc_defaults {
+    name: "libartd_static_defaults",
+    defaults: [
+        "libart_static_base_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
+    ],
+    static_libs: ["libartd"],
+}
+
 gensrcs {
     name: "art_operator_srcs",
     cmd: "$(location generate_operator_out) art/runtime $(in) > $(out)",
diff --git a/test/Android.bp b/test/Android.bp
index e265651..4b61463 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -417,10 +417,11 @@
 
 art_cc_defaults {
     name: "libtistress-static-defaults",
-    defaults: ["libtistress-srcs"],
-    static_libs: art_static_dependencies + [
-        "slicer",
+    defaults: [
+        "libtistress-srcs",
+        "libart_static_defaults",
     ],
+    static_libs: ["slicer"],
 }
 
 art_cc_test_library {
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 05c9aa9..768bc79 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -697,9 +697,14 @@
         "description": ["Tests that depend on input-vdex are not supported with compact dex"]
     },
     {
-        "tests": ["661-oat-writer-layout", "004-StackWalk"],
+        "tests": ["661-oat-writer-layout"],
         "variant": "interp-ac | interpreter | jit | no-prebuild | no-image | trace | redefine-stress | jvmti-stress",
-        "description": ["Tests are designed to only check --optimizing"]
+        "description": ["Test is designed to only check --optimizing"]
+    },
+    {
+        "tests": ["004-StackWalk"],
+        "variant": "interp-ac | interpreter | jit | no-prebuild | no-image | trace | redefine-stress | jvmti-stress | debuggable",
+        "description": ["Test is designed to only check --optimizing"]
     },
     {
         "tests": "674-HelloWorld-Dm",
diff --git a/tools/art_verifier/Android.bp b/tools/art_verifier/Android.bp
index afd52fb..6fff27a 100644
--- a/tools/art_verifier/Android.bp
+++ b/tools/art_verifier/Android.bp
@@ -16,7 +16,10 @@
 
 art_cc_defaults {
     name: "art_verifier-defaults",
-    defaults: ["art_defaults"],
+    defaults: [
+        "art_defaults",
+        "libart_static_defaults",
+    ],
     host_supported: true,
     srcs: [
         "art_verifier.cc",
@@ -24,11 +27,8 @@
     header_libs: [
         "art_cmdlineparser_headers",
     ],
-    static_libs: art_static_dependencies + [
-        "libart",
-        "libartbase",
-        "libdexfile",
-        "libprofile",
+    static_libs: [
+        "libsigchain_dummy",
     ],
     target: {
         android: {
diff --git a/tools/field-null-percent/check-null-fields.py b/tools/field-null-percent/check-null-fields.py
new file mode 100755
index 0000000..c11d51a
--- /dev/null
+++ b/tools/field-null-percent/check-null-fields.py
@@ -0,0 +1,149 @@
+#!/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.
+
+"""
+Retrieves the counts of how many objects have a particular field null on all running processes.
+
+Prints a json map from pid -> (log-tag, field-name, null-count, total-count).
+"""
+
+
+import adb
+import argparse
+import concurrent.futures
+import itertools
+import json
+import logging
+import os
+import os.path
+import signal
+import subprocess
+import time
+
+def main():
+  parser = argparse.ArgumentParser(description="Get counts of null fields from a device.")
+  parser.add_argument("-S", "--serial", metavar="SERIAL", type=str,
+                      required=False,
+                      default=os.environ.get("ANDROID_SERIAL", None),
+                      help="Android serial to use. Defaults to ANDROID_SERIAL")
+  parser.add_argument("-p", "--pid", required=False,
+                      default=[], action="append",
+                      help="Specific pids to check. By default checks all running dalvik processes")
+  has_out = "OUT" in os.environ
+  def_32 = os.path.join(os.environ.get("OUT", ""), "system", "lib", "libfieldnull.so")
+  def_64 = os.path.join(os.environ.get("OUT", ""), "system", "lib64", "libfieldnull.so")
+  has_32 = has_out and os.path.exists(def_32)
+  has_64 = has_out and os.path.exists(def_64)
+  def pushable_lib(name):
+    if os.path.isfile(name):
+      return name
+    else:
+      raise argparse.ArgumentTypeError(name + " is not a file!")
+  parser.add_argument('--lib32', type=pushable_lib,
+                      required=not has_32,
+                      action='store',
+                      default=def_32,
+                      help="Location of 32 bit agent to push")
+  parser.add_argument('--lib64', type=pushable_lib,
+                      required=not has_64,
+                      action='store',
+                      default=def_64 if has_64 else None,
+                      help="Location of 64 bit agent to push")
+  parser.add_argument("fields", nargs="+",
+                      help="fields to check")
+
+  out = parser.parse_args()
+
+  device = adb.device.get_device(out.serial)
+  print("getting root")
+  device.root()
+
+  print("Disabling selinux")
+  device.shell("setenforce 0".split())
+
+  print("Pushing libraries")
+  lib32 = device.shell("mktemp".split())[0].strip()
+  lib64 = device.shell("mktemp".split())[0].strip()
+
+  print(out.lib32 + " -> " + lib32)
+  device.push(out.lib32, lib32)
+
+  print(out.lib64 + " -> " + lib64)
+  device.push(out.lib64, lib64)
+
+  cmd32 = "'{}={}'".format(lib32, ','.join(out.fields))
+  cmd64 = "'{}={}'".format(lib64, ','.join(out.fields))
+
+  if len(out.pid) == 0:
+    print("Getting jdwp pids")
+    new_env = dict(os.environ)
+    new_env["ANDROID_SERIAL"] = device.serial
+    p = subprocess.Popen([device.adb_path, "jdwp"], env=new_env, stdout=subprocess.PIPE)
+    # ADB jdwp doesn't ever exit so just kill it after 1 second to get a list of pids.
+    with concurrent.futures.ProcessPoolExecutor() as ppe:
+      ppe.submit(kill_it, p.pid).result()
+    out.pid = p.communicate()[0].strip().split()
+    p.wait()
+    print(out.pid)
+  print("Clearing logcat")
+  device.shell("logcat -c".split())
+  final = {}
+  print("Getting info from every process dumped to logcat")
+  for p in out.pid:
+    res = check_single_process(p, device, cmd32, cmd64);
+    if res is not None:
+      final[p] = res
+  device.shell('rm {}'.format(lib32).split())
+  device.shell('rm {}'.format(lib64).split())
+  print(json.dumps(final, indent=2))
+
+def kill_it(p):
+  time.sleep(1)
+  os.kill(p, signal.SIGINT)
+
+def check_single_process(pid, device, bit32, bit64):
+  try:
+    # Just try attaching both 32 and 64 bit. Wrong one will fail silently.
+    device.shell(['am', 'attach-agent', str(pid), bit32])
+    device.shell(['am', 'attach-agent', str(pid), bit64])
+    time.sleep(0.5)
+    device.shell('kill -3 {}'.format(pid).split())
+    time.sleep(0.5)
+    out = []
+    all_fields = []
+    lc_cmd = "logcat -d -b main --pid={} -e '^\\t.*\\t[0-9]*\\t[0-9]*$'".format(pid).split(' ')
+    for l in device.shell(lc_cmd)[0].strip().split('\n'):
+      # first 4 are just date and other useless data.
+      data = l.strip().split()[5:]
+      if len(data) < 4:
+        continue
+      # If we run multiple times many copies of the agent will be attached. Just choose one of any
+      # copies for each field.
+      field = data[1]
+      if field not in all_fields:
+        out.append((str(data[0]), str(data[1]), int(data[2]), int(data[3])))
+        all_fields.append(field)
+    if len(out) != 0:
+      print("pid: " + pid + " -> " + str(out))
+      return out
+    else:
+      return None
+  except adb.device.ShellError as e:
+    print("failed on pid " + repr(pid) + " because " + repr(e))
+    return None
+
+if __name__ == '__main__':
+  main()