[autotest] cras_utils: Add get_plugged_node_types

Refactor get_selected_node_types and add get_plugged_node_types method.

BUG=chromium:532713
TEST=not used yet

Change-Id: Ie8fff105d57704891673390ebd3196d672d3a580
Reviewed-on: https://chromium-review.googlesource.com/301340
Commit-Ready: Cheng-Yi Chiang <cychiang@chromium.org>
Tested-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Wai-Hong Tam <waihong@chromium.org>
diff --git a/client/cros/audio/cras_utils.py b/client/cros/audio/cras_utils.py
index b667bc2..57fe66b 100644
--- a/client/cros/audio/cras_utils.py
+++ b/client/cros/audio/cras_utils.py
@@ -274,18 +274,22 @@
 CRAS_NODE_TYPES = CRAS_OUTPUT_NODE_TYPES + CRAS_INPUT_NODE_TYPES
 
 
-def get_selected_node_types():
-    """Returns the pair of active output node types and input node types.
+def get_filtered_node_types(callback):
+    """Returns the pair of filtered output node types and input node types.
+
+    @param callback: A callback function which takes a node as input parameter
+                     and filter the node based on its return value.
 
     @returns: A tuple (output_node_types, input_node_types) where each
-              field is a list of selected node types defined in CRAS_NODE_TYPES.
+              field is a list of node types defined in CRAS_NODE_TYPES,
+              and their 'attribute_name' is True.
 
     """
     output_node_types = []
     input_node_types = []
     nodes = get_cras_nodes()
     for node in nodes:
-        if node['Active']:
+        if callback(node):
             node_type = str(node['Type'])
             if node_type not in CRAS_NODE_TYPES:
                 raise RuntimeError(
@@ -297,6 +301,50 @@
     return (output_node_types, input_node_types)
 
 
+def get_selected_node_types():
+    """Returns the pair of active output node types and input node types.
+
+    @returns: A tuple (output_node_types, input_node_types) where each
+              field is a list of selected node types defined in CRAS_NODE_TYPES.
+
+    """
+    def is_selected(node):
+        """Checks if a node is selected.
+
+        A node is selected if its Active attribute is True.
+
+        @returns: True is a node is selected, False otherwise.
+
+        """
+        return node['Active']
+
+    return get_filtered_node_types(is_selected)
+
+
+def get_plugged_node_types():
+    """Returns the pair of plugged output node types and input node types.
+
+    @returns: A tuple (output_node_types, input_node_types) where each
+              field is a list of plugged node types defined in CRAS_NODE_TYPES.
+
+    """
+    def is_plugged(node):
+        """Checks if a node is plugged and is not unknown node.
+
+        Cras DBus API only reports plugged node, so every node reported by Cras
+        DBus API is plugged. However, we filter out UNKNOWN node here because
+        the existence of unknown node depends on the number of redundant
+        playback/record audio device created on audio card. Also, the user of
+        Cras will ignore unknown nodes.
+
+        @returns: True if a node is plugged and is not an UNKNOWN node.
+
+        """
+        return node['Type'] != 'UNKNOWN'
+
+    return get_filtered_node_types(is_plugged)
+
+
 def set_selected_node_types(output_node_types, input_node_types):
     """Sets selected node types.