release-request-777c0f47-a42e-446a-b45c-0bb1aaa9612e-for-git_oc-release-4066915 snap-temp-L92300000070444114

Change-Id: I1c3ee7a1d2445ce2b48c6117f03ff416cff0b10f
diff --git a/src/com/android/loganalysis/item/CompactMemInfoItem.java b/src/com/android/loganalysis/item/CompactMemInfoItem.java
index 9c52b88..cf9bff9 100644
--- a/src/com/android/loganalysis/item/CompactMemInfoItem.java
+++ b/src/com/android/loganalysis/item/CompactMemInfoItem.java
@@ -37,6 +37,10 @@
     public static final String ACTIVITIES_JSON_KEY = "activities";
     public static final String PROCESSES_JSON_KEY = "processes";
     public static final String LOST_RAM_JSON_KEY = "lostRam";
+    public static final String TOTAL_ZRAM_JSON_KEY = "totalZram";
+    public static final String FREE_SWAP_ZRAM_JSON_KEY = "freeSwapZram";
+    public static final String FREE_RAM_JSON_KEY = "freeRam";
+    public static final String TUNING_LEVEL_JSON_KEY = "tuningLevel";
     /** Constants for attributes HashMap */
     private static final String NAME_ATTR_KEY = "name";
     private static final String PSS_ATTR_KEY = "pss";
@@ -45,7 +49,11 @@
     private static final String ACTIVITIES_ATTR_KEY = "activities";
 
     private Map<Integer, Map<String, Object>> mPids = new HashMap<Integer, Map<String, Object>>();
+    private long mFreeRam;
+    private long mFreeSwapZram;
     private long mLostRam;
+    private long mTotalZram;
+    private long mTuningLevel;
 
     @Override
     public IItem merge(IItem other) throws ConflictingItemException {
@@ -78,8 +86,12 @@
         }
         try {
             object.put(PROCESSES_JSON_KEY, processes);
-            // Add the lost RAM field
+            // Add the additional non-process field
             object.put(LOST_RAM_JSON_KEY, getLostRam());
+            object.put(TOTAL_ZRAM_JSON_KEY, getTotalZram());
+            object.put(FREE_SWAP_ZRAM_JSON_KEY, getFreeSwapZram());
+            object.put(FREE_RAM_JSON_KEY, getFreeRam());
+            object.put(TUNING_LEVEL_JSON_KEY, getTuningLevel());
         } catch (JSONException e) {
             // ignore
         }
@@ -161,4 +173,44 @@
     public long getLostRam() {
         return mLostRam;
     }
+
+    /** Sets the free RAM field */
+    public void setFreeRam(long freeRam) {
+        mFreeRam = freeRam;
+    }
+
+    /** Returns the free RAM field */
+    public long getFreeRam() {
+        return mFreeRam;
+    }
+
+    /** Sets the total ZRAM field */
+    public void setTotalZram(long totalZram) {
+        mTotalZram = totalZram;
+    }
+
+    /** Returns the total ZRAM field */
+    public long getTotalZram() {
+        return mTotalZram;
+    }
+
+    /** Sets the free swap ZRAM field */
+    public void setFreeSwapZram(long freeSwapZram) {
+        mFreeSwapZram = freeSwapZram;
+    }
+
+    /** Returns the free swap ZRAM field */
+    public long getFreeSwapZram() {
+        return mFreeSwapZram;
+    }
+
+    /** Sets the tuning level field */
+    public void setTuningLevel(long tuningLevel) {
+        mTuningLevel = tuningLevel;
+    }
+
+    /** Returns the tuning level field */
+    public long getTuningLevel() {
+        return mTuningLevel;
+    }
 }
diff --git a/src/com/android/loganalysis/item/DmesgStageInfoItem.java b/src/com/android/loganalysis/item/DmesgStageInfoItem.java
index a5bfd39..a446090 100644
--- a/src/com/android/loganalysis/item/DmesgStageInfoItem.java
+++ b/src/com/android/loganalysis/item/DmesgStageInfoItem.java
@@ -30,9 +30,11 @@
     public static final String STAGE_NAME = "STAGE_NAME";
     /** Constant for JSON output */
     public static final String STAGE_START_TIME = "STAGE_START_TIME";
+    /** Constant for JSON output */
+    public static final String STAGE_DURATION = "STAGE_DURATION";
 
     private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(
-            STAGE_NAME, STAGE_START_TIME));
+            STAGE_NAME, STAGE_START_TIME, STAGE_DURATION));
 
     /**
      * The constructor for {@link DmesgStageInfoItem}.
@@ -44,10 +46,11 @@
     /**
      * The constructor for {@link DmesgStageInfoItem}.
      */
-    public DmesgStageInfoItem(String name, Long startTime) {
+    public DmesgStageInfoItem(String name, Long startTime, Long duration) {
         super(ATTRIBUTES);
         setAttribute(STAGE_NAME, name);
         setAttribute(STAGE_START_TIME, startTime);
+        setAttribute(STAGE_DURATION, duration);
     }
 
     /**
@@ -78,10 +81,24 @@
         setAttribute(STAGE_START_TIME, startTime);
     }
 
+    /**
+     * Get the duration in msecs
+     */
+    public Long getDuration() {
+        return (Long) getAttribute(STAGE_DURATION);
+    }
+
+    /**
+     * Set the duration in msecs
+     */
+    public void setDuration(Long duration) {
+        setAttribute(STAGE_DURATION, duration);
+    }
+
     @Override
     public String toString() {
         return "StageInfoItem [getStageName()=" + getStageName() + ", getStartTime()="
-                + getStartTime() + "]";
+                + getStartTime() + ", getDuration()=" + getDuration() + "]";
     }
 
 }
diff --git a/src/com/android/loganalysis/parser/CompactMemInfoParser.java b/src/com/android/loganalysis/parser/CompactMemInfoParser.java
index 788cd8b..263cdf1 100644
--- a/src/com/android/loganalysis/parser/CompactMemInfoParser.java
+++ b/src/com/android/loganalysis/parser/CompactMemInfoParser.java
@@ -37,10 +37,12 @@
  *
  */
 public class CompactMemInfoParser implements IParser {
-    private static final Pattern PROC_PREFIX = Pattern.compile(
-            "proc,(\\w+),([a-zA-Z_0-9\\.]+),(\\d+),(\\d+),((\\S+),)?(.*)");
-    private static final Pattern LOST_RAM_PREFIX = Pattern.compile(
-            "lostram,(.+)");
+    private static final Pattern PROC_PATTERN =
+            Pattern.compile("proc,(\\w+),([a-zA-Z_0-9\\.]+),(\\d+),(\\d+),((\\S+),)?(.*)");
+    private static final Pattern LOST_RAM_PATTERN = Pattern.compile("lostram,(\\d+)");
+    private static final Pattern RAM_PATTERN = Pattern.compile("ram,(\\d+),(\\d+),(\\d+)");
+    private static final Pattern ZRAM_PATTERN = Pattern.compile("zram,(\\d+),(\\d+),(\\d+)");
+    private static final Pattern TUNING_PATTERN = Pattern.compile("tuning,(\\d+),(\\d+),(\\d+).*");
 
     /**
      * Parse compact meminfo log. Output a CompactMemInfoItem which contains
@@ -50,7 +52,7 @@
     public CompactMemInfoItem parse(List<String> lines) {
         CompactMemInfoItem item = new CompactMemInfoItem();
         for (String line : lines) {
-            Matcher m = PROC_PREFIX.matcher(line);
+            Matcher m = PROC_PATTERN.matcher(line);
             if (m.matches()) {
                 String type = m.group(1);
                 String name = m.group(2);
@@ -69,9 +71,8 @@
                 }
             }
 
-            m = LOST_RAM_PREFIX.matcher(line);
+            m = LOST_RAM_PATTERN.matcher(line);
             if (m.matches()) {
-                String name = "Lost RAM";
                 try {
                     long lostRam = Long.parseLong(m.group(1));
                     item.setLostRam(lostRam);
@@ -80,6 +81,37 @@
                     // ignore exception
                 }
             }
+
+            m = RAM_PATTERN.matcher(line);
+            if (m.matches()) {
+                try {
+                    item.setFreeRam(Long.parseLong(m.group(2)));
+                    continue;
+                } catch (NumberFormatException nfe) {
+                    // ignore exception
+                }
+            }
+
+            m = ZRAM_PATTERN.matcher(line);
+            if (m.matches()) {
+                try {
+                    item.setTotalZram(Long.parseLong(m.group(1)));
+                    item.setFreeSwapZram(Long.parseLong(m.group(3)));
+                    continue;
+                } catch (NumberFormatException nfe) {
+                    // ignore exception
+                }
+            }
+
+            m = TUNING_PATTERN.matcher(line);
+            if (m.matches()) {
+                try {
+                    item.setTuningLevel(Long.parseLong(m.group(3)));
+                    continue;
+                } catch (NumberFormatException nfe) {
+                    // ignore exception
+                }
+            }
         }
         return item;
     }
diff --git a/src/com/android/loganalysis/parser/DmesgParser.java b/src/com/android/loganalysis/parser/DmesgParser.java
index ba802cf..ce3d389 100644
--- a/src/com/android/loganalysis/parser/DmesgParser.java
+++ b/src/com/android/loganalysis/parser/DmesgParser.java
@@ -40,15 +40,22 @@
     private static final String TIMESTAMP = "TIMESTAMP";
     private static final String STAGE = "STAGE";
     private static final String ACTION = "ACTION";
+    private static final String DURATION = "DURATION";
+    private static final String UEVENTD = "ueventd";
+
     // Matches: [ 14.822691] init:
     private static final String SERVICE_PREFIX = String.format("^\\[\\s+(?<%s>.*)\\] init:\\s+",
             TIMESTAMP);
+    // Matches: [    3.791635] ueventd:
+    private static final String UEVENTD_PREFIX = String.format("^\\[\\s+(?<%s>.*)\\] ueventd:\\s+",
+            TIMESTAMP);
+
     // Matches: starting service 'ueventd'...
     private static final String START_SERVICE_SUFFIX = String.format("starting service "
             + "\\'(?<%s>.*)\\'...", SERVICENAME);
     // Matches: Service 'ueventd' (pid 439) exited with status 0
     private static final String EXIT_SERVICE_SUFFIX = String.format("Service \\'(?<%s>.*)\\'\\s+"
-            + "\\((?<PID>.*)\\) exited with status 0", SERVICENAME);
+            + "\\((?<PID>.*)\\) exited with status 0.*", SERVICENAME);
 
     private static final Pattern START_SERVICE = Pattern.compile(
             String.format("%s%s", SERVICE_PREFIX, START_SERVICE_SUFFIX));
@@ -65,15 +72,19 @@
             String.format("%s%s", SERVICE_PREFIX, START_STAGE_PREFIX));
 
     // Matches: init: processing action (early-init)
-    // must not match: init: processing action (vold.decrypt=trigger_restart_framework)
     private static final String START_PROCESSING_ACTION_PREFIX = String.format(
-            "processing action \\((?<%s>[^=]+)\\)", ACTION);
+            "processing action \\((?<%s>.*)\\) from.*$", ACTION);
 
     // Matches: [   14.942872] init: processing action (early-init)
-    // Does not match: [   22.361049] init: processing action (persist.sys.usb.config=* boot)
     private static final Pattern START_PROCESSING_ACTION = Pattern.compile(
             String.format("%s%s", SERVICE_PREFIX, START_PROCESSING_ACTION_PREFIX));
 
+    // Matches: [    3.791635] ueventd: Coldboot took 0.695055 seconds
+    private static final String STAGE_SUFFIX= String.format(
+            "(?<%s>.*)\\s+took\\s+(?<%s>.*)\\s+seconds$", STAGE, DURATION);
+    private static final Pattern UEVENTD_STAGE_INFO = Pattern.compile(
+            String.format("%s%s", UEVENTD_PREFIX, STAGE_SUFFIX));
+
 
     private DmesgItem mDmesgItem = new DmesgItem();
 
@@ -166,7 +177,8 @@
 
     /**
      * Parse init stages log from each {@code line} of dmesg log and
-     * store the stage name and start time in a {@link DmesgStageInfoItem} object
+     * store the stage name, start time and duration if available in a
+     * {@link DmesgStageInfoItem} object
      *
      * @param individual line of the dmesg log
      * @return {@code true}, if the {@code line} indicates start of a boot stage,
@@ -183,6 +195,13 @@
             mDmesgItem.addStageInfoItem(stageInfoItem);
             return true;
         }
+        if((match = matches(UEVENTD_STAGE_INFO, line)) != null) {
+            DmesgStageInfoItem stageInfoItem = new DmesgStageInfoItem();
+            stageInfoItem.setStageName(String.format("%s_%s", UEVENTD, match.group(STAGE)));
+            stageInfoItem.setDuration((long) (Double.parseDouble(
+                    match.group(DURATION)) * 1000));
+            mDmesgItem.addStageInfoItem(stageInfoItem);
+        }
         return false;
     }
 
diff --git a/src/com/android/loganalysis/parser/LogcatParser.java b/src/com/android/loganalysis/parser/LogcatParser.java
index 96cd1c2..b32536d 100644
--- a/src/com/android/loganalysis/parser/LogcatParser.java
+++ b/src/com/android/loganalysis/parser/LogcatParser.java
@@ -54,12 +54,18 @@
 
     /**
      * Match a single line of `logcat -v threadtime`, such as:
-     * 05-26 11:02:36.886  5689  5689 D AndroidRuntime: CheckJNI is OFF
+     *
+     * <pre>05-26 11:02:36.886 5689 5689 D AndroidRuntime: CheckJNI is OFF.</pre>
      */
-    private static final Pattern THREADTIME_LINE = Pattern.compile(
-            "^(\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3})\\s+" +  /* timestamp [1] */
-                "(\\d+)\\s+(\\d+)\\s+([A-Z])\\s+" +  /* pid/tid and log level [2-4] */
-                "(.+?)\\s*: (.*)$" /* tag and message [5-6]*/);
+    private static final Pattern THREADTIME_LINE =
+            // UID was added to logcat. It could either be a number or a string.
+            Pattern.compile(
+                    // timestamp[1]
+                    "^(\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3})"
+                            // pid/tid and log level [2-4]
+                            + "(?:\\s+[0-9A-Za-z]+)?\\s+(\\d+)\\s+(\\d+)\\s+([A-Z])\\s+"
+                            // tag and message [5-6]
+                            + "(.+?)\\s*: (.*)$");
 
     /**
      * Match a single line of `logcat -v time`, such as:
diff --git a/tests/.classpath b/tests/.classpath
index 96fc008..c7726fe 100644
--- a/tests/.classpath
+++ b/tests/.classpath
@@ -3,7 +3,7 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/loganalysis"/>
-	<classpathentry exported="true" kind="var" path="TRADEFED_ROOT/out/host/common/obj/JAVA_LIBRARIES/easymock_intermediates/javalib.jar" sourcepath="/TRADEFED_ROOT/external/easymock/src"/>
 	<classpathentry kind="var" path="TRADEFED_ROOT/out/host/common/obj/JAVA_LIBRARIES/junit-host_intermediates/javalib.jar"/>
+	<classpathentry kind="var" path="TRADEFED_ROOT/external/easymock/src"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tests/src/com/android/loganalysis/parser/CompactMemInfoParserTest.java b/tests/src/com/android/loganalysis/parser/CompactMemInfoParserTest.java
index 32119bd..ed4b39b 100644
--- a/tests/src/com/android/loganalysis/parser/CompactMemInfoParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/CompactMemInfoParserTest.java
@@ -74,14 +74,49 @@
         assertEquals(1005, item.getLostRam());
     }
 
+    public void testSingleRamLine() {
+        List<String> input = Arrays.asList("ram,2866484,1221694,1112777");
+        CompactMemInfoItem item = new CompactMemInfoParser().parse(input);
+        assertEquals(1221694, item.getFreeRam());
+    }
+
+    public void testSingleZramLine() {
+        List<String> input = Arrays.asList("zram,5800,520908,491632");
+        CompactMemInfoItem item = new CompactMemInfoParser().parse(input);
+        assertEquals(5800, item.getTotalZram());
+        assertEquals(491632, item.getFreeSwapZram());
+    }
+
+    public void testSingleTuningLine() {
+        // With specific configuration
+        List<String> input1 = Arrays.asList("tuning,192,512,322560,high-end-gfx");
+        CompactMemInfoItem item1 = new CompactMemInfoParser().parse(input1);
+        assertEquals(322560, item1.getTuningLevel());
+        // Without specific configuration
+        List<String> input2 = Arrays.asList("tuning,193,513,322561");
+        CompactMemInfoItem item2 = new CompactMemInfoParser().parse(input2);
+        assertEquals(322561, item2.getTuningLevel());
+    }
+
     public void testSomeMalformedLines() {
-        List<String> input = Arrays.asList(
-                "proc,cached,com.google.android.youtube,a,b,e",
-                "proc,cached,com.google.android.youtube,2964,c,e",
-                "proc,cached,com.google.android.youtube,2964,e",
-                "proc,cached,com.google.android.youtube,2964,19345,a,e",
-                "lostram,a,1000",
-                "lostram,1000,a");
+        List<String> input =
+                Arrays.asList(
+                        "proc,cached,com.google.android.youtube,a,b,e",
+                        "proc,cached,com.google.android.youtube,2964,c,e",
+                        "proc,cached,com.google.android.youtube,2964,e",
+                        "proc,cached,com.google.android.youtube,2964,19345,a,e",
+                        "lostram,a,1000",
+                        "lostram,1000,a",
+                        "ram,123,345",
+                        "ram,123,345,abc",
+                        "ram,123,345,456,678",
+                        "ram,123,345,456,abc",
+                        "zram,123,345",
+                        "zram,123,345,abc",
+                        "zram,123,345,456,678",
+                        "zram,123,345,456,abc",
+                        "tuning,123,345",
+                        "tuning,123,345,abc");
 
         CompactMemInfoItem item = new CompactMemInfoParser().parse(input);
 
@@ -89,13 +124,17 @@
     }
 
     public void testMultipleLines() {
-        List<String> input = Arrays.asList(
-                "proc,cached,com.google.android.youtube,2964,19345,123,e",
-                "proc,cached,com.google.android.apps.plus,2877,9604,N/A,e",
-                "proc,cached,com.google.android.apps.magazines,2009,20111,N/A,e",
-                "proc,cached,com.google.android.apps.walletnfcrel,10790,11164,100,e",
-                "proc,cached,com.google.android.incallui,3410,9491,N/A,e",
-                "lostram,1005");
+        List<String> input =
+                Arrays.asList(
+                        "proc,cached,com.google.android.youtube,2964,19345,123,e",
+                        "proc,cached,com.google.android.apps.plus,2877,9604,N/A,e",
+                        "proc,cached,com.google.android.apps.magazines,2009,20111,N/A,e",
+                        "proc,cached,com.google.android.apps.walletnfcrel,10790,11164,100,e",
+                        "proc,cached,com.google.android.incallui,3410,9491,N/A,e",
+                        "lostram,1005",
+                        "ram,2866484,1221694,1112777",
+                        "zram,5800,520908,491632",
+                        "tuning,193,513,322561");
 
         CompactMemInfoItem item = new CompactMemInfoParser().parse(input);
 
@@ -107,6 +146,10 @@
         assertEquals(false, item.hasActivities(2964));
 
         assertEquals(1005, item.getLostRam());
+        assertEquals(1221694, item.getFreeRam());
+        assertEquals(5800, item.getTotalZram());
+        assertEquals(491632, item.getFreeSwapZram());
+        assertEquals(322561, item.getTuningLevel());
     }
 
     public void testSkipNonProcLines() {
@@ -132,15 +175,19 @@
     }
 
     public void testJson() throws JSONException {
-        List<String> input = Arrays.asList(
-                "oom,cached,141357",
-                "proc,cached,com.google.android.youtube,2964,19345,N/A,e",
-                "proc,cached,com.google.android.apps.plus,2877,9604,50,e",
-                "proc,cached,com.google.android.apps.magazines,2009,20111,100,e",
-                "proc,cached,com.google.android.apps.walletnfcrel,10790,11164,0,e",
-                "proc,cached,com.google.android.incallui,3410,9491,500,e",
-                "lostram,1005",
-                "cat,Native,63169");
+        List<String> input =
+                Arrays.asList(
+                        "oom,cached,141357",
+                        "proc,cached,com.google.android.youtube,2964,19345,N/A,e",
+                        "proc,cached,com.google.android.apps.plus,2877,9604,50,e",
+                        "proc,cached,com.google.android.apps.magazines,2009,20111,100,e",
+                        "proc,cached,com.google.android.apps.walletnfcrel,10790,11164,0,e",
+                        "proc,cached,com.google.android.incallui,3410,9491,500,e",
+                        "lostram,1005",
+                        "ram,2866484,1221694,1112777",
+                        "zram,5800,520908,491632",
+                        "tuning,193,513,322561",
+                        "cat,Native,63169");
 
         CompactMemInfoItem item = new CompactMemInfoParser().parse(input);
         JSONObject json = item.toJson();
@@ -150,5 +197,9 @@
         assertEquals(5, processes.length());
 
         assertEquals(1005, (long)json.get("lostRam"));
+        assertEquals(1221694, (long) json.get("freeRam"));
+        assertEquals(5800, (long) json.get("totalZram"));
+        assertEquals(491632, (long) json.get("freeSwapZram"));
+        assertEquals(322561, (long) json.get("tuningLevel"));
     }
 }
diff --git a/tests/src/com/android/loganalysis/parser/DmesgParserTest.java b/tests/src/com/android/loganalysis/parser/DmesgParserTest.java
index 4b043e1..7db2c49 100644
--- a/tests/src/com/android/loganalysis/parser/DmesgParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/DmesgParserTest.java
@@ -39,6 +39,7 @@
     private static final String BOOT_ANIMATION = "bootanim";
     private static final String NETD = "netd";
     private static final String[] LINES = new String[] {
+            "[    3.786943] ueventd: Coldboot took 0.701291 seconds",
             "[   22.962730] init: starting service 'bootanim'...",
             "[   23.252321] init: starting service 'netd'...",
             "[   29.331069] ipa-wan ipa_wwan_ioctl:1428 dev(rmnet_data0) register to IPA",
@@ -46,15 +47,14 @@
             "[   35.642666] SELinux: initialized (dev fuse, type fuse), uses genfs_contexts",
             "[   39.855818] init: Service 'bootanim' (pid 588) exited with status 0",
             "[   41.665818] init: init first stage started!",
-            "[   42.425056] init: init second stage started!",
-            "[   44.942872] init: processing action (early-init)",
-            "[   47.233446] init: processing action (set_mmap_rnd_bits)",
-            "[   47.240083] init: processing action (set_kptr_restrict)",
-            "[   47.245778] init: processing action (keychord_init)",
-            "[   52.361049] init: processing action (persist.sys.usb.config=* boot)",
-            "[   52.361108] init: processing action (enable_property_trigger)",
-            "[   52.361313] init: processing action (security.perf_harden=1)",
-            "[   52.361495] init: processing action (ro.debuggable=1)",
+            "[   44.942872] init: processing action (early-init) from (/init.rc:13)",
+            "[   47.233446] init: processing action (set_mmap_rnd_bits) from (<Builtin Action>:0)",
+            "[   47.240083] init: processing action (set_kptr_restrict) from (<Builtin Action>:0)",
+            "[   47.245778] init: processing action (keychord_init) from (<Builtin Action>:0)",
+            "[   52.361049] init: processing action (persist.sys.usb.config=* boot) from (<Builtin Action>:0)",
+            "[   52.361108] init: processing action (enable_property_trigger) from (<Builtin Action>:0)",
+            "[   52.361313] init: processing action (security.perf_harden=1) from (/init.rc:677)",
+            "[   52.361495] init: processing action (ro.debuggable=1) from (/init.rc:700)",
             "[   59.331069] ipa-wan ipa_wwan_ioctl:1428 dev(rmnet_data0) register to IPA",
             "[   62.182592] ueventd: fixup /sys/devices/virtual/input/poll_delay 0 1004 660",
             "[   65.642666] SELinux: initialized (dev fuse, type fuse), uses genfs_contexts",
@@ -95,7 +95,7 @@
                 dmesgParser.getServiceInfoItems().size());
         assertEquals("Stage info items list size should be 2", 2,
                 dmesgParser.getStageInfoItems().size());
-        assertEquals("Action info items list size should be 5", 5,
+        assertEquals("Action info items list size should be 8", 8,
                 dmesgParser.getActionInfoItems().size());
 
         assertEquals(EXPECTED_SERVICE_INFO_ITEMS, actualDmesgItem.getServiceInfoItems());
@@ -115,7 +115,7 @@
                     dmesgParser.getServiceInfoItems().size());
             assertEquals("Stage info items list size should be 2", 2,
                     dmesgParser.getStageInfoItems().size());
-            assertEquals("Action info items list size should be 5", 5,
+            assertEquals("Action info items list size should be 8", 8,
                     dmesgParser.getActionInfoItems().size());
         }
     }
@@ -207,7 +207,7 @@
             dmesgParser.parseActionInfo(line);
         }
         List<DmesgActionInfoItem> actualActionInfoItems = dmesgParser.getActionInfoItems();
-        assertEquals(5, actualActionInfoItems.size());
+        assertEquals(8, actualActionInfoItems.size());
         assertEquals(EXPECTED_ACTION_INFO_ITEMS, actualActionInfoItems);
     }
 
@@ -219,13 +219,20 @@
                 new DmesgActionInfoItem("set_kptr_restrict",
                         (long) (Double.parseDouble("47240.083"))),
                 new DmesgActionInfoItem("keychord_init", (long) (Double.parseDouble("47245.778"))),
+                new DmesgActionInfoItem("persist.sys.usb.config=* boot",
+                        (long) (Double.parseDouble("52361.049"))),
                 new DmesgActionInfoItem("enable_property_trigger",
-                        (long) (Double.parseDouble("52361.108"))));
+                        (long) (Double.parseDouble("52361.108"))),
+                new DmesgActionInfoItem("security.perf_harden=1",
+                        (long) (Double.parseDouble("52361.313"))),
+                new DmesgActionInfoItem("ro.debuggable=1",
+                        (long) (Double.parseDouble("52361.495"))));
     }
 
     private static List<DmesgStageInfoItem> getExpectedStageInfoItems() {
         return Arrays.asList(
-                new DmesgStageInfoItem("first", 41665L), new DmesgStageInfoItem("second", 42425L));
+                new DmesgStageInfoItem("ueventd_Coldboot", null, 701L),
+                new DmesgStageInfoItem("first", 41665L, null));
     }
 
     private static Map<String, DmesgServiceInfoItem> getExpectedServiceInfoItems() {
diff --git a/tests/src/com/android/loganalysis/parser/LogcatParserTest.java b/tests/src/com/android/loganalysis/parser/LogcatParserTest.java
index 7adeed6..1d4f72c 100644
--- a/tests/src/com/android/loganalysis/parser/LogcatParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/LogcatParserTest.java
@@ -442,6 +442,78 @@
 
         assertEquals(3064, logcat.getJavaCrashes().get(0).getPid().intValue());
         assertEquals(3082, logcat.getJavaCrashes().get(0).getTid().intValue());
+        assertEquals(
+                parseTime("2012-04-25 09:55:47.799"),
+                logcat.getJavaCrashes().get(0).getEventTime());
+
+        assertEquals(3065, logcat.getJavaCrashes().get(1).getPid().intValue());
+        assertEquals(3090, logcat.getJavaCrashes().get(1).getTid().intValue());
+        assertEquals(
+                parseTime("2012-04-25 09:55:47.799"),
+                logcat.getJavaCrashes().get(1).getEventTime());
+
+        assertEquals(3112, logcat.getNativeCrashes().get(0).getPid().intValue());
+        assertEquals(3112, logcat.getNativeCrashes().get(0).getTid().intValue());
+        assertEquals(
+                parseTime("2012-04-25 18:33:27.273"),
+                logcat.getNativeCrashes().get(0).getEventTime());
+
+        assertEquals(3113, logcat.getNativeCrashes().get(1).getPid().intValue());
+        assertEquals(3113, logcat.getNativeCrashes().get(1).getTid().intValue());
+        assertEquals(
+                parseTime("2012-04-25 18:33:27.273"),
+                logcat.getNativeCrashes().get(1).getEventTime());
+    }
+
+    /** Test that including extra uid column still parses the logs. */
+    public void testParse_uid() throws ParseException {
+        List<String> lines =
+                Arrays.asList(
+                        "04-25 09:55:47.799  wifi  3064  3082 E AndroidRuntime: java.lang.Exception",
+                        "04-25 09:55:47.799  wifi  3064  3082 E AndroidRuntime: \tat class.method1(Class.java:1)",
+                        "04-25 09:55:47.799  wifi  3064  3082 E AndroidRuntime: \tat class.method2(Class.java:2)",
+                        "04-25 09:55:47.799  wifi  3064  3082 E AndroidRuntime: \tat class.method3(Class.java:3)",
+                        "04-25 09:55:47.799  wifi  3065  3090 E AndroidRuntime: java.lang.Exception",
+                        "04-25 09:55:47.799  wifi  3065  3090 E AndroidRuntime: \tat class.method1(Class.java:1)",
+                        "04-25 09:55:47.799  wifi  3065  3090 E AndroidRuntime: \tat class.method2(Class.java:2)",
+                        "04-25 09:55:47.799  wifi  3065  3090 E AndroidRuntime: \tat class.method3(Class.java:3)",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: ANR (application not responding) in process: com.android.package",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: ANR (application not responding) in process: com.android.package",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
+                        "04-25 17:17:08.445  1337  312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
+                        "04-25 18:33:27.273  wifi123  115   115 I DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***",
+                        "04-25 18:33:27.273  wifi123  115   115 I DEBUG   : Build fingerprint: 'product:build:target'",
+                        "04-25 18:33:27.273  wifi123  115   115 I DEBUG   : pid: 3112, tid: 3112  >>> com.google.android.browser <<<",
+                        "04-25 18:33:27.273  wifi123  115   115 I DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000",
+                        "04-25 18:33:27.273  wifi123  117   117 I DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***",
+                        "04-25 18:33:27.273  wifi123  117   117 I DEBUG   : Build fingerprint: 'product:build:target'",
+                        "04-25 18:33:27.273  wifi123  117   117 I DEBUG   : pid: 3113, tid: 3113  >>> com.google.android.browser <<<",
+                        "04-25 18:33:27.273  wifi123  117   117 I DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000");
+
+
+        LogcatItem logcat = new LogcatParser("2012").parse(lines);
+        assertNotNull(logcat);
+        assertEquals(parseTime("2012-04-25 09:55:47.799"), logcat.getStartTime());
+        assertEquals(parseTime("2012-04-25 18:33:27.273"), logcat.getStopTime());
+        assertEquals(6, logcat.getEvents().size());
+        assertEquals(2, logcat.getAnrs().size());
+        assertEquals(2, logcat.getJavaCrashes().size());
+        assertEquals(2, logcat.getNativeCrashes().size());
+
+        assertEquals(312, logcat.getAnrs().get(0).getPid().intValue());
+        assertEquals(366, logcat.getAnrs().get(0).getTid().intValue());
+        assertEquals(parseTime("2012-04-25 17:17:08.445"), logcat.getAnrs().get(0).getEventTime());
+
+        assertEquals(312, logcat.getAnrs().get(1).getPid().intValue());
+        assertEquals(366, logcat.getAnrs().get(1).getTid().intValue());
+        assertEquals(parseTime("2012-04-25 17:17:08.445"), logcat.getAnrs().get(1).getEventTime());
+
+        assertEquals(3064, logcat.getJavaCrashes().get(0).getPid().intValue());
+        assertEquals(3082, logcat.getJavaCrashes().get(0).getTid().intValue());
         assertEquals(parseTime("2012-04-25 09:55:47.799"),
                 logcat.getJavaCrashes().get(0).getEventTime());
 
diff --git a/tests/src/com/android/loganalysis/util/RegexTrieTest.java b/tests/src/com/android/loganalysis/util/RegexTrieTest.java
index 3b00e55..4b689b6 100644
--- a/tests/src/com/android/loganalysis/util/RegexTrieTest.java
+++ b/tests/src/com/android/loganalysis/util/RegexTrieTest.java
@@ -15,9 +15,18 @@
  */
 package com.android.loganalysis.util;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import com.android.loganalysis.util.RegexTrie.CompPattern;
 
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -25,25 +34,26 @@
 import java.util.List;
 import java.util.regex.Pattern;
 
-/**
- * Set of unit tests to verify the behavior of the RegexTrie
- */
-public class RegexTrieTest extends TestCase {
+/** Set of unit tests to verify the behavior of the RegexTrie */
+@RunWith(JUnit4.class)
+public class RegexTrieTest {
     private RegexTrie<Integer> mTrie = null;
     private static final Integer STORED_VAL = 42;
     private static final List<String> NULL_LIST = Arrays.asList((String)null);
 
-    @Override
+    @Before
     public void setUp() throws Exception {
         mTrie = new RegexTrie<Integer>();
     }
 
+    @Test
     public void testStringPattern() {
         mTrie.put(STORED_VAL, "[p]art1", "[p]art2", "[p]art3");
         Integer retrieved = mTrie.retrieve("part1", "part2", "part3");
         assertEquals(STORED_VAL, retrieved);
     }
 
+    @Test
     public void testAlternation_single() {
         mTrie.put(STORED_VAL, "alpha|beta");
         Integer retrieved;
@@ -59,6 +69,7 @@
         assertNull(retrieved);
     }
 
+    @Test
     public void testAlternation_multiple() {
         mTrie.put(STORED_VAL, "a|alpha", "b|beta");
         Integer retrieved;
@@ -79,6 +90,7 @@
         assertNull(retrieved);
     }
 
+    @Test
     public void testGroups_fullMatch() {
         mTrie.put(STORED_VAL, "a|(alpha)", "b|(beta)");
         Integer retrieved;
@@ -109,6 +121,7 @@
         assertEquals(Arrays.asList("beta"), groups.get(1));
     }
 
+    @Test
     public void testGroups_partialMatch() {
         mTrie.put(STORED_VAL, "a|(alpha)", "b|(beta)");
         Integer retrieved;
@@ -140,9 +153,8 @@
         assertEquals(Arrays.asList("beta"), groups.get(1));
     }
 
-    /**
-     * Make sure that the wildcard functionality works
-     */
+    /** Make sure that the wildcard functionality works */
+    @Test
     public void testWildcard() {
         mTrie.put(STORED_VAL, "a", null);
         Integer retrieved;
@@ -165,6 +177,7 @@
      * Make sure that if a wildcard and a more specific match could both match, that the more
      * specific match takes precedence
      */
+    @Test
     public void testWildcard_precedence() {
         // Do one before and one after the wildcard to check for ordering effects
         mTrie.put(STORED_VAL + 1, "a", "(b)");
@@ -196,6 +209,7 @@
      * Verify a bugfix: make sure that no NPE results from calling #retrieve with a wildcard but
      * without a place to retrieve captures.
      */
+    @Test
     public void testWildcard_noCapture() throws NullPointerException {
         mTrie.put(STORED_VAL, "a", null);
         String[] key = new String[] {"a", "b", "c"};
@@ -205,6 +219,7 @@
         // test passes if no exceptions were thrown
     }
 
+    @Test
     public void testMultiChild() {
         mTrie.put(STORED_VAL + 1, "a", "b");
         mTrie.put(STORED_VAL + 2, "a", "c");
@@ -217,8 +232,9 @@
     }
 
     /**
-     * Make sure that {@link CompPattern#equals} works as expected.  Shake a proverbial fist at Java
+     * Make sure that {@link CompPattern#equals} works as expected. Shake a proverbial fist at Java
      */
+    @Test
     public void testCompPattern_equality() {
         String regex = "regex";
         Pattern p1 = Pattern.compile(regex);
@@ -229,19 +245,20 @@
         CompPattern cpOther = new CompPattern(pOther);
 
         // This is the problem with Pattern as implemented
-        assertFalse(p1.equals(p2));
-        assertFalse(p2.equals(p1));
+        assertNotEquals(p1, p2);
+        assertNotEquals(p2, p1);
 
         // Make sure that wrapped patterns with the same regex are considered equivalent
-        assertTrue(cp2.equals(p1));
-        assertTrue(cp2.equals(p2));
-        assertTrue(cp2.equals(cp1));
+        assertEquals(cp2, p1);
+        assertEquals(cp2, p1);
+        assertEquals(cp2, cp1);
 
         // And make sure that wrapped patterns with different regexen are still considered different
-        assertFalse(cp2.equals(pOther));
-        assertFalse(cp2.equals(cpOther));
+        assertNotEquals(cp2, pOther);
+        assertNotEquals(cp2, cpOther);
     }
 
+    @Test
     public void testCompPattern_hashmap() {
         HashMap<CompPattern, Integer> map = new HashMap<CompPattern, Integer>();
         String regex = "regex";