Rewrote the zombie metric to get serials.

Added ability to get the serial number of phone from pid, by parsing
output of ps, also simplified output dictionary.

Bug: None
Test: see tests/zombie_metric_test.py
Change-Id: Ibfc921c6e41dfa81593fa8a8bd4c79c3c5e232e5
diff --git a/tools/lab/metrics/zombie_metric.py b/tools/lab/metrics/zombie_metric.py
index 1eaad2f..6224c09 100644
--- a/tools/lab/metrics/zombie_metric.py
+++ b/tools/lab/metrics/zombie_metric.py
@@ -18,53 +18,38 @@
 
 
 class ZombieMetric(Metric):
-
-    COMMAND = "ps axo pid=,stat=,comm= | awk '$2~/^Z { print }'"
-    # Fields for response dictionary
-    ADB_ZOMBIES = 'adb_zombies'
-    FASTBOOT_ZOMBIES = 'fastboot_zombies'
-    OTHER_ZOMBIES = 'other_zombies'
+    COMMAND = 'ps -eo pid,stat,comm,args | awk \'$2~/^Z/ { print }\''
 
     def gather_metric(self):
-        """finds PIDs and command names for zombie processes
+        """Gathers the pids, process names, and serial numbers of processes.
+
+        If process does not have serial, None is returned instead.
 
         Returns:
-            A dict with the following fields:
-                adb_zombies: list of zombie processes w/ 'adb' in command name
-                fastboot_zombies: list of zombie processes w/ 'fastboot'
-                  in command name
-                other_zombies: list of zombie processes w/o 'adb'or 'fastboot
-                  in command name
-            all elements in list are formatted as (PID, state, name) tuples
+            A dictionary where the keys are the pids of the processes, and the
+            value is a tuple of (process name, serial number|None)
         """
-        # Initialize empty lists
-        adb_zombies, fastboot_zombies, other_zombies = [], [], []
-        # Run shell command
-        result = self._shell.run(self.COMMAND)
-        """Example stdout:
-        30797 Z+   adb <defunct>
-        30798 Z+   adb <defunct>
-        """
-        # Split output into lines
-        output = result.stdout.splitlines()
-        for ln in output:
-            # Get first two parts of output
-            pid, state = ln.split()[:2]
-            # Rest of line will be the command name, may have spaces
-            name = ' '.join(ln.split()[2:])
-            # Create zombie and append to proper list
-            zombie = (int(pid), state, name)
-            if 'adb' in name:
-                adb_zombies.append(zombie)
-            elif 'fastboot' in name:
-                fastboot_zombies.append(zombie)
-            else:
-                other_zombies.append(zombie)
+        response = {}
+        result = self._shell.run(self.COMMAND).stdout
+        # Example stdout:
+        # 30797 Z+   adb <defunct> adb -s AHDLSERIAL0001
+        # 30798 Z+   adb <defunct> /usr/bin/adb
 
-        # Create response dictionary
-        response = {
-            self.ADB_ZOMBIES: adb_zombies,
-            self.FASTBOOT_ZOMBIES: fastboot_zombies,
-            self.OTHER_ZOMBIES: other_zombies
-        }
+        output = result.splitlines()
+        for ln in output:
+            spl_ln = ln.split()
+            # spl_ln looks like ['1xx', 'Z+', 'adb', '<defunct'>, ...]
+            pid, state, name = spl_ln[:3]
+
+            if '-s' in spl_ln:
+                # Finds the '-s' flag, the index after that is the serial.
+                sn_idx = spl_ln.index('-s')
+                if sn_idx + 1 >= len(spl_ln):
+                    sn = None
+                else:
+                    sn = spl_ln[sn_idx + 1]
+                response[pid] = (name, sn)
+            else:
+                response[pid] = (name, None)
+
         return response
diff --git a/tools/lab/tests/zombie_metric_test.py b/tools/lab/tests/zombie_metric_test.py
index 185effe..4395c55 100755
--- a/tools/lab/tests/zombie_metric_test.py
+++ b/tools/lab/tests/zombie_metric_test.py
@@ -23,35 +23,45 @@
 class ZombieMetricTest(unittest.TestCase):
     """Class for testing ZombieMetric."""
 
-    def test_return_one_process(self):
+    def test_gather_metric_oob(self):
+        stdout_string = '30888 Z+ adb -s'
+        FAKE_RESULT = fake.FakeResult(stdout=stdout_string)
+        fake_shell = fake.MockShellCommand(fake_result=FAKE_RESULT)
+        metric_obj = zombie_metric.ZombieMetric(shell=fake_shell)
+
+        expected_result = {'30888': ('adb', None)}
+        self.assertEqual(expected_result, metric_obj.gather_metric())
+
+    def test_gather_metric_no_serial(self):
         stdout_string = '30888 Z+ adb <defunct>'
         FAKE_RESULT = fake.FakeResult(stdout=stdout_string)
         fake_shell = fake.MockShellCommand(fake_result=FAKE_RESULT)
         metric_obj = zombie_metric.ZombieMetric(shell=fake_shell)
 
-        expected_result = {
-            zombie_metric.ZombieMetric.ADB_ZOMBIES: [(30888, 'Z+',
-                                                      'adb <defunct>')],
-            zombie_metric.ZombieMetric.FASTBOOT_ZOMBIES: [],
-            zombie_metric.ZombieMetric.OTHER_ZOMBIES: []
-        }
+        expected_result = {'30888': ('adb', None)}
         self.assertEqual(expected_result, metric_obj.gather_metric())
 
-    def test_return_one_of_each(self):
-        stdout_string = ('30888 Z+ adb <defunct>\n'
-                         '12345 Z+ fastboot\n'
-                         '99999 Z+ random\n')
+    def test_gather_metric_with_serial(self):
+        stdout_string = ('12345 Z+ fastboot -s M4RKY_M4RK\n'
+                         '99999 Z+ adb -s OR3G4N0\n')
         FAKE_RESULT = fake.FakeResult(stdout=stdout_string)
         fake_shell = fake.MockShellCommand(fake_result=FAKE_RESULT)
         metric_obj = zombie_metric.ZombieMetric(shell=fake_shell)
 
         expected_result = {
-            zombie_metric.ZombieMetric.ADB_ZOMBIES: [(30888, 'Z+',
-                                                      'adb <defunct>')],
-            zombie_metric.ZombieMetric.FASTBOOT_ZOMBIES: [(12345, 'Z+',
-                                                           'fastboot')],
-            zombie_metric.ZombieMetric.OTHER_ZOMBIES: [(99999, 'Z+', 'random')]
+            '12345': ('fastboot', 'M4RKY_M4RK'),
+            '99999': ('adb', 'OR3G4N0')
         }
+        self.assertEquals(metric_obj.gather_metric(), expected_result)
+
+    def test_gather_metric_adb_fastboot_no_s(self):
+        stdout_string = ('12345 Z+ fastboot\n' '99999 Z+ adb\n')
+        FAKE_RESULT = fake.FakeResult(stdout=stdout_string)
+        fake_shell = fake.MockShellCommand(fake_result=FAKE_RESULT)
+        metric_obj = zombie_metric.ZombieMetric(shell=fake_shell)
+
+        expected_result = {'12345': ('fastboot', None), '99999': ('adb', None)}
+        self.assertEquals(metric_obj.gather_metric(), expected_result)
 
 
 if __name__ == '__main__':