CRAS: iodev_list - Enable/disable active node for pinned stream

When a pinned stream is connected, the active node on the iodev-
to-pin might not work properly due to it was left in disabled
state when user's last action was switching to the other iodev.
Fix this problem by calling update_active_node() when a pinned
stream connected and removed.

BUG=chromium:700247
TEST=Plug 3.5mm headphone and a USB headset, select to headphone
in UI tray and then select to USB headset as output.
Execute 'cras_test_client --pin_device <id-of-internal-card>' to
play something, and verify audio coming out from headphone.
Next, click on UI to select to internal speaker and then select to
USB headset as output. Execute cras_test_client --pin_device to
play something, verify audio coming out from internal speaker this
time.

Change-Id: I438fdfc591b52186ed5a5079f8d3125b47f3499a
Reviewed-on: https://chromium-review.googlesource.com/462736
Commit-Ready: Hsinyu Chao <hychao@chromium.org>
Tested-by: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: Chinyue Chen <chinyue@chromium.org>
diff --git a/cras/src/server/cras_iodev_list.c b/cras/src/server/cras_iodev_list.c
index 5eac3e6..b89767e 100644
--- a/cras/src/server/cras_iodev_list.c
+++ b/cras/src/server/cras_iodev_list.c
@@ -593,6 +593,28 @@
 				tm, INIT_DEV_DELAY_MS, init_device_cb, edev);
 }
 
+static int pinned_stream_added(struct cras_rstream *rstream)
+{
+	struct cras_iodev *dev;
+	int rc;
+
+	/* Check that the target device is valid for pinned streams. */
+	dev = find_dev(rstream->pinned_dev_idx);
+	if (!dev)
+		return -EINVAL;
+
+	/* Make sure the active node is configured properly, it could be
+	 * disabled when last normal stream removed. */
+	dev->update_active_node(dev, dev->active_node->idx, 1);
+
+	/* Negative EAGAIN code indicates dev will be opened later. */
+	rc = init_device(dev, rstream);
+	if (rc && (rc != -EAGAIN))
+		return rc;
+
+	return audio_thread_add_stream(audio_thread, rstream, &dev, 1);
+}
+
 static int stream_added_cb(struct cras_rstream *rstream)
 {
 	struct enabled_dev *edev;
@@ -603,20 +625,8 @@
 	if (stream_list_suspended)
 		return 0;
 
-	/* Check that the target device is valid for pinned streams. */
-	if (rstream->is_pinned) {
-		struct cras_iodev *dev;
-		dev = find_dev(rstream->pinned_dev_idx);
-		if (!dev)
-			return -EINVAL;
-
-		/* Negative EAGAIN code indicates dev will be opened later. */
-		rc = init_device(dev, rstream);
-		if (rc && (rc != -EAGAIN))
-			return rc;
-
-		return audio_thread_add_stream(audio_thread, rstream, &dev, 1);
-	}
+	if (rstream->is_pinned)
+		return pinned_stream_added(rstream);
 
 	/* Add the new stream to all enabled iodevs at once to avoid offset
 	 * in shm level between different ouput iodevs. */
@@ -697,8 +707,10 @@
 	struct cras_iodev *dev;
 
 	dev = find_dev(rstream->pinned_dev_idx);
-	if (!cras_iodev_list_dev_is_enabled(dev))
+	if (!cras_iodev_list_dev_is_enabled(dev)) {
 		close_dev(dev);
+		dev->update_active_node(dev, dev->active_node->idx, 0);
+	}
 }
 
 /* Returns the number of milliseconds left to drain this stream.  This is passed