Generate a kernel reset event if reboot reson could not be determined.

BUG: 19963847
Change-Id: I9e380ecba32313e1f423b5af192acf0010487730
diff --git a/src/com/android/loganalysis/parser/KernelLogParser.java b/src/com/android/loganalysis/parser/KernelLogParser.java
index 741c261..b4b3b21 100644
--- a/src/com/android/loganalysis/parser/KernelLogParser.java
+++ b/src/com/android/loganalysis/parser/KernelLogParser.java
@@ -34,6 +34,7 @@
     public static final String KERNEL_RESET = "KERNEL_RESET";
     public static final String KERNEL_ERROR = "KERNEL_ERROR";
     public static final String SELINUX_DENIAL = "SELINUX_DENIAL";
+    public static final String NORMAL_REBOOT = "NORMAL_REBOOT";
 
     /**
      * Matches: [     0.000000] Message<br />
@@ -57,6 +58,7 @@
 
     private LogPatternUtil mPatternUtil = new LogPatternUtil();
     private LogTailUtil mPreambleUtil = new LogTailUtil(500, 50, 50);
+    private boolean mRebootReasonFound = false;
 
     public KernelLogParser() {
         initPatterns();
@@ -85,6 +87,7 @@
      */
     @Override
     public KernelLogItem parse(List<String> lines) {
+        mRebootReasonFound = false;
         for (String line : lines) {
             parseLine(line);
         }
@@ -132,6 +135,14 @@
             return;
         }
 
+        if (category.equals(KERNEL_RESET) || category.equals(NORMAL_REBOOT)) {
+            mRebootReasonFound = true;
+        }
+
+        if (category.equals(NORMAL_REBOOT)) {
+            return;
+        }
+
         MiscKernelLogItem kernelLogItem;
         if (category.equals(SELINUX_DENIAL)) {
             SELinuxItem selinuxItem = new SELinuxItem();
@@ -159,6 +170,14 @@
         }
         mKernelLog.setStartTime(mStartTime);
         mKernelLog.setStopTime(mStopTime);
+
+        if (!mRebootReasonFound) {
+            MiscKernelLogItem unknownReset = new MiscKernelLogItem();
+            unknownReset.setEventTime(mStopTime);
+            unknownReset.setPreamble(mPreambleUtil.getLastTail());
+            unknownReset.setCategory(KERNEL_RESET);
+            mKernelLog.addEvent(unknownReset);
+        }
     }
 
     private void initPatterns() {
@@ -181,9 +200,17 @@
             "Last boot reason: " + BAD_BOOTREASONS,
             "Last reset was system watchdog timer reset.*",
         };
+        final String[] goodSignatures = {
+                "Restarting system.*",
+                "Power down.*",
+                "Last boot reason: (?:PowerKey|normal|recovery|reboot)",
+        };
         for (String pattern : kernelResets) {
             mPatternUtil.addPattern(Pattern.compile(pattern), KERNEL_RESET);
         }
+        for (String pattern : goodSignatures) {
+            mPatternUtil.addPattern(Pattern.compile(pattern), NORMAL_REBOOT);
+        }
 
         mPatternUtil.addPattern(Pattern.compile("Internal error:.*"), KERNEL_ERROR);
 
diff --git a/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java b/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
index 890a196..0f554ec 100644
--- a/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
@@ -96,6 +96,40 @@
     }
 
     /**
+     * Test that unknown last boot reasons are parsed.
+     */
+    public void testParseUnknownLastMessage() {
+        List<String> lines = Arrays.asList(
+                "[    0.000000] Start",
+                "[    2.000000] End",
+                "Last boot reason: unknown failure");
+
+        KernelLogItem kernelLog = new KernelLogParser().parse(lines);
+        assertNotNull(kernelLog);
+        assertEquals(0.0, kernelLog.getStartTime(), 0.0000005);
+        assertEquals(2.0, kernelLog.getStopTime(), 0.0000005);
+        assertEquals(1, kernelLog.getEvents().size());
+        assertEquals(1, kernelLog.getMiscEvents(KernelLogParser.KERNEL_RESET).size());
+
+        MiscKernelLogItem item = kernelLog.getMiscEvents(KernelLogParser.KERNEL_RESET).get(0);
+        assertEquals(2.0, item.getEventTime(), 0.0000005);
+        assertEquals("[    0.000000] Start\n[    2.000000] End", item.getPreamble());
+    }
+
+    public void testParseKnownGoodLastMessage() {
+        List<String> lines = Arrays.asList(
+                "[    0.000000] Start",
+                "[    2.000000] End",
+                "Last boot reason: reboot");
+
+        KernelLogItem kernelLog = new KernelLogParser().parse(lines);
+        assertNotNull(kernelLog);
+        assertEquals(0.0, kernelLog.getStartTime(), 0.0000005);
+        assertEquals(2.0, kernelLog.getStopTime(), 0.0000005);
+        assertEquals(0, kernelLog.getEvents().size());
+    }
+
+    /**
      * Test that reset reasons don't crash if times are set.
      */
     public void testNoPreviousLogs() {
@@ -183,7 +217,7 @@
         assertNotNull(kernelLog);
         assertEquals(0.0, kernelLog.getStartTime(), 0.0000005);
         assertEquals(43.399164, kernelLog.getStopTime(), 0.0000005);
-        assertEquals(1, kernelLog.getEvents().size());
+        assertEquals(2, kernelLog.getEvents().size());
         assertEquals(1, kernelLog.getMiscEvents(KernelLogParser.SELINUX_DENIAL).size());
         assertEquals(1, kernelLog.getSELinuxEvents().size());