[devmgr] Make virtcon_open private to Coordinator

Encapsulate the virtcon channel that is used to open new virtual
consoles within the Coordinator.

Test: Ran Fuchsia and /system/test/ddk tests.
Change-Id: I750a4e1945ebadb78ba73f1d8f233f8075d342d6
diff --git a/system/core/devmgr/devmgr/coordinator.cpp b/system/core/devmgr/devmgr/coordinator.cpp
index 3ea0ddf..b974cb8 100644
--- a/system/core/devmgr/devmgr/coordinator.cpp
+++ b/system/core/devmgr/devmgr/coordinator.cpp
@@ -154,6 +154,11 @@
     return ZX_OK;
 }
 
+zx_status_t Coordinator::OpenVirtcon(zx::channel virtcon_receiver) const {
+    zx_handle_t raw_virtcon_receiver = virtcon_receiver.release();
+    return virtcon_channel_.write(0, nullptr, 0, &raw_virtcon_receiver, 1);
+}
+
 void Coordinator::DmPrintf(const char* fmt, ...) const {
     if (!dmctl_socket_.is_valid()) {
         return;
@@ -1253,11 +1258,8 @@
 }
 
 static zx_status_t fidl_DmOpenVirtcon(void* ctx, zx_handle_t raw_vc_receiver) {
-    zx::channel vc_receiver(raw_vc_receiver);
-
-    zx_handle_t h = vc_receiver.release();
-    zx_channel_write(virtcon_open, 0, nullptr, 0, &h, 1);
-    return ZX_OK;
+    auto dev = static_cast<Device*>(ctx);
+    return dev->coordinator->OpenVirtcon(zx::channel(raw_vc_receiver));
 }
 
 static zx_status_t fidl_DmMexec(void* ctx, zx_handle_t raw_kernel, zx_handle_t raw_bootdata) {
diff --git a/system/core/devmgr/devmgr/coordinator.h b/system/core/devmgr/devmgr/coordinator.h
index 958e44a..d9783ce 100644
--- a/system/core/devmgr/devmgr/coordinator.h
+++ b/system/core/devmgr/devmgr/coordinator.h
@@ -292,6 +292,8 @@
 
     zx_status_t InitializeCoreDevices();
 
+    zx_status_t OpenVirtcon(zx::channel virtcon_receiver) const;
+
     void DmPrintf(const char* fmt, ...) const;
     zx_status_t HandleDmctlWrite(size_t len, const char* cmd);
 
@@ -363,6 +365,9 @@
     void set_loader_service(DevhostLoaderService* loader_service) {
         loader_service_ = loader_service;
     }
+    void set_virtcon_channel(zx::channel virtcon_channel) {
+        virtcon_channel_ = std::move(virtcon_channel);
+    }
     void set_dmctl_socket(zx::socket dmctl_socket) { dmctl_socket_ = std::move(dmctl_socket); }
 
     fbl::DoublyLinkedList<Device*, Device::AllDevicesNode>& devices() { return devices_; }
@@ -386,6 +391,9 @@
     bool running_ = false;
     bool launched_first_devhost_ = false;
     DevhostLoaderService* loader_service_ = nullptr;
+
+    // Channel for creating new virtual consoles.
+    zx::channel virtcon_channel_;
     // This socket is used by DmPrintf for output, and DmPrintf can be called in
     // the context of a const member function, therefore it is also const. Given
     // that, we must make dmctl_socket_ mutable.
diff --git a/system/core/devmgr/devmgr/devmgr.h b/system/core/devmgr/devmgr/devmgr.h
index 9eb1ac4..54fef05 100644
--- a/system/core/devmgr/devmgr/devmgr.h
+++ b/system/core/devmgr/devmgr/devmgr.h
@@ -14,8 +14,6 @@
 struct Device;
 struct Devnode;
 
-extern zx_handle_t virtcon_open;
-
 // Initializes a devfs directory from |device|.
 void devfs_init(Device* device, async_dispatcher_t* dispatcher);
 
diff --git a/system/core/devmgr/devmgr/main.cpp b/system/core/devmgr/devmgr/main.cpp
index 07d6b3b..11e5f12 100644
--- a/system/core/devmgr/devmgr/main.cpp
+++ b/system/core/devmgr/devmgr/main.cpp
@@ -621,18 +621,23 @@
         envp[envc] = nullptr;
 
         const char* num_shells = coordinator->require_system() && !netboot ? "0" : "3";
-
         size_t handle_count = 0;
+        zx_handle_t handles[2];
         uint32_t types[2];
-        zx_handle_t handles[2] = {ZX_HANDLE_INVALID, ZX_HANDLE_INVALID};
 
-        if (zx_channel_create(0, &handles[0], &devmgr::virtcon_open) == ZX_OK) {
-            types[handle_count++] = PA_HND(PA_USER0, 0);
+        zx::channel virtcon_client, virtcon_server;
+        zx_status_t status = zx::channel::create(0, &virtcon_client, &virtcon_server);
+        if (status == ZX_OK) {
+            coordinator->set_virtcon_channel(std::move(virtcon_client));
+            handles[handle_count] = virtcon_server.release();
+            types[handle_count] = PA_HND(PA_USER0, 0);
+            ++handle_count;
         }
 
         zx::debuglog debuglog;
-        if (zx::debuglog::create(coordinator->root_resource(), ZX_LOG_FLAG_READABLE, &debuglog) ==
-            ZX_OK) {
+        status = zx::debuglog::create(coordinator->root_resource(), ZX_LOG_FLAG_READABLE,
+                                      &debuglog);
+        if (status == ZX_OK) {
             handles[handle_count] = debuglog.release();
             types[handle_count] = PA_HND(PA_USER0, 1);
             ++handle_count;
@@ -742,8 +747,6 @@
 
 namespace devmgr {
 
-zx_handle_t virtcon_open;
-
 zx::channel fs_clone(const char* path) {
     if (!strcmp(path, "dev")) {
         return devfs_root_clone();